summaryrefslogtreecommitdiffstats
path: root/webkit
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
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')
-rw-r--r--webkit/build/glue/glue.vcproj8
-rw-r--r--webkit/build/port/port.vcproj4
-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
-rw-r--r--webkit/port/page/chromium/ChromeClientChromium.h2
-rw-r--r--webkit/port/platform/chromium/PopupMenuChromium.cpp133
-rw-r--r--webkit/port/platform/chromium/PopupMenuChromium.h82
-rw-r--r--webkit/webkit.xcodeproj/project.pbxproj8
20 files changed, 565 insertions, 88 deletions
diff --git a/webkit/build/glue/glue.vcproj b/webkit/build/glue/glue.vcproj
index 879bf66..dcae341 100644
--- a/webkit/build/glue/glue.vcproj
+++ b/webkit/build/glue/glue.vcproj
@@ -381,6 +381,14 @@
>
</File>
<File
+ RelativePath="..\..\glue\form_autocomplete_listener.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\glue\form_autocomplete_listener.h"
+ >
+ </File>
+ <File
RelativePath="..\..\glue\glue_accessibility.cc"
>
</File>
diff --git a/webkit/build/port/port.vcproj b/webkit/build/port/port.vcproj
index 3a42435..b18530a 100644
--- a/webkit/build/port/port.vcproj
+++ b/webkit/build/port/port.vcproj
@@ -807,6 +807,10 @@
>
</File>
<File
+ RelativePath="..\..\port\platform\chromium\PopupMenuChromium.h"
+ >
+ </File>
+ <File
RelativePath="..\..\port\platform\chromium\SearchPopupMenuChromium.cpp"
>
</File>
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
diff --git a/webkit/port/page/chromium/ChromeClientChromium.h b/webkit/port/page/chromium/ChromeClientChromium.h
index 5813770..783b5b5 100644
--- a/webkit/port/page/chromium/ChromeClientChromium.h
+++ b/webkit/port/page/chromium/ChromeClientChromium.h
@@ -26,7 +26,7 @@ namespace WebCore {
// Notifies the client of a new popup widget. The client should place
// and size the widget with the given bounds, relative to the screen.
- virtual void popupOpened(FramelessScrollView* popupView, const IntRect& bounds) = 0;
+ virtual void popupOpened(FramelessScrollView* popupView, const IntRect& bounds, bool focus_on_show) = 0;
};
}
diff --git a/webkit/port/platform/chromium/PopupMenuChromium.cpp b/webkit/port/platform/chromium/PopupMenuChromium.cpp
index d30df68..ae9f164 100644
--- a/webkit/port/platform/chromium/PopupMenuChromium.cpp
+++ b/webkit/port/platform/chromium/PopupMenuChromium.cpp
@@ -36,9 +36,9 @@
#include "ChromeClientChromium.h"
#include "Document.h"
#include "Font.h"
-#include "Frame.h"
#include "FrameView.h"
#include "FontSelector.h"
+#include "Frame.h"
#include "FramelessScrollView.h"
#include "FramelessScrollViewClient.h"
#include "GraphicsContext.h"
@@ -57,6 +57,8 @@
#include "Widget.h"
#pragma warning(pop)
+#include "webkit/port/platform/chromium/PopupMenuChromium.h"
+
using namespace WTF;
using namespace Unicode;
@@ -72,51 +74,6 @@ static const int kMaxHeight = 500;
static const int kBorderSize = 1;
static const TimeStamp kTypeAheadTimeoutMs = 1000;
-class PopupListBox;
-
-// TODO(darin): Our FramelessScrollView classes need to implement HostWindow!
-
-// This class holds a PopupListBox. Its sole purpose is to be able to draw
-// a border around its child. All its paint/event handling is just forwarded
-// to the child listBox (with the appropriate transforms).
-class PopupContainer : public FramelessScrollView, public RefCounted<PopupContainer> {
-public:
- static PassRefPtr<PopupContainer> create(PopupMenuClient* client);
-
- // FramelessScrollView
- virtual void paint(GraphicsContext* gc, const IntRect& rect);
- virtual void hide();
- virtual bool handleMouseDownEvent(const PlatformMouseEvent& event);
- virtual bool handleMouseMoveEvent(const PlatformMouseEvent& event);
- virtual bool handleMouseReleaseEvent(const PlatformMouseEvent& event);
- virtual bool handleWheelEvent(const PlatformWheelEvent& event);
- virtual bool handleKeyEvent(const PlatformKeyboardEvent& event);
-
- // PopupContainer methods
-
- // Show the popup
- void showPopup(FrameView* view);
-
- // Hide the popup. Do not call this directly: use client->hidePopup().
- void hidePopup();
-
- // Compute size of widget and children.
- void layout();
-
- PopupListBox* listBox() const { return m_listBox.get(); }
-
-private:
- friend class RefCounted<PopupContainer>;
-
- PopupContainer(PopupMenuClient* client);
- ~PopupContainer();
-
- // Paint the border.
- void paintBorder(GraphicsContext* gc, const IntRect& rect);
-
- RefPtr<PopupListBox> m_listBox;
-};
-
// This class uses WebCore code to paint and handle events for a drop-down list
// box ("combobox" on Windows).
class PopupListBox : public FramelessScrollView, public RefCounted<PopupListBox> {
@@ -170,6 +127,9 @@ public:
// Compute size of widget and children.
void layout();
+ // Returns whether the popup wants to process events for the passed key.
+ bool isInterestedInEventForKey(int key_code);
+
private:
friend class PopupContainer;
friend class RefCounted<PopupListBox>;
@@ -327,13 +287,15 @@ static PlatformWheelEvent constructRelativeWheelEvent(const PlatformWheelEvent&
// PopupContainer implementation
// static
-PassRefPtr<PopupContainer> PopupContainer::create(PopupMenuClient* client)
+PassRefPtr<PopupContainer> PopupContainer::create(PopupMenuClient* client,
+ bool focusOnShow)
{
- return adoptRef(new PopupContainer(client));
+ return adoptRef(new PopupContainer(client, focusOnShow));
}
-PopupContainer::PopupContainer(PopupMenuClient* client)
- : m_listBox(new PopupListBox(client))
+PopupContainer::PopupContainer(PopupMenuClient* client, bool focusOnShow)
+ : m_listBox(new PopupListBox(client)),
+ m_focusOnShow(focusOnShow)
{
// FrameViews are created with a refcount of 1 so it needs releasing after we
// assign it to a RefPtr.
@@ -367,7 +329,7 @@ void PopupContainer::showPopup(FrameView* view)
if (widgetRect.bottom() > static_cast<int>(screen.bottom()))
widgetRect.move(0, -(widgetRect.height() + selectHeight));
- chromeClient->popupOpened(this, widgetRect);
+ chromeClient->popupOpened(this, widgetRect, m_focusOnShow);
}
// Must get called after we have a client and containingWindow.
@@ -474,6 +436,33 @@ void PopupContainer::paintBorder(GraphicsContext* gc, const IntRect& rect)
gc->drawRect(IntRect(tx + width() - kBorderSize, ty, kBorderSize, height()));
}
+bool PopupContainer::isInterestedInEventForKey(int key_code) {
+ return m_listBox->isInterestedInEventForKey(key_code);
+}
+
+void PopupContainer::show(const IntRect& r, FrameView* v, int index) {
+ // The rect is the size of the select box. It's usually larger than we need.
+ // subtract border size so that usually the container will be displayed
+ // exactly the same width as the select box.
+ listBox()->setBaseWidth(max(r.width() - kBorderSize * 2, 0));
+
+ listBox()->updateFromElement();
+
+ // We set the selected item in updateFromElement(), and disregard the
+ // index passed into this function (same as Webkit's PopupMenuWin.cpp)
+ // TODO(ericroman): make sure this is correct, and add an assertion.
+ // DCHECK(popupWindow(popup)->listBox()->selectedIndex() == index);
+
+ // Convert point to main window coords.
+ IntPoint location = v->contentsToWindow(r.location());
+
+ // Move it below the select widget.
+ location.move(0, r.height());
+
+ IntRect popupRect(location, r.size());
+ setFrameRect(popupRect);
+ showPopup(v);
+}
///////////////////////////////////////////////////////////////////////////////
// PopupListBox implementation
@@ -548,6 +537,23 @@ bool PopupListBox::handleWheelEvent(const PlatformWheelEvent& event)
return true;
}
+// Should be kept in sync with handleKeyEvent().
+bool PopupListBox::isInterestedInEventForKey(int key_code) {
+ switch (key_code) {
+ case VKEY_ESCAPE:
+ case VKEY_RETURN:
+ case VKEY_UP:
+ case VKEY_DOWN:
+ case VKEY_PRIOR:
+ case VKEY_NEXT:
+ case VKEY_HOME:
+ case VKEY_END:
+ return true;
+ default:
+ return false;
+ }
+}
+
bool PopupListBox::handleKeyEvent(const PlatformKeyboardEvent& event)
{
if (event.type() == PlatformKeyboardEvent::KeyUp)
@@ -1036,29 +1042,8 @@ PopupMenu::~PopupMenu()
void PopupMenu::show(const IntRect& r, FrameView* v, int index)
{
- p.m_popup = PopupContainer::create(client());
-
- // The rect is the size of the select box. It's usually larger than we need.
- // subtract border size so that usually the container will be displayed
- // exactly the same width as the select box.
- p.m_popup->listBox()->setBaseWidth(max(r.width() - kBorderSize * 2, 0));
-
- updateFromElement();
-
- // We set the selected item in updateFromElement(), and disregard the
- // index passed into this function (same as Webkit's PopupMenuWin.cpp)
- // TODO(ericroman): make sure this is correct, and add an assertion.
- // DCHECK(popupWindow(m_popup)->listBox()->selectedIndex() == index);
-
- // Convert point to main window coords.
- IntPoint location = v->contentsToWindow(r.location());
-
- // Move it below the select widget.
- location.move(0, r.height());
-
- IntRect popupRect(location, r.size());
- p.m_popup->setFrameRect(popupRect);
- p.m_popup->showPopup(v);
+ p.m_popup = PopupContainer::create(client(), true);
+ p.m_popup->show(r, v, index);
}
void PopupMenu::hide()
diff --git a/webkit/port/platform/chromium/PopupMenuChromium.h b/webkit/port/platform/chromium/PopupMenuChromium.h
index e69de29..d419468 100644
--- a/webkit/port/platform/chromium/PopupMenuChromium.h
+++ b/webkit/port/platform/chromium/PopupMenuChromium.h
@@ -0,0 +1,82 @@
+// 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 PopupMenuChromium_h
+#define PopupMenuChromium_h
+
+#pragma warning(push, 0)
+#include "PopupMenuClient.h"
+
+#include "FramelessScrollView.h"
+#include "IntRect.h"
+#pragma warning(pop)
+
+
+namespace WebCore {
+
+class PopupListBox;
+
+// TODO(darin): Our FramelessScrollView classes need to implement HostWindow!
+
+// This class holds a PopupListBox (see cpp file). Its sole purpose is to be
+// able to draw a border around its child. All its paint/event handling is just
+// forwarded to the child listBox (with the appropriate transforms).
+// NOTE: this class is exposed so it can be instantiated direcly for the
+// autofill popup. We cannot use the Popup class directly in that case as the
+// autofill popup should not be focused when shown and we want to forward the
+// key events to it (through handleKeyEvent).
+
+class PopupContainer : public FramelessScrollView, public RefCounted<PopupContainer> {
+public:
+ static PassRefPtr<PopupContainer> create(PopupMenuClient* client,
+ bool focusOnShow);
+
+ // Whether a key event should be sent to this popup.
+ virtual bool isInterestedInEventForKey(int key_code);
+
+ // FramelessScrollView
+ virtual void paint(GraphicsContext* gc, const IntRect& rect);
+ virtual void hide();
+ virtual bool handleMouseDownEvent(const PlatformMouseEvent& event);
+ virtual bool handleMouseMoveEvent(const PlatformMouseEvent& event);
+ virtual bool handleMouseReleaseEvent(const PlatformMouseEvent& event);
+ virtual bool handleWheelEvent(const PlatformWheelEvent& event);
+ virtual bool handleKeyEvent(const PlatformKeyboardEvent& event);
+
+ // PopupContainer methods
+
+ // Show the popup
+ void showPopup(FrameView* view);
+
+ // Show the popup in the specified rect for the specified frame.
+ // Note: this code was somehow arbitrarily factored-out of the Popup class
+ // so WebViewImpl can create a PopupContainer.
+ void show(const IntRect& r, FrameView* v, int index);
+
+ // Hide the popup. Do not call this directly: use client->hidePopup().
+ void hidePopup();
+
+ // Compute size of widget and children.
+ void layout();
+
+ PopupListBox* listBox() const { return m_listBox.get(); }
+
+private:
+ friend class WTF::RefCounted<PopupContainer>;
+
+ PopupContainer(PopupMenuClient* client, bool focusOnShow);
+ ~PopupContainer();
+
+ // Paint the border.
+ void paintBorder(GraphicsContext* gc, const IntRect& rect);
+
+ RefPtr<PopupListBox> m_listBox;
+
+ // Whether the window showing this popup should be focused when shown.
+ bool m_focusOnShow;
+};
+
+}
+
+#endif // PopupMenuChromium_h
diff --git a/webkit/webkit.xcodeproj/project.pbxproj b/webkit/webkit.xcodeproj/project.pbxproj
index 990ba1b..77e4813 100644
--- a/webkit/webkit.xcodeproj/project.pbxproj
+++ b/webkit/webkit.xcodeproj/project.pbxproj
@@ -61,6 +61,7 @@
4D16381F0EBFA4FB008F024E /* StorageArea.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4D1638060EBFA4FB008F024E /* StorageArea.cpp */; };
4D1638200EBFA4FC008F024E /* StorageEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4D1638080EBFA4FB008F024E /* StorageEvent.cpp */; };
4D1638210EBFA4FC008F024E /* StorageMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4D16380A0EBFA4FB008F024E /* StorageMap.cpp */; };
+ 4D163E990EC23D9D008F024E /* form_autocomplete_listener.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D163E970EC23D9D008F024E /* form_autocomplete_listener.cc */; };
4D2A63EB0EBBBEDF00B55603 /* MediaPlayerPrivateChromium.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4D2A63E90EBBBEDF00B55603 /* MediaPlayerPrivateChromium.cpp */; };
4D2A64400EBBC0A700B55603 /* V8HTMLVideoElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4D2A643A0EBBC0A700B55603 /* V8HTMLVideoElement.cpp */; };
4D2A64410EBBC0A700B55603 /* V8MediaError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4D2A643C0EBBC0A700B55603 /* V8MediaError.cpp */; };
@@ -1483,6 +1484,9 @@
4D1638090EBFA4FB008F024E /* StorageEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StorageEvent.h; sourceTree = "<group>"; };
4D16380A0EBFA4FB008F024E /* StorageMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StorageMap.cpp; sourceTree = "<group>"; };
4D16380B0EBFA4FB008F024E /* StorageMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StorageMap.h; sourceTree = "<group>"; };
+ 4D163E970EC23D9D008F024E /* form_autocomplete_listener.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = form_autocomplete_listener.cc; sourceTree = "<group>"; };
+ 4D163E980EC23D9D008F024E /* form_autocomplete_listener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = form_autocomplete_listener.h; sourceTree = "<group>"; };
+ 4D163E9D0EC23DC6008F024E /* PopupMenuChromium.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PopupMenuChromium.h; sourceTree = "<group>"; };
4D2A63E90EBBBEDF00B55603 /* MediaPlayerPrivateChromium.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaPlayerPrivateChromium.cpp; sourceTree = "<group>"; };
4D2A63EA0EBBBEDF00B55603 /* MediaPlayerPrivateChromium.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaPlayerPrivateChromium.h; sourceTree = "<group>"; };
4D2A643A0EBBC0A700B55603 /* V8HTMLVideoElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = V8HTMLVideoElement.cpp; sourceTree = "<group>"; };
@@ -7443,6 +7447,8 @@
8254050F0D92E3DA0006B936 /* feed_preview.cc */,
825405100D92E3DA0006B936 /* feed_preview.h */,
825405110D92E3DA0006B936 /* find_in_page_request.h */,
+ 4D163E970EC23D9D008F024E /* form_autocomplete_listener.cc */,
+ 4D163E980EC23D9D008F024E /* form_autocomplete_listener.h */,
825405120D92E3DA0006B936 /* form_data.h */,
825405140D92E3DA0006B936 /* glue_serialize.cc */,
825405150D92E3DA0006B936 /* glue_serialize.h */,
@@ -7782,6 +7788,7 @@
E473F6520EAE002F006C2098 /* PlatformCursor.h */,
E473F65D0EAE009A006C2098 /* PlatformWidget.h */,
E473F65E0EAE00A6006C2098 /* PopupMenuChromium.cpp */,
+ 4D163E9D0EC23DC6008F024E /* PopupMenuChromium.h */,
E473F65F0EAE00A6006C2098 /* PopupMenuPrivate.h */,
E473F6630EAE00E4006C2098 /* SearchPopupMenuChromium.cpp */,
E473F6650EAE00F4006C2098 /* SharedTimerChromium.cpp */,
@@ -9261,6 +9268,7 @@
E45626FE0E268F03005E4685 /* editor_client_impl.cc in Sources */,
E456270A0E268F03005E4685 /* event_conversion.cc in Sources */,
E45628370E269DBB005E4685 /* feed_preview.cc in Sources */,
+ 4D163E990EC23D9D008F024E /* form_autocomplete_listener.cc in Sources */,
E45626FA0E268F03005E4685 /* glue_serialize.cc in Sources */,
E45626F50E268F03005E4685 /* glue_util.cc in Sources */,
E4A238C70E3FA19C002BDE14 /* image_decoder.cc in Sources */,