PageRenderTime 77ms CodeModel.GetById 32ms RepoModel.GetById 1ms app.codeStats 0ms

/chromium/third_party/WebKit/Source/web/AutofillPopupMenuClient.cpp

https://gitlab.com/f3822/qtwebengine-chromium
C++ | 348 lines | 256 code | 52 blank | 40 comment | 31 complexity | c816d822c87667b0595edfc6407ce67c MD5 | raw file
  1. /*
  2. * Copyright (C) 2011 Google Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are
  6. * met:
  7. *
  8. * * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * * Redistributions in binary form must reproduce the above
  11. * copyright notice, this list of conditions and the following disclaimer
  12. * in the documentation and/or other materials provided with the
  13. * distribution.
  14. * * Neither the name of Google Inc. nor the names of its
  15. * contributors may be used to endorse or promote products derived from
  16. * this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. #include "config.h"
  31. #include "AutofillPopupMenuClient.h"
  32. #include "CSSValueKeywords.h"
  33. #include "WebAutofillClient.h"
  34. #include "WebNode.h"
  35. #include "WebViewClient.h"
  36. #include "WebViewImpl.h"
  37. #include "core/css/CSSFontSelector.h"
  38. #include "core/css/resolver/StyleResolver.h"
  39. #include "core/html/HTMLInputElement.h"
  40. #include "core/frame/Frame.h"
  41. #include "core/frame/FrameView.h"
  42. #include "core/rendering/RenderTheme.h"
  43. #include "public/platform/WebString.h"
  44. #include "public/platform/WebVector.h"
  45. using namespace WebCore;
  46. namespace blink {
  47. AutofillPopupMenuClient::AutofillPopupMenuClient()
  48. : m_selectedIndex(-1)
  49. , m_textField(0)
  50. , m_useLegacyBehavior(false)
  51. {
  52. }
  53. AutofillPopupMenuClient::~AutofillPopupMenuClient()
  54. {
  55. }
  56. unsigned AutofillPopupMenuClient::getSuggestionsCount() const
  57. {
  58. return m_names.size();
  59. }
  60. WebString AutofillPopupMenuClient::getSuggestion(unsigned listIndex) const
  61. {
  62. ASSERT_WITH_SECURITY_IMPLICATION(listIndex < m_names.size());
  63. return m_names[listIndex];
  64. }
  65. WebString AutofillPopupMenuClient::getLabel(unsigned listIndex) const
  66. {
  67. ASSERT_WITH_SECURITY_IMPLICATION(listIndex < m_labels.size());
  68. return m_labels[listIndex];
  69. }
  70. WebString AutofillPopupMenuClient::getIcon(unsigned listIndex) const
  71. {
  72. ASSERT_WITH_SECURITY_IMPLICATION(listIndex < m_icons.size());
  73. return m_icons[listIndex];
  74. }
  75. void AutofillPopupMenuClient::removeSuggestionAtIndex(unsigned listIndex)
  76. {
  77. if (!canRemoveSuggestionAtIndex(listIndex))
  78. return;
  79. ASSERT_WITH_SECURITY_IMPLICATION(listIndex < m_names.size());
  80. m_names.remove(listIndex);
  81. m_labels.remove(listIndex);
  82. m_icons.remove(listIndex);
  83. m_itemIDs.remove(listIndex);
  84. }
  85. bool AutofillPopupMenuClient::canRemoveSuggestionAtIndex(unsigned listIndex)
  86. {
  87. return m_itemIDs[listIndex] == WebAutofillClient::MenuItemIDAutocompleteEntry || m_itemIDs[listIndex] == WebAutofillClient::MenuItemIDPasswordEntry;
  88. }
  89. void AutofillPopupMenuClient::valueChanged(unsigned listIndex, bool fireEvents)
  90. {
  91. WebViewImpl* webView = getWebView();
  92. if (!webView)
  93. return;
  94. ASSERT_WITH_SECURITY_IMPLICATION(listIndex < m_names.size());
  95. if (m_useLegacyBehavior) {
  96. for (size_t i = 0; i < m_itemIDs.size(); ++i) {
  97. if (m_itemIDs[i] == WebAutofillClient::MenuItemIDSeparator) {
  98. if (listIndex > i)
  99. listIndex--;
  100. break;
  101. }
  102. }
  103. }
  104. webView->autofillClient()->didAcceptAutofillSuggestion(WebNode(getTextField()),
  105. m_names[listIndex],
  106. m_labels[listIndex],
  107. m_itemIDs[listIndex],
  108. listIndex);
  109. }
  110. void AutofillPopupMenuClient::selectionChanged(unsigned listIndex, bool fireEvents)
  111. {
  112. WebViewImpl* webView = getWebView();
  113. if (!webView)
  114. return;
  115. ASSERT_WITH_SECURITY_IMPLICATION(listIndex < m_names.size());
  116. webView->autofillClient()->didSelectAutofillSuggestion(WebNode(getTextField()),
  117. m_names[listIndex],
  118. m_labels[listIndex],
  119. m_itemIDs[listIndex]);
  120. }
  121. void AutofillPopupMenuClient::selectionCleared()
  122. {
  123. WebViewImpl* webView = getWebView();
  124. if (webView)
  125. webView->autofillClient()->didClearAutofillSelection(WebNode(getTextField()));
  126. }
  127. String AutofillPopupMenuClient::itemText(unsigned listIndex) const
  128. {
  129. return getSuggestion(listIndex);
  130. }
  131. String AutofillPopupMenuClient::itemLabel(unsigned listIndex) const
  132. {
  133. return getLabel(listIndex);
  134. }
  135. String AutofillPopupMenuClient::itemIcon(unsigned listIndex) const
  136. {
  137. return getIcon(listIndex);
  138. }
  139. bool AutofillPopupMenuClient::itemIsEnabled(unsigned listIndex) const
  140. {
  141. return !itemIsWarning(listIndex);
  142. }
  143. PopupMenuStyle AutofillPopupMenuClient::itemStyle(unsigned listIndex) const
  144. {
  145. return itemIsWarning(listIndex) ? *m_warningStyle : *m_regularStyle;
  146. }
  147. PopupMenuStyle AutofillPopupMenuClient::menuStyle() const
  148. {
  149. return *m_regularStyle;
  150. }
  151. WebCore::LayoutUnit AutofillPopupMenuClient::clientPaddingLeft() const
  152. {
  153. // Bug http://crbug.com/7708 seems to indicate the style can be 0.
  154. RenderStyle* style = textFieldStyle();
  155. if (!style)
  156. return 0;
  157. return RenderTheme::theme().popupInternalPaddingLeft(style);
  158. }
  159. WebCore::LayoutUnit AutofillPopupMenuClient::clientPaddingRight() const
  160. {
  161. // Bug http://crbug.com/7708 seems to indicate the style can be 0.
  162. RenderStyle* style = textFieldStyle();
  163. if (!style)
  164. return 0;
  165. return RenderTheme::theme().popupInternalPaddingRight(style);
  166. }
  167. void AutofillPopupMenuClient::popupDidHide()
  168. {
  169. WebViewImpl* webView = getWebView();
  170. if (!webView)
  171. return;
  172. webView->autofillPopupDidHide();
  173. webView->autofillClient()->didClearAutofillSelection(WebNode(getTextField()));
  174. }
  175. bool AutofillPopupMenuClient::itemIsSeparator(unsigned listIndex) const
  176. {
  177. return m_itemIDs[listIndex] == WebAutofillClient::MenuItemIDSeparator;
  178. }
  179. bool AutofillPopupMenuClient::itemIsWarning(unsigned listIndex) const
  180. {
  181. return m_itemIDs[listIndex] == WebAutofillClient::MenuItemIDWarningMessage;
  182. }
  183. void AutofillPopupMenuClient::setTextFromItem(unsigned listIndex)
  184. {
  185. m_textField->setValue(getSuggestion(listIndex));
  186. }
  187. FontSelector* AutofillPopupMenuClient::fontSelector() const
  188. {
  189. return m_textField->document().styleEngine()->fontSelector();
  190. }
  191. HostWindow* AutofillPopupMenuClient::hostWindow() const
  192. {
  193. return m_textField->document().view()->hostWindow();
  194. }
  195. PassRefPtr<Scrollbar> AutofillPopupMenuClient::createScrollbar(
  196. ScrollableArea* scrollableArea,
  197. ScrollbarOrientation orientation,
  198. ScrollbarControlSize size)
  199. {
  200. return Scrollbar::create(scrollableArea, orientation, size);
  201. }
  202. void AutofillPopupMenuClient::initialize(
  203. HTMLInputElement* textField,
  204. const WebVector<WebString>& names,
  205. const WebVector<WebString>& labels,
  206. const WebVector<WebString>& icons,
  207. const WebVector<int>& itemIDs,
  208. int separatorIndex)
  209. {
  210. ASSERT(names.size() == labels.size());
  211. ASSERT(names.size() == icons.size());
  212. ASSERT(names.size() == itemIDs.size());
  213. m_selectedIndex = -1;
  214. m_textField = textField;
  215. if (separatorIndex == -1) {
  216. // The suggestions must be set before initializing the
  217. // AutofillPopupMenuClient.
  218. setSuggestions(names, labels, icons, itemIDs);
  219. } else {
  220. m_useLegacyBehavior = true;
  221. WebVector<WebString> namesWithSeparator(names.size() + 1);
  222. WebVector<WebString> labelsWithSeparator(labels.size() + 1);
  223. WebVector<WebString> iconsWithSeparator(icons.size() + 1);
  224. WebVector<int> itemIDsWithSeparator(itemIDs.size() + 1);
  225. for (size_t i = 0; i < names.size(); ++i) {
  226. size_t j = i < static_cast<size_t>(separatorIndex) ? i : i + 1;
  227. namesWithSeparator[j] = names[i];
  228. labelsWithSeparator[j] = labels[i];
  229. iconsWithSeparator[j] = icons[i];
  230. itemIDsWithSeparator[j] = itemIDs[i];
  231. }
  232. itemIDsWithSeparator[separatorIndex] = WebAutofillClient::MenuItemIDSeparator;
  233. setSuggestions(namesWithSeparator, labelsWithSeparator, iconsWithSeparator, itemIDsWithSeparator);
  234. }
  235. FontDescription regularFontDescription;
  236. RenderTheme::theme().systemFont(CSSValueWebkitControl,
  237. regularFontDescription);
  238. RenderStyle* style = m_textField->computedStyle();
  239. regularFontDescription.setComputedSize(style->fontDescription().computedSize());
  240. Font regularFont(regularFontDescription, 0, 0);
  241. regularFont.update(textField->document().styleEngine()->fontSelector());
  242. // The direction of text in popup menu is set the same as the direction of
  243. // the input element: textField.
  244. m_regularStyle = adoptPtr(new PopupMenuStyle(Color::black, Color::white, regularFont, true, false,
  245. Length(WebCore::Fixed), textField->renderer()->style()->direction(),
  246. textField->renderer()->style()->unicodeBidi() == Override,
  247. PopupMenuStyle::CustomBackgroundColor, PopupMenuStyle::AutofillPopup));
  248. FontDescription warningFontDescription = regularFont.fontDescription();
  249. warningFontDescription.setItalic(true);
  250. Font warningFont(warningFontDescription, regularFont.letterSpacing(), regularFont.wordSpacing());
  251. warningFont.update(regularFont.fontSelector());
  252. m_warningStyle = adoptPtr(new PopupMenuStyle(Color::darkGray, m_regularStyle->backgroundColor(), warningFont,
  253. m_regularStyle->isVisible(), m_regularStyle->isDisplayNone(),
  254. m_regularStyle->textIndent(), m_regularStyle->textDirection(),
  255. m_regularStyle->hasTextDirectionOverride(),
  256. PopupMenuStyle::CustomBackgroundColor, PopupMenuStyle::AutofillPopup));
  257. }
  258. void AutofillPopupMenuClient::setSuggestions(const WebVector<WebString>& names,
  259. const WebVector<WebString>& labels,
  260. const WebVector<WebString>& icons,
  261. const WebVector<int>& itemIDs)
  262. {
  263. ASSERT(names.size() == labels.size());
  264. ASSERT(names.size() == icons.size());
  265. ASSERT(names.size() == itemIDs.size());
  266. m_names.clear();
  267. m_labels.clear();
  268. m_icons.clear();
  269. m_itemIDs.clear();
  270. for (size_t i = 0; i < names.size(); ++i) {
  271. m_names.append(names[i]);
  272. m_labels.append(labels[i]);
  273. m_icons.append(icons[i]);
  274. m_itemIDs.append(itemIDs[i]);
  275. }
  276. // Try to preserve selection if possible.
  277. if (getSelectedIndex() >= static_cast<int>(names.size()))
  278. setSelectedIndex(-1);
  279. }
  280. WebViewImpl* AutofillPopupMenuClient::getWebView() const
  281. {
  282. return WebViewImpl::fromPage(m_textField->document().page());
  283. }
  284. RenderStyle* AutofillPopupMenuClient::textFieldStyle() const
  285. {
  286. RenderStyle* style = m_textField->computedStyle();
  287. if (!style) {
  288. // It seems we can only have a 0 style in a TextField if the
  289. // node is detached, in which case we the popup should not be
  290. // showing. Please report this in http://crbug.com/7708 and
  291. // include the page you were visiting.
  292. ASSERT_NOT_REACHED();
  293. }
  294. return style;
  295. }
  296. } // namespace blink