summaryrefslogtreecommitdiffstats
path: root/webkit/glue
diff options
context:
space:
mode:
authorjcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-11-07 21:35:03 +0000
committerjcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-11-07 21:35:03 +0000
commit0ebf38756f3a68b30fe0d8e9336dbfafda52b5d5 (patch)
treea9ce0236b330fab3f39124c52fa0c1f184eb3965 /webkit/glue
parent5e91242859811aef980a929253e6c33eb2cfec6e (diff)
downloadchromium_src-0ebf38756f3a68b30fe0d8e9336dbfafda52b5d5.zip
chromium_src-0ebf38756f3a68b30fe0d8e9336dbfafda52b5d5.tar.gz
chromium_src-0ebf38756f3a68b30fe0d8e9336dbfafda52b5d5.tar.bz2
Landing this again as I cannot reproduce the perf regression locally.
Will investigate on the bot. TBR=nsylvain Review URL: http://codereview.chromium.org/9700 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@5018 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/glue')
-rw-r--r--webkit/glue/SConscript1
-rw-r--r--webkit/glue/autocomplete_input_listener.h1
-rw-r--r--webkit/glue/chrome_client_impl.cc8
-rw-r--r--webkit/glue/chrome_client_impl.h3
-rw-r--r--webkit/glue/form_autocomplete_listener.cc37
-rw-r--r--webkit/glue/form_autocomplete_listener.h46
-rw-r--r--webkit/glue/password_autocomplete_listener.cc1
-rw-r--r--webkit/glue/webframeloaderclient_impl.cc60
-rw-r--r--webkit/glue/webframeloaderclient_impl.h8
-rw-r--r--webkit/glue/webplugin_impl_mac.mm3
-rw-r--r--webkit/glue/webview.h7
-rw-r--r--webkit/glue/webview_delegate.h11
-rw-r--r--webkit/glue/webview_impl.cc214
-rw-r--r--webkit/glue/webview_impl.h16
14 files changed, 403 insertions, 13 deletions
diff --git a/webkit/glue/SConscript b/webkit/glue/SConscript
index c82a3c8..0870d6b 100644
--- a/webkit/glue/SConscript
+++ b/webkit/glue/SConscript
@@ -35,6 +35,7 @@ input_files = [
'editor_client_impl.cc',
'entity_map.cc',
'event_conversion.cc',
+ 'form_autocomplete_listener.cc',
'feed_preview.cc',
'glue_util.cc',
'glue_serialize.cc',
diff --git a/webkit/glue/autocomplete_input_listener.h b/webkit/glue/autocomplete_input_listener.h
index 3b92b86..fe412f1 100644
--- a/webkit/glue/autocomplete_input_listener.h
+++ b/webkit/glue/autocomplete_input_listener.h
@@ -16,7 +16,6 @@
MSVC_PUSH_WARNING_LEVEL(0);
#include "EventListener.h"
MSVC_POP_WARNING();
-#undef LOG
#include "base/basictypes.h"
#include "base/scoped_ptr.h"
diff --git a/webkit/glue/chrome_client_impl.cc b/webkit/glue/chrome_client_impl.cc
index 387f307..081d4c7 100644
--- a/webkit/glue/chrome_client_impl.cc
+++ b/webkit/glue/chrome_client_impl.cc
@@ -449,12 +449,14 @@ void ChromeClientImpl::runFileChooser(const WebCore::String& default_path,
delegate->RunFileChooser(suggestion, chooser);
}
-void ChromeClientImpl::popupOpened(
- WebCore::FramelessScrollView* popup_view, const WebCore::IntRect& bounds) {
+void ChromeClientImpl::popupOpened(WebCore::FramelessScrollView* popup_view,
+ const WebCore::IntRect& bounds,
+ bool focus_on_show) {
WebViewDelegate* d = webview_->delegate();
if (d) {
WebWidgetImpl* webwidget =
- static_cast<WebWidgetImpl*>(d->CreatePopupWidget(webview_));
+ static_cast<WebWidgetImpl*>(d->CreatePopupWidget(webview_,
+ focus_on_show));
webwidget->Init(popup_view, webkit_glue::FromIntRect(bounds));
}
}
diff --git a/webkit/glue/chrome_client_impl.h b/webkit/glue/chrome_client_impl.h
index 88cf83c..7bb132b 100644
--- a/webkit/glue/chrome_client_impl.h
+++ b/webkit/glue/chrome_client_impl.h
@@ -115,7 +115,8 @@ public:
virtual void runFileChooser(const WebCore::String&,
PassRefPtr<WebCore::FileChooser>);
virtual void popupOpened(WebCore::FramelessScrollView* popup_view,
- const WebCore::IntRect& bounds);
+ const WebCore::IntRect& bounds,
+ bool focus_on_show);
void SetCursor(const WebCursor& cursor);
diff --git a/webkit/glue/form_autocomplete_listener.cc b/webkit/glue/form_autocomplete_listener.cc
new file mode 100644
index 0000000..aaaf0f70
--- /dev/null
+++ b/webkit/glue/form_autocomplete_listener.cc
@@ -0,0 +1,37 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+
+#include "webkit/glue/form_autocomplete_listener.h"
+
+MSVC_PUSH_WARNING_LEVEL(0);
+#include "HTMLInputElement.h"
+MSVC_POP_WARNING();
+
+#undef LOG
+
+#include "webkit/glue/autocomplete_input_listener.h"
+#include "webkit/glue/glue_util.h"
+#include "webkit/glue/webview_delegate.h"
+
+namespace webkit_glue {
+
+FormAutocompleteListener::FormAutocompleteListener(
+ WebViewDelegate* webview_delegate,
+ WebCore::HTMLInputElement* input_element)
+ : AutocompleteInputListener(new HTMLInputDelegate(input_element)),
+ webview_delegate_(webview_delegate),
+ name_(webkit_glue::StringToStdWString(input_element->name().string())),
+ node_id_(reinterpret_cast<int64>(input_element)) {
+ DCHECK(input_element->isTextField() && !input_element->isPasswordField() &&
+ input_element->autoComplete());
+}
+
+void FormAutocompleteListener::OnInlineAutocompleteNeeded(
+ const std::wstring& user_input) {
+ webview_delegate_->QueryFormFieldAutofill(name_, user_input, node_id_);
+}
+
+} // namespace
diff --git a/webkit/glue/form_autocomplete_listener.h b/webkit/glue/form_autocomplete_listener.h
new file mode 100644
index 0000000..e55522e
--- /dev/null
+++ b/webkit/glue/form_autocomplete_listener.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_GLUE_FORM_AUTOCOMPLETE_LISTENER_
+#define WEBKIT_GLUE_FORM_AUTOCOMPLETE_LISTENER_
+
+#include <string>
+
+#include "webkit/glue/autocomplete_input_listener.h"
+
+class WebViewDelegate;
+
+namespace webkit_glue {
+
+// This class listens for the user typing in a text input in a form and queries
+// the browser for autofill information.
+
+class FormAutocompleteListener : public AutocompleteInputListener {
+ public:
+ FormAutocompleteListener(WebViewDelegate* webview_delegate,
+ WebCore::HTMLInputElement* input_element);
+ virtual ~FormAutocompleteListener() { }
+
+ // AutocompleteInputListener implementation.
+ virtual void OnBlur(const std::wstring& user_input) { }
+ virtual void OnInlineAutocompleteNeeded(const std::wstring& user_input);
+
+ private:
+ // The delegate associated with the WebView that contains thhe input we are
+ // listening to.
+ WebViewDelegate* webview_delegate_;
+
+ // The name of the input node we are listening to.
+ std::wstring name_;
+
+ // An id to represent the input element. That ID is passed to the call that
+ // queries for suggestions.
+ int64 node_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(FormAutocompleteListener);
+};
+
+} // webkit_glue
+
+#endif // WEBKIT_GLUE_FORM_AUTOCOMPLETE_LISTENER_
diff --git a/webkit/glue/password_autocomplete_listener.cc b/webkit/glue/password_autocomplete_listener.cc
index aaf6125..0a88ab3 100644
--- a/webkit/glue/password_autocomplete_listener.cc
+++ b/webkit/glue/password_autocomplete_listener.cc
@@ -6,6 +6,7 @@
// component.
#include "webkit/glue/password_autocomplete_listener.h"
+#undef LOG
#include "base/logging.h"
namespace webkit_glue {
diff --git a/webkit/glue/webframeloaderclient_impl.cc b/webkit/glue/webframeloaderclient_impl.cc
index 8138900..06e0645 100644
--- a/webkit/glue/webframeloaderclient_impl.cc
+++ b/webkit/glue/webframeloaderclient_impl.cc
@@ -16,6 +16,9 @@ MSVC_PUSH_WARNING_LEVEL(0);
#include "Element.h"
#include "HistoryItem.h"
#include "HTMLFormElement.h" // needed by FormState.h
+#include "HTMLFormControlElement.h"
+#include "HTMLInputElement.h"
+#include "HTMLNames.h"
#include "FormState.h"
#include "FrameLoader.h"
#include "FrameLoadRequest.h"
@@ -39,8 +42,9 @@ MSVC_POP_WARNING();
#if defined(OS_WIN)
#include "webkit/activex_shim/activex_shared.h"
#endif
-#include "webkit/glue/webframeloaderclient_impl.h"
#include "webkit/glue/alt_404_page_resource_fetcher.h"
+#include "webkit/glue/autocomplete_input_listener.h"
+#include "webkit/glue/form_autocomplete_listener.h"
#include "webkit/glue/glue_util.h"
#include "webkit/glue/password_form_dom_manager.h"
#include "webkit/glue/plugins/plugin_list.h"
@@ -48,6 +52,7 @@ MSVC_POP_WARNING();
#include "webkit/glue/webdatasource_impl.h"
#include "webkit/glue/webdocumentloader_impl.h"
#include "webkit/glue/weberror_impl.h"
+#include "webkit/glue/webframeloaderclient_impl.h"
#include "webkit/glue/webhistoryitem_impl.h"
#include "webkit/glue/webkit_glue.h"
#include "webkit/glue/webplugin_impl.h"
@@ -351,10 +356,26 @@ void WebFrameLoaderClient::dispatchDidFinishDocumentLoad() {
if (!form->autoComplete())
continue;
+ std::set<std::wstring> password_related_fields;
scoped_ptr<PasswordForm> data(
PasswordFormDomManager::CreatePasswordForm(form));
- if (data.get())
+ if (data.get()) {
actions.push_back(*data);
+ // Let's remember the names of password related fields so we do not
+ // autofill them with the regular form autofill.
+ DCHECK(!data->username_element.empty());
+ DCHECK(!data->password_element.empty());
+ password_related_fields.insert(data->username_element);
+ password_related_fields.insert(data->password_element);
+ if (!data->old_password_element.empty())
+ password_related_fields.insert(data->old_password_element);
+ }
+
+ // Now let's register for any text input.
+ // TODO(jcampan): bug #3847 merge password and form autofill so we
+ // traverse the form elements only once.
+ // Disabling the autofill to investigate the perf regression on build bot.
+ // RegisterAutofillListeners(form, password_related_fields);
}
}
@@ -686,6 +707,40 @@ NavigationGesture WebFrameLoaderClient::NavigationGestureForLastLoad() {
NavigationGestureAuto;
}
+void WebFrameLoaderClient::RegisterAutofillListeners(
+ WebCore::HTMLFormElement* form,
+ const std::set<std::wstring>& excluded_fields) {
+
+ WebViewDelegate* webview_delegate = webframe_->webview_impl()->delegate();
+ if (!webview_delegate)
+ return;
+
+ for (size_t i = 0; i < form->formElements.size(); i++) {
+ WebCore::HTMLFormControlElement* form_element = form->formElements[i];
+ if (!form_element->hasLocalName(WebCore::HTMLNames::inputTag))
+ continue;
+
+ WebCore::HTMLInputElement* input_element =
+ static_cast<WebCore::HTMLInputElement*>(form_element);
+ if (!input_element->isEnabled() || !input_element->isTextField() ||
+ input_element->isPasswordField() || !input_element->autoComplete()) {
+ continue;
+ }
+
+ std::wstring name = webkit_glue::StringToStdWString(input_element->name());
+ if (excluded_fields.find(name) != excluded_fields.end())
+ continue;
+
+#if !defined(OS_MACOSX)
+ // FIXME on Mac
+ webkit_glue::FormAutocompleteListener* listener =
+ new webkit_glue::FormAutocompleteListener(webview_delegate,
+ input_element);
+ webkit_glue::AttachForInlineAutocomplete(input_element, listener);
+#endif
+ }
+}
+
void WebFrameLoaderClient::dispatchDidReceiveTitle(const String& title) {
WebViewImpl* webview = webframe_->webview_impl();
WebViewDelegate* d = webview->delegate();
@@ -1478,4 +1533,3 @@ bool WebFrameLoaderClient::ActionSpecifiesDisposition(
*disposition = shift ? NEW_WINDOW : SAVE_TO_DISK;
return true;
}
-
diff --git a/webkit/glue/webframeloaderclient_impl.h b/webkit/glue/webframeloaderclient_impl.h
index 20b12ee..6010ba8 100644
--- a/webkit/glue/webframeloaderclient_impl.h
+++ b/webkit/glue/webframeloaderclient_impl.h
@@ -5,6 +5,8 @@
#ifndef WEBKIT_GLUE_WEBFRAMELOADERCLIENT_IMPL_H__
#define WEBKIT_GLUE_WEBFRAMELOADERCLIENT_IMPL_H__
+#include <set>
+
#include "base/compiler_specific.h"
MSVC_PUSH_WARNING_LEVEL(0);
@@ -18,6 +20,7 @@ MSVC_POP_WARNING();
namespace WebCore {
class Frame;
+class HTMLFormElement;
class Widget;
}
@@ -209,6 +212,11 @@ class WebFrameLoaderClient : public WebCore::FrameLoaderClient {
// otherwise returns NavigationGestureUnknown.
NavigationGesture NavigationGestureForLastLoad();
+ // Registers the text input fields in the passed form for autofill, with the
+ // exclusion of any field whose name is contained in |excluded_fields|.
+ void RegisterAutofillListeners(WebCore::HTMLFormElement* form,
+ const std::set<std::wstring>& excluded_fields);
+
// The WebFrame that owns this object and manages its lifetime. Therefore,
// the web frame object is guaranteed to exist.
WebFrameImpl* webframe_;
diff --git a/webkit/glue/webplugin_impl_mac.mm b/webkit/glue/webplugin_impl_mac.mm
index 191ebb7..1a420ea 100644
--- a/webkit/glue/webplugin_impl_mac.mm
+++ b/webkit/glue/webplugin_impl_mac.mm
@@ -4,6 +4,9 @@
#include "config.h"
+#include "wtf/ASCIICType.h"
+
+#undef LOG
#include "webkit/glue/webplugin_impl.h"
// TODO(pinkerton): all of this needs to be filled in. webplugin_impl.cc has
diff --git a/webkit/glue/webview.h b/webkit/glue/webview.h
index e47ad0e..1c67c4f4 100644
--- a/webkit/glue/webview.h
+++ b/webkit/glue/webview.h
@@ -6,6 +6,7 @@
#define WEBKIT_GLUE_WEBVIEW_H__
#include <string>
+#include <vector>
#include "base/basictypes.h"
#include "base/ref_counted.h"
@@ -195,6 +196,12 @@ class WebView : public WebWidget {
virtual void DragTargetDrop(
int client_x, int client_y, int screen_x, int screen_y) = 0;
+ // Notifies the webview that autofill suggestions are available for a node.
+ virtual void AutofillSuggestionsForNode(
+ int64 node_id,
+ const std::vector<std::wstring>& suggestions,
+ int default_suggestion_index) = 0;
+
private:
DISALLOW_EVIL_CONSTRUCTORS(WebView);
};
diff --git a/webkit/glue/webview_delegate.h b/webkit/glue/webview_delegate.h
index 97944dd..1ce50c5 100644
--- a/webkit/glue/webview_delegate.h
+++ b/webkit/glue/webview_delegate.h
@@ -108,7 +108,8 @@ class WebViewDelegate : virtual public WebWidgetDelegate {
// This method is called to create a new WebWidget to act as a popup
// (like a drop-down menu).
- virtual WebWidget* CreatePopupWidget(WebView* webview) {
+ virtual WebWidget* CreatePopupWidget(WebView* webview,
+ bool focus_on_show) {
return NULL;
}
@@ -457,6 +458,14 @@ class WebViewDelegate : virtual public WebWidgetDelegate {
virtual void OnUnloadListenerChanged(WebView* webview, WebFrame* webframe) {
}
+ // Queries the browser for suggestions to be shown for the form text field
+ // named |field_name|. |text| is the text entered by the user so far and
+ // |node_id| is the id of the node of the input field.
+ virtual void QueryFormFieldAutofill(const std::wstring& field_name,
+ const std::wstring& text,
+ int64 node_id) {
+ }
+
// UIDelegate --------------------------------------------------------------
// Asks the browser to show a modal HTML dialog. The dialog is passed the
diff --git a/webkit/glue/webview_impl.cc b/webkit/glue/webview_impl.cc
index 6375fa3..c807b31 100644
--- a/webkit/glue/webview_impl.cc
+++ b/webkit/glue/webview_impl.cc
@@ -35,6 +35,7 @@
#include "base/compiler_specific.h"
MSVC_PUSH_WARNING_LEVEL(0);
+#include "CSSStyleSelector.h"
#if defined(OS_WIN)
#include "Cursor.h"
#endif
@@ -50,20 +51,25 @@ MSVC_PUSH_WARNING_LEVEL(0);
#include "FrameTree.h"
#include "FrameView.h"
#include "GraphicsContext.h"
+#include "HTMLNames.h"
+#include "HTMLInputElement.h"
#include "HitTestResult.h"
#include "Image.h"
#include "InspectorController.h"
#include "IntRect.h"
#include "KeyboardEvent.h"
#include "MIMETypeRegistry.h"
+#include "NodeRenderStyle.h"
#include "Page.h"
#include "PlatformKeyboardEvent.h"
#include "PlatformMouseEvent.h"
#include "PlatformWheelEvent.h"
#include "PluginInfoStore.h"
+#include "PopupMenuClient.h"
#if defined(OS_WIN)
#include "RenderThemeWin.h"
#endif
+#include "RenderView.h"
#include "ResourceHandle.h"
#include "SelectionController.h"
#include "Settings.h"
@@ -94,6 +100,7 @@ MSVC_POP_WARNING();
#include "webkit/glue/webview_delegate.h"
#include "webkit/glue/webview_impl.h"
#include "webkit/glue/webwidget_impl.h"
+#include "webkit/port/platform/chromium/PopupMenuChromium.h"
#include "webkit/port/platform/graphics/PlatformContextSkia.h"
// Get rid of WTF's pow define so we can use std::pow.
@@ -115,6 +122,126 @@ static const double kMaxTextSizeMultiplier = 3.0;
static const WebCore::DragOperation kDropTargetOperation =
static_cast<WebCore::DragOperation>(DragOperationCopy | DragOperationLink);
+// AutocompletePopupMenuClient
+class AutocompletePopupMenuClient
+ : public RefCounted<AutocompletePopupMenuClient>,
+ public WebCore::PopupMenuClient {
+ public:
+ AutocompletePopupMenuClient(WebViewImpl* webview,
+ WebCore::HTMLInputElement* text_field,
+ const std::vector<std::wstring>& suggestions,
+ int default_suggestion_index)
+ : text_field_(text_field),
+ selected_index_(default_suggestion_index),
+ webview_(webview) {
+ for (std::vector<std::wstring>::const_iterator iter = suggestions.begin();
+ iter != suggestions.end(); ++iter) {
+ suggestions_.push_back(webkit_glue::StdWStringToString(*iter));
+ }
+ }
+ virtual ~AutocompletePopupMenuClient() {
+ }
+
+ virtual void valueChanged(unsigned listIndex, bool fireEvents = true) {
+ text_field_->setValue(suggestions_[listIndex]);
+ }
+
+ virtual WebCore::String itemText(unsigned list_index) const {
+ return suggestions_[list_index];
+ }
+
+ virtual bool itemIsEnabled(unsigned listIndex) const {
+ return true;
+ }
+
+ virtual PopupMenuStyle itemStyle(unsigned listIndex) const {
+ return menuStyle();
+ }
+
+ virtual PopupMenuStyle menuStyle() const {
+ RenderStyle* style = text_field_->renderStyle() ?
+ text_field_->renderStyle() :
+ text_field_->computedStyle();
+ return PopupMenuStyle(style->color(), Color::white, style->font(),
+ style->visibility() == VISIBLE);
+ }
+
+ virtual int clientInsetLeft() const {
+ return 0;
+ }
+ virtual int clientInsetRight() const {
+ return 0;
+ }
+ virtual int clientPaddingLeft() const {
+#if defined(OS_WIN)
+ return theme()->popupInternalPaddingLeft(text_field_->computedStyle());
+#else
+ NOTIMPLEMENTED();
+ return 0;
+#endif
+ }
+ virtual int clientPaddingRight() const {
+#if defined(OS_WIN)
+ return theme()->popupInternalPaddingRight(text_field_->computedStyle());
+#else
+ NOTIMPLEMENTED();
+ return 0;
+#endif
+ }
+ virtual int listSize() const {
+ return suggestions_.size();
+ }
+ virtual int selectedIndex() const {
+ return selected_index_;
+ }
+ virtual void hidePopup() {
+ webview_->HideAutoCompletePopup();
+ }
+ virtual bool itemIsSeparator(unsigned listIndex) const {
+ return false;
+ }
+ virtual bool itemIsLabel(unsigned listIndex) const {
+ return false;
+ }
+ virtual bool itemIsSelected(unsigned listIndex) const {
+ return false;
+ }
+ virtual bool shouldPopOver() const {
+ return false;
+ }
+ virtual bool valueShouldChangeOnHotTrack() const {
+ return false;
+ }
+
+ virtual FontSelector* fontSelector() const {
+ return text_field_->document()->styleSelector()->fontSelector();
+ }
+
+ virtual void setTextFromItem(unsigned listIndex) {
+ text_field_->setValue(suggestions_[listIndex]);
+ }
+
+ virtual HostWindow* hostWindow() const {
+ return text_field_->document()->view()->hostWindow();
+ }
+
+ virtual PassRefPtr<Scrollbar> createScrollbar(
+ ScrollbarClient* client,
+ ScrollbarOrientation orientation,
+ ScrollbarControlSize size) {
+ RefPtr<Scrollbar> widget = Scrollbar::createNativeScrollbar(client,
+ orientation,
+ size);
+ return widget.release();
+ }
+
+ private:
+ RefPtr<WebCore::HTMLInputElement> text_field_;
+ std::vector<WebCore::String> suggestions_;
+ int selected_index_;
+ WebViewImpl* webview_;
+};
+
// WebView ----------------------------------------------------------------
/*static*/
@@ -292,6 +419,18 @@ bool WebViewImpl::KeyEvent(const WebKeyboardEvent& event) {
// event.
suppress_next_keypress_event_ = false;
+ // Give autocomplete a chance to consume the key events it is interested in.
+ if (autocomplete_popup_ &&
+ autocomplete_popup_->isInterestedInEventForKey(event.key_code)) {
+ if (autocomplete_popup_->handleKeyEvent(MakePlatformKeyboardEvent(event)))
+ return true;
+ return false;
+ }
+
+ // A new key being pressed should hide the popup.
+ if (event.type == WebInputEvent::KEY_DOWN)
+ HideAutoCompletePopup();
+
Frame* frame = GetFocusedWebCoreFrame();
if (!frame)
return false;
@@ -714,7 +853,6 @@ bool WebViewImpl::HandleInputEvent(const WebInputEvent* input_event) {
// we're done.
if (doing_drag_and_drop_)
return true;
-
// TODO(eseidel): Remove g_current_input_event.
// This only exists to allow ChromeClient::show() to know which mouse button
// triggered a window.open event.
@@ -782,6 +920,14 @@ void WebViewImpl::SetBackForwardListSize(int size) {
void WebViewImpl::SetFocus(bool enable) {
if (enable) {
+ // Hide the popup menu if any.
+ // TODO(jcampan): bug #3844: we should do that when we lose focus. The
+ // reason we are not doing it is because when clicking on the autofill
+ // popup, the page first loses focus before the mouse click is sent to the
+ // popup. So if we close when the focus is lost, the mouse click does not
+ // do anything.
+ HideAutoCompletePopup();
+
// Getting the focused frame will have the side-effect of setting the main
// frame as the focused frame if it is not already focused. Otherwise, if
// there is already a focused frame, then this does nothing.
@@ -803,8 +949,6 @@ void WebViewImpl::SetFocus(bool enable) {
// updated below.
ReleaseFocusReferences();
- // Clear focus on the currently focused frame if any.
-
if (!main_frame_)
return;
@@ -1018,7 +1162,8 @@ void WebViewImpl::SetInitialFocus(bool reverse) {
// We have to set the key type explicitly to avoid an assert in the
// KeyboardEvent constructor.
platform_event.SetKeyType(PlatformKeyboardEvent::RawKeyDown);
- RefPtr<KeyboardEvent> webkit_event = KeyboardEvent::create(platform_event, NULL);
+ RefPtr<KeyboardEvent> webkit_event = KeyboardEvent::create(platform_event,
+ NULL);
page()->focusController()->setInitialFocus(
reverse ? WebCore::FocusDirectionBackward :
WebCore::FocusDirectionForward,
@@ -1331,6 +1476,59 @@ SearchableFormData* WebViewImpl::CreateSearchableFormDataForFocusedNode() {
return NULL;
}
+void WebViewImpl::AutofillSuggestionsForNode(
+ int64 node_id,
+ const std::vector<std::wstring>& suggestions,
+ int default_suggestion_index) {
+ if (!main_frame_ || suggestions.empty())
+ return;
+
+ DCHECK(default_suggestion_index < static_cast<int>(suggestions.size()));
+
+ Frame* frame = main_frame_->frame();
+ if (!frame)
+ return;
+
+ if (RefPtr<Frame> focused =
+ frame->page()->focusController()->focusedFrame()) {
+ RefPtr<Document> document = focused->document();
+ if (!document.get())
+ return;
+
+ RefPtr<Node> focused_node = document->focusedNode();
+ // If the node for which we queried the autofill suggestions is not the
+ // focused node, then we have nothing to do.
+ // TODO(jcampan): also check the carret is at the end and that the text has
+ // not changed.
+ if (!focused_node.get() ||
+ reinterpret_cast<int64>(focused_node.get()) != node_id)
+ return;
+
+ if (!focused_node->hasTagName(WebCore::HTMLNames::inputTag)) {
+ NOTREACHED();
+ return;
+ }
+
+ WebCore::HTMLInputElement* input_elem =
+ static_cast<WebCore::HTMLInputElement*>(focused_node.get());
+ // Hide any current autocomplete popup.
+ HideAutoCompletePopup();
+
+ if (suggestions.size() > 0) {
+ autocomplete_popup_client_ =
+ adoptRef(new AutocompletePopupMenuClient(this, input_elem,
+ suggestions,
+ default_suggestion_index));
+ // Autocomplete popup does not get focused. We need the page to still
+ // have focus so the user can keep typing when the popup is showing.
+ autocomplete_popup_ =
+ WebCore::PopupContainer::create(autocomplete_popup_client_.get(),
+ false);
+ autocomplete_popup_->show(focused_node->getRect(), frame->view(), 0);
+ }
+ }
+}
+
void WebViewImpl::DidCommitLoad(bool* is_new_navigation) {
if (is_new_navigation)
*is_new_navigation = observed_new_navigation_;
@@ -1479,3 +1677,11 @@ void WebViewImpl::DeleteImageResourceFetcher(ImageResourceFetcher* fetcher) {
// deletion.
MessageLoop::current()->DeleteSoon(FROM_HERE, fetcher);
}
+
+void WebViewImpl::HideAutoCompletePopup() {
+ if (autocomplete_popup_) {
+ autocomplete_popup_->hidePopup();
+ autocomplete_popup_.clear();
+ autocomplete_popup_client_.clear();
+ }
+}
diff --git a/webkit/glue/webview_impl.h b/webkit/glue/webview_impl.h
index da0d533..83cddebd 100644
--- a/webkit/glue/webview_impl.h
+++ b/webkit/glue/webview_impl.h
@@ -27,10 +27,12 @@ class HistoryItem;
class KeyboardEvent;
class Page;
class PlatformKeyboardEvent;
+class PopupContainer;
class Range;
class Widget;
}
+class AutocompletePopupMenuClient;
class ImageResourceFetcher;
class SearchableFormData;
struct WebDropData;
@@ -98,6 +100,10 @@ class WebViewImpl : public WebView, public WebCore::BackForwardListClient {
virtual void DragTargetDragLeave();
virtual void DragTargetDrop(
int client_x, int client_y, int screen_x, int screen_y);
+ virtual void AutofillSuggestionsForNode(
+ int64 node_id,
+ const std::vector<std::wstring>& suggestions,
+ int default_suggestion_index);
// WebViewImpl
@@ -178,6 +184,9 @@ class WebViewImpl : public WebView, public WebCore::BackForwardListClient {
bool errored,
const SkBitmap& image);
+ // Hides the autocomplete popup if it is showing.
+ void HideAutoCompletePopup();
+
protected:
friend class WebView; // So WebView::Create can call our constructor
@@ -287,6 +296,13 @@ class WebViewImpl : public WebView, public WebCore::BackForwardListClient {
// Represents whether or not this object should process incoming IME events.
bool ime_accept_events_;
+ // The currently shown autocomplete popup.
+ RefPtr<WebCore::PopupContainer> autocomplete_popup_;
+
+ // The popup client of the currently shown autocomplete popup. Necessary for
+ // managing the life of the client.
+ RefPtr<AutocompletePopupMenuClient> autocomplete_popup_client_;
+
// HACK: current_input_event is for ChromeClientImpl::show(), until we can fix
// WebKit to pass enough information up into ChromeClient::show() so we can
// decide if the window.open event was caused by a middle-mouse click