/chromium/third_party/WebKit/Source/web/AutofillPopupMenuClient.cpp
C++ | 348 lines | 256 code | 52 blank | 40 comment | 31 complexity | c816d822c87667b0595edfc6407ce67c MD5 | raw file
- /*
- * Copyright (C) 2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include "config.h"
- #include "AutofillPopupMenuClient.h"
- #include "CSSValueKeywords.h"
- #include "WebAutofillClient.h"
- #include "WebNode.h"
- #include "WebViewClient.h"
- #include "WebViewImpl.h"
- #include "core/css/CSSFontSelector.h"
- #include "core/css/resolver/StyleResolver.h"
- #include "core/html/HTMLInputElement.h"
- #include "core/frame/Frame.h"
- #include "core/frame/FrameView.h"
- #include "core/rendering/RenderTheme.h"
- #include "public/platform/WebString.h"
- #include "public/platform/WebVector.h"
- using namespace WebCore;
- namespace blink {
- AutofillPopupMenuClient::AutofillPopupMenuClient()
- : m_selectedIndex(-1)
- , m_textField(0)
- , m_useLegacyBehavior(false)
- {
- }
- AutofillPopupMenuClient::~AutofillPopupMenuClient()
- {
- }
- unsigned AutofillPopupMenuClient::getSuggestionsCount() const
- {
- return m_names.size();
- }
- WebString AutofillPopupMenuClient::getSuggestion(unsigned listIndex) const
- {
- ASSERT_WITH_SECURITY_IMPLICATION(listIndex < m_names.size());
- return m_names[listIndex];
- }
- WebString AutofillPopupMenuClient::getLabel(unsigned listIndex) const
- {
- ASSERT_WITH_SECURITY_IMPLICATION(listIndex < m_labels.size());
- return m_labels[listIndex];
- }
- WebString AutofillPopupMenuClient::getIcon(unsigned listIndex) const
- {
- ASSERT_WITH_SECURITY_IMPLICATION(listIndex < m_icons.size());
- return m_icons[listIndex];
- }
- void AutofillPopupMenuClient::removeSuggestionAtIndex(unsigned listIndex)
- {
- if (!canRemoveSuggestionAtIndex(listIndex))
- return;
- ASSERT_WITH_SECURITY_IMPLICATION(listIndex < m_names.size());
- m_names.remove(listIndex);
- m_labels.remove(listIndex);
- m_icons.remove(listIndex);
- m_itemIDs.remove(listIndex);
- }
- bool AutofillPopupMenuClient::canRemoveSuggestionAtIndex(unsigned listIndex)
- {
- return m_itemIDs[listIndex] == WebAutofillClient::MenuItemIDAutocompleteEntry || m_itemIDs[listIndex] == WebAutofillClient::MenuItemIDPasswordEntry;
- }
- void AutofillPopupMenuClient::valueChanged(unsigned listIndex, bool fireEvents)
- {
- WebViewImpl* webView = getWebView();
- if (!webView)
- return;
- ASSERT_WITH_SECURITY_IMPLICATION(listIndex < m_names.size());
- if (m_useLegacyBehavior) {
- for (size_t i = 0; i < m_itemIDs.size(); ++i) {
- if (m_itemIDs[i] == WebAutofillClient::MenuItemIDSeparator) {
- if (listIndex > i)
- listIndex--;
- break;
- }
- }
- }
- webView->autofillClient()->didAcceptAutofillSuggestion(WebNode(getTextField()),
- m_names[listIndex],
- m_labels[listIndex],
- m_itemIDs[listIndex],
- listIndex);
- }
- void AutofillPopupMenuClient::selectionChanged(unsigned listIndex, bool fireEvents)
- {
- WebViewImpl* webView = getWebView();
- if (!webView)
- return;
- ASSERT_WITH_SECURITY_IMPLICATION(listIndex < m_names.size());
- webView->autofillClient()->didSelectAutofillSuggestion(WebNode(getTextField()),
- m_names[listIndex],
- m_labels[listIndex],
- m_itemIDs[listIndex]);
- }
- void AutofillPopupMenuClient::selectionCleared()
- {
- WebViewImpl* webView = getWebView();
- if (webView)
- webView->autofillClient()->didClearAutofillSelection(WebNode(getTextField()));
- }
- String AutofillPopupMenuClient::itemText(unsigned listIndex) const
- {
- return getSuggestion(listIndex);
- }
- String AutofillPopupMenuClient::itemLabel(unsigned listIndex) const
- {
- return getLabel(listIndex);
- }
- String AutofillPopupMenuClient::itemIcon(unsigned listIndex) const
- {
- return getIcon(listIndex);
- }
- bool AutofillPopupMenuClient::itemIsEnabled(unsigned listIndex) const
- {
- return !itemIsWarning(listIndex);
- }
- PopupMenuStyle AutofillPopupMenuClient::itemStyle(unsigned listIndex) const
- {
- return itemIsWarning(listIndex) ? *m_warningStyle : *m_regularStyle;
- }
- PopupMenuStyle AutofillPopupMenuClient::menuStyle() const
- {
- return *m_regularStyle;
- }
- WebCore::LayoutUnit AutofillPopupMenuClient::clientPaddingLeft() const
- {
- // Bug http://crbug.com/7708 seems to indicate the style can be 0.
- RenderStyle* style = textFieldStyle();
- if (!style)
- return 0;
- return RenderTheme::theme().popupInternalPaddingLeft(style);
- }
- WebCore::LayoutUnit AutofillPopupMenuClient::clientPaddingRight() const
- {
- // Bug http://crbug.com/7708 seems to indicate the style can be 0.
- RenderStyle* style = textFieldStyle();
- if (!style)
- return 0;
- return RenderTheme::theme().popupInternalPaddingRight(style);
- }
- void AutofillPopupMenuClient::popupDidHide()
- {
- WebViewImpl* webView = getWebView();
- if (!webView)
- return;
- webView->autofillPopupDidHide();
- webView->autofillClient()->didClearAutofillSelection(WebNode(getTextField()));
- }
- bool AutofillPopupMenuClient::itemIsSeparator(unsigned listIndex) const
- {
- return m_itemIDs[listIndex] == WebAutofillClient::MenuItemIDSeparator;
- }
- bool AutofillPopupMenuClient::itemIsWarning(unsigned listIndex) const
- {
- return m_itemIDs[listIndex] == WebAutofillClient::MenuItemIDWarningMessage;
- }
- void AutofillPopupMenuClient::setTextFromItem(unsigned listIndex)
- {
- m_textField->setValue(getSuggestion(listIndex));
- }
- FontSelector* AutofillPopupMenuClient::fontSelector() const
- {
- return m_textField->document().styleEngine()->fontSelector();
- }
- HostWindow* AutofillPopupMenuClient::hostWindow() const
- {
- return m_textField->document().view()->hostWindow();
- }
- PassRefPtr<Scrollbar> AutofillPopupMenuClient::createScrollbar(
- ScrollableArea* scrollableArea,
- ScrollbarOrientation orientation,
- ScrollbarControlSize size)
- {
- return Scrollbar::create(scrollableArea, orientation, size);
- }
- void AutofillPopupMenuClient::initialize(
- HTMLInputElement* textField,
- const WebVector<WebString>& names,
- const WebVector<WebString>& labels,
- const WebVector<WebString>& icons,
- const WebVector<int>& itemIDs,
- int separatorIndex)
- {
- ASSERT(names.size() == labels.size());
- ASSERT(names.size() == icons.size());
- ASSERT(names.size() == itemIDs.size());
- m_selectedIndex = -1;
- m_textField = textField;
- if (separatorIndex == -1) {
- // The suggestions must be set before initializing the
- // AutofillPopupMenuClient.
- setSuggestions(names, labels, icons, itemIDs);
- } else {
- m_useLegacyBehavior = true;
- WebVector<WebString> namesWithSeparator(names.size() + 1);
- WebVector<WebString> labelsWithSeparator(labels.size() + 1);
- WebVector<WebString> iconsWithSeparator(icons.size() + 1);
- WebVector<int> itemIDsWithSeparator(itemIDs.size() + 1);
- for (size_t i = 0; i < names.size(); ++i) {
- size_t j = i < static_cast<size_t>(separatorIndex) ? i : i + 1;
- namesWithSeparator[j] = names[i];
- labelsWithSeparator[j] = labels[i];
- iconsWithSeparator[j] = icons[i];
- itemIDsWithSeparator[j] = itemIDs[i];
- }
- itemIDsWithSeparator[separatorIndex] = WebAutofillClient::MenuItemIDSeparator;
- setSuggestions(namesWithSeparator, labelsWithSeparator, iconsWithSeparator, itemIDsWithSeparator);
- }
- FontDescription regularFontDescription;
- RenderTheme::theme().systemFont(CSSValueWebkitControl,
- regularFontDescription);
- RenderStyle* style = m_textField->computedStyle();
- regularFontDescription.setComputedSize(style->fontDescription().computedSize());
- Font regularFont(regularFontDescription, 0, 0);
- regularFont.update(textField->document().styleEngine()->fontSelector());
- // The direction of text in popup menu is set the same as the direction of
- // the input element: textField.
- m_regularStyle = adoptPtr(new PopupMenuStyle(Color::black, Color::white, regularFont, true, false,
- Length(WebCore::Fixed), textField->renderer()->style()->direction(),
- textField->renderer()->style()->unicodeBidi() == Override,
- PopupMenuStyle::CustomBackgroundColor, PopupMenuStyle::AutofillPopup));
- FontDescription warningFontDescription = regularFont.fontDescription();
- warningFontDescription.setItalic(true);
- Font warningFont(warningFontDescription, regularFont.letterSpacing(), regularFont.wordSpacing());
- warningFont.update(regularFont.fontSelector());
- m_warningStyle = adoptPtr(new PopupMenuStyle(Color::darkGray, m_regularStyle->backgroundColor(), warningFont,
- m_regularStyle->isVisible(), m_regularStyle->isDisplayNone(),
- m_regularStyle->textIndent(), m_regularStyle->textDirection(),
- m_regularStyle->hasTextDirectionOverride(),
- PopupMenuStyle::CustomBackgroundColor, PopupMenuStyle::AutofillPopup));
- }
- void AutofillPopupMenuClient::setSuggestions(const WebVector<WebString>& names,
- const WebVector<WebString>& labels,
- const WebVector<WebString>& icons,
- const WebVector<int>& itemIDs)
- {
- ASSERT(names.size() == labels.size());
- ASSERT(names.size() == icons.size());
- ASSERT(names.size() == itemIDs.size());
- m_names.clear();
- m_labels.clear();
- m_icons.clear();
- m_itemIDs.clear();
- for (size_t i = 0; i < names.size(); ++i) {
- m_names.append(names[i]);
- m_labels.append(labels[i]);
- m_icons.append(icons[i]);
- m_itemIDs.append(itemIDs[i]);
- }
- // Try to preserve selection if possible.
- if (getSelectedIndex() >= static_cast<int>(names.size()))
- setSelectedIndex(-1);
- }
- WebViewImpl* AutofillPopupMenuClient::getWebView() const
- {
- return WebViewImpl::fromPage(m_textField->document().page());
- }
- RenderStyle* AutofillPopupMenuClient::textFieldStyle() const
- {
- RenderStyle* style = m_textField->computedStyle();
- if (!style) {
- // It seems we can only have a 0 style in a TextField if the
- // node is detached, in which case we the popup should not be
- // showing. Please report this in http://crbug.com/7708 and
- // include the page you were visiting.
- ASSERT_NOT_REACHED();
- }
- return style;
- }
- } // namespace blink