summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcsharp@chromium.org <csharp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-05 18:18:42 +0000
committercsharp@chromium.org <csharp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-05 18:18:42 +0000
commit61fd4dc472f8990d53b6773d98ef9c090dc33789 (patch)
tree25eb6a9cb4ee1832a59ebfc1eda5a26166699f80
parentc385b2015f0969f9885f1284123d23c578ed8d8b (diff)
downloadchromium_src-61fd4dc472f8990d53b6773d98ef9c090dc33789.zip
chromium_src-61fd4dc472f8990d53b6773d98ef9c090dc33789.tar.gz
chromium_src-61fd4dc472f8990d53b6773d98ef9c090dc33789.tar.bz2
First pass for new GTK Autofill popup.
This first pass just displays the new Autofill popup and then hides it at the correct times. The box is the correct size, but none of the text is drawn at the moment. This is only enabled when the --external-autofill-popup flag is enabled. BUG=51644 Review URL: http://codereview.chromium.org/8890035 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@116512 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/autocomplete_history_manager.h5
-rw-r--r--chrome/browser/autocomplete_history_manager_unittest.cc7
-rw-r--r--chrome/browser/autofill/autofill_external_delegate.cc10
-rw-r--r--chrome/browser/autofill/autofill_external_delegate.h14
-rw-r--r--chrome/browser/autofill/autofill_external_delegate_gtk.cc86
-rw-r--r--chrome/browser/autofill/autofill_external_delegate_gtk.h66
-rw-r--r--chrome/browser/autofill/autofill_external_delegate_unittest.cc106
-rw-r--r--chrome/browser/autofill/autofill_manager_unittest.cc22
-rw-r--r--chrome/browser/autofill/autofill_popup_view.cc32
-rw-r--r--chrome/browser/autofill/autofill_popup_view.h54
-rw-r--r--chrome/browser/autofill/autofill_popup_view_browsertest.cc87
-rw-r--r--chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.cc62
-rw-r--r--chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.h38
-rw-r--r--chrome/chrome_browser.gypi6
-rw-r--r--chrome/chrome_tests.gypi2
15 files changed, 572 insertions, 25 deletions
diff --git a/chrome/browser/autocomplete_history_manager.h b/chrome/browser/autocomplete_history_manager.h
index 8f5eabc..c4c02d6 100644
--- a/chrome/browser/autocomplete_history_manager.h
+++ b/chrome/browser/autocomplete_history_manager.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -57,7 +57,8 @@ class AutocompleteHistoryManager : public content::WebContentsObserver,
friend class AutocompleteHistoryManagerTest;
friend class AutofillManagerTest;
FRIEND_TEST_ALL_PREFIXES(AutocompleteHistoryManagerTest, ExternalDelegate);
- FRIEND_TEST_ALL_PREFIXES(AutofillManagerTest, TestTabContents);
+ FRIEND_TEST_ALL_PREFIXES(AutofillManagerTest,
+ TestTabContentsWithExternalDelegate);
// For tests.
AutocompleteHistoryManager(TabContents* tab_contents,
diff --git a/chrome/browser/autocomplete_history_manager_unittest.cc b/chrome/browser/autocomplete_history_manager_unittest.cc
index d1086f1..94a7a9e 100644
--- a/chrome/browser/autocomplete_history_manager_unittest.cc
+++ b/chrome/browser/autocomplete_history_manager_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -142,7 +142,7 @@ namespace {
class MockAutofillExternalDelegate : public AutofillExternalDelegate {
public:
explicit MockAutofillExternalDelegate(TabContentsWrapper* wrapper)
- : AutofillExternalDelegate(wrapper) {}
+ : AutofillExternalDelegate(wrapper, NULL) {}
virtual ~MockAutofillExternalDelegate() {}
virtual void OnQuery(int query_id,
@@ -171,7 +171,8 @@ class MockAutofillExternalDelegate : public AutofillExternalDelegate {
virtual void OnQueryPlatformSpecific(
int query_id,
const webkit::forms::FormData& form,
- const webkit::forms::FormField& field) OVERRIDE {}
+ const webkit::forms::FormField& field,
+ const gfx::Rect& bounds) OVERRIDE {}
private:
DISALLOW_COPY_AND_ASSIGN(MockAutofillExternalDelegate);
diff --git a/chrome/browser/autofill/autofill_external_delegate.cc b/chrome/browser/autofill/autofill_external_delegate.cc
index 6d0a6f3..8c0bcdd 100644
--- a/chrome/browser/autofill/autofill_external_delegate.cc
+++ b/chrome/browser/autofill/autofill_external_delegate.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -17,8 +17,10 @@ AutofillExternalDelegate::~AutofillExternalDelegate() {
}
AutofillExternalDelegate::AutofillExternalDelegate(
- TabContentsWrapper* tab_contents_wrapper)
+ TabContentsWrapper* tab_contents_wrapper,
+ AutofillManager* autofill_manager)
: tab_contents_wrapper_(tab_contents_wrapper),
+ autofill_manager_(autofill_manager),
autofill_query_id_(0),
display_warning_if_disabled_(false),
has_shown_autofill_popup_for_current_edit_(false) {
@@ -41,7 +43,7 @@ void AutofillExternalDelegate::OnQuery(int query_id,
display_warning_if_disabled_ = display_warning_if_disabled;
autofill_query_id_ = query_id;
- OnQueryPlatformSpecific(query_id, form, field);
+ OnQueryPlatformSpecific(query_id, form, field, bounds);
}
void AutofillExternalDelegate::DidEndTextFieldEditing() {
@@ -134,7 +136,7 @@ void AutofillExternalDelegate::OnSuggestionsReturned(
// in an autofill_external_delegate_YOUROS.cc. Currently there are
// none, so all platforms use the default.
-#if !defined(OS_ANDROID)
+#if !defined(OS_ANDROID) && !defined(TOOLKIT_GTK)
AutofillExternalDelegate* AutofillExternalDelegate::Create(
TabContentsWrapper*, AutofillManager*) {
diff --git a/chrome/browser/autofill/autofill_external_delegate.h b/chrome/browser/autofill/autofill_external_delegate.h
index 4890565..20d15bb 100644
--- a/chrome/browser/autofill/autofill_external_delegate.h
+++ b/chrome/browser/autofill/autofill_external_delegate.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -76,7 +76,8 @@ class AutofillExternalDelegate {
void DidEndTextFieldEditing();
protected:
- explicit AutofillExternalDelegate(TabContentsWrapper* tab_contents_wrapper);
+ explicit AutofillExternalDelegate(TabContentsWrapper* tab_contents_wrapper,
+ AutofillManager* autofill_manager);
// Displays the the Autofill results to the user with an external
// Autofill popup that lives completely in the browser. The suggestions
@@ -89,13 +90,14 @@ class AutofillExternalDelegate {
int separator_index) = 0;
// Handle instance specific OnQueryCode.
- virtual void OnQueryPlatformSpecific(
- int query_id,
- const webkit::forms::FormData& form,
- const webkit::forms::FormField& field) = 0;
+ virtual void OnQueryPlatformSpecific(int query_id,
+ const webkit::forms::FormData& form,
+ const webkit::forms::FormField& field,
+ const gfx::Rect& bounds) = 0;
private:
TabContentsWrapper* tab_contents_wrapper_; // weak; owns me.
+ AutofillManager* autofill_manager_; // weak.
// The ID of the last request sent for form field Autofill. Used to ignore
// out of date responses.
diff --git a/chrome/browser/autofill/autofill_external_delegate_gtk.cc b/chrome/browser/autofill/autofill_external_delegate_gtk.cc
new file mode 100644
index 0000000..e39b72e
--- /dev/null
+++ b/chrome/browser/autofill/autofill_external_delegate_gtk.cc
@@ -0,0 +1,86 @@
+// Copyright (c) 2012 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 "chrome/browser/autofill/autofill_external_delegate_gtk.h"
+
+#include "chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
+#include "content/browser/tab_contents/tab_contents.h"
+#include "content/browser/tab_contents/tab_contents_view.h"
+#include "content/public/browser/web_contents.h"
+
+AutofillExternalDelegate* AutofillExternalDelegate::Create(
+ TabContentsWrapper* tab_contents_wrapper,
+ AutofillManager* autofill_manager) {
+ return new AutofillExternalDelegateGtk(tab_contents_wrapper,
+ autofill_manager);
+}
+
+AutofillExternalDelegateGtk::AutofillExternalDelegateGtk(
+ TabContentsWrapper* tab_contents_wrapper,
+ AutofillManager* autofill_manager)
+ : AutofillExternalDelegate(tab_contents_wrapper, autofill_manager),
+ web_contents_(tab_contents_wrapper->web_contents()) {
+ tab_native_view_ = web_contents_->GetView()->GetNativeView();
+}
+
+AutofillExternalDelegateGtk::~AutofillExternalDelegateGtk() {
+}
+
+void AutofillExternalDelegateGtk::OnQueryPlatformSpecific(
+ int query_id,
+ const webkit::forms::FormData& form,
+ const webkit::forms::FormField& field,
+ const gfx::Rect& bounds) {
+ CreateViewIfNeeded();
+ view_->set_element_bounds(bounds);
+}
+
+void AutofillExternalDelegateGtk::ApplyAutofillSuggestions(
+ const std::vector<string16>& autofill_values,
+ const std::vector<string16>& autofill_labels,
+ const std::vector<string16>& autofill_icons,
+ const std::vector<int>& autofill_unique_ids,
+ int separator_index) {
+ view_->Show(autofill_values,
+ autofill_labels,
+ autofill_icons,
+ autofill_unique_ids,
+ separator_index);
+}
+
+void AutofillExternalDelegateGtk::HideAutofillPopup() {
+ if (!view_.get())
+ return;
+
+ view_->Hide();
+ view_.reset();
+
+ GtkWidget* toplevel = gtk_widget_get_toplevel(tab_native_view_);
+ g_signal_handler_disconnect(toplevel, event_handler_id_);
+}
+
+void AutofillExternalDelegateGtk::CreateViewIfNeeded() {
+ if (view_.get())
+ return;
+
+ view_.reset(new AutofillPopupViewGtk(web_contents_,
+ tab_native_view_));
+
+ GtkWidget* toplevel = gtk_widget_get_toplevel(tab_native_view_);
+ if (!g_signal_handler_is_connected(toplevel, event_handler_id_)) {
+ event_handler_id_ = g_signal_connect(
+ toplevel,
+ "focus-out-event",
+ G_CALLBACK(HandleViewFocusOutThunk),
+ this);
+ }
+}
+
+gboolean AutofillExternalDelegateGtk::HandleViewFocusOut(GtkWidget* sender,
+ GdkEventFocus* event) {
+ HideAutofillPopup();
+
+ return TRUE;
+}
diff --git a/chrome/browser/autofill/autofill_external_delegate_gtk.h b/chrome/browser/autofill/autofill_external_delegate_gtk.h
new file mode 100644
index 0000000..31e2fd0
--- /dev/null
+++ b/chrome/browser/autofill/autofill_external_delegate_gtk.h
@@ -0,0 +1,66 @@
+// Copyright (c) 2012 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 CHROME_BROWSER_AUTOFILL_AUTOFILL_EXTERNAL_DELEGATE_GTK_H_
+#define CHROME_BROWSER_AUTOFILL_AUTOFILL_EXTERNAL_DELEGATE_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/autofill/autofill_external_delegate.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/gfx/native_widget_types.h"
+
+class AutofillPopupViewGtk;
+
+namespace content {
+class WebContents;
+}
+
+class AutofillExternalDelegateGtk : public AutofillExternalDelegate {
+ public:
+ AutofillExternalDelegateGtk(TabContentsWrapper* tab_contents_wrapper,
+ AutofillManager* autofill_manager);
+
+ virtual ~AutofillExternalDelegateGtk();
+
+ // AutofillExternalDelegate implementation.
+ virtual void HideAutofillPopup() OVERRIDE;
+
+ protected:
+ // AutofillExternalDelegate implementations.
+ virtual void OnQueryPlatformSpecific(
+ int query_id,
+ const webkit::forms::FormData& form,
+ const webkit::forms::FormField& field,
+ const gfx::Rect& bounds) OVERRIDE;
+ virtual void ApplyAutofillSuggestions(
+ const std::vector<string16>& autofill_values,
+ const std::vector<string16>& autofill_labels,
+ const std::vector<string16>& autofill_icons,
+ const std::vector<int>& autofill_unique_ids,
+ int separator_index) OVERRIDE;
+
+ private:
+ // Create a valid view to display the autofill results if one doesn't
+ // currently exist.
+ void CreateViewIfNeeded();
+
+ CHROMEGTK_CALLBACK_1(AutofillExternalDelegateGtk, gboolean,
+ HandleViewFocusOut, GdkEventFocus*);
+
+ scoped_ptr<AutofillPopupViewGtk> view_;
+
+ content::WebContents* web_contents_; // Weak reference.
+ gfx::NativeView tab_native_view_; // Weak reference.
+
+ // The handler value for the focus out event, allows us to block and unblock
+ // it as needed.
+ gulong event_handler_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(AutofillExternalDelegateGtk);
+};
+
+#endif // CHROME_BROWSER_AUTOFILL_AUTOFILL_EXTERNAL_DELEGATE_GTK_H_
diff --git a/chrome/browser/autofill/autofill_external_delegate_unittest.cc b/chrome/browser/autofill/autofill_external_delegate_unittest.cc
new file mode 100644
index 0000000..f9e6f6c
--- /dev/null
+++ b/chrome/browser/autofill/autofill_external_delegate_unittest.cc
@@ -0,0 +1,106 @@
+// Copyright (c) 2012 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 <vector>
+
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "base/string16.h"
+#include "chrome/browser/autofill/autofill_external_delegate.h"
+#include "chrome/browser/autofill/autofill_manager.h"
+#include "chrome/browser/ui/tab_contents/test_tab_contents_wrapper.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/test/test_browser_thread.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/rect.h"
+#include "webkit/forms/form_data.h"
+#include "webkit/forms/form_field.h"
+
+using content::BrowserThread;
+using testing::_;
+using webkit::forms::FormData;
+using webkit::forms::FormField;
+
+namespace {
+
+class MockAutofillExternalDelegate : public AutofillExternalDelegate {
+ public:
+ explicit MockAutofillExternalDelegate(TabContentsWrapper* wrapper,
+ AutofillManager* autofill_manager)
+ : AutofillExternalDelegate(wrapper, autofill_manager) {}
+ virtual ~MockAutofillExternalDelegate() {}
+
+ virtual void HideAutofillPopup() OVERRIDE {}
+
+ MOCK_METHOD5(ApplyAutofillSuggestions, void(
+ const std::vector<string16>& autofill_values,
+ const std::vector<string16>& autofill_labels,
+ const std::vector<string16>& autofill_icons,
+ const std::vector<int>& autofill_unique_ids,
+ int separator_index));
+
+ MOCK_METHOD4(OnQueryPlatformSpecific,
+ void(int query_id,
+ const webkit::forms::FormData& form,
+ const webkit::forms::FormField& field,
+ const gfx::Rect& bounds));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockAutofillExternalDelegate);
+};
+
+} // namespace
+
+class AutofillExternalDelegateTest : public TabContentsWrapperTestHarness {
+ public:
+ AutofillExternalDelegateTest()
+ : ui_thread_(BrowserThread::UI, &message_loop_) {}
+ virtual ~AutofillExternalDelegateTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ TabContentsWrapperTestHarness::SetUp();
+ autofill_manager_ = new AutofillManager(contents_wrapper());
+ }
+
+ protected:
+ scoped_refptr<AutofillManager> autofill_manager_;
+
+ private:
+ content::TestBrowserThread ui_thread_;
+
+ DISALLOW_COPY_AND_ASSIGN(AutofillExternalDelegateTest);
+};
+
+// Test that our external delegate called the virtual methods at the right time.
+TEST_F(AutofillExternalDelegateTest, TestExternalDelegateVirtualCalls) {
+ MockAutofillExternalDelegate external_delegate(contents_wrapper(),
+ autofill_manager_);
+ const int kQueryId = 5;
+ const FormData form;
+ FormField field;
+ field.is_focusable = true;
+ field.should_autocomplete = true;
+ const gfx::Rect bounds;
+
+ EXPECT_CALL(external_delegate,
+ OnQueryPlatformSpecific(kQueryId, form, field, bounds));
+
+ // This should call OnQueryPlatform specific.
+ external_delegate.OnQuery(kQueryId, form, field, bounds, false);
+
+
+ EXPECT_CALL(external_delegate, ApplyAutofillSuggestions(_, _, _, _, _));
+
+ // This should call ApplyAutofillSuggestions.
+ std::vector<string16> autofill_item;
+ autofill_item.push_back(string16());
+ std::vector<int> autofill_ids;
+ autofill_ids.push_back(1);
+ external_delegate.OnSuggestionsReturned(kQueryId,
+ autofill_item,
+ autofill_item,
+ autofill_item,
+ autofill_ids);
+}
diff --git a/chrome/browser/autofill/autofill_manager_unittest.cc b/chrome/browser/autofill/autofill_manager_unittest.cc
index 22abbf0..ee42ca3 100644
--- a/chrome/browser/autofill/autofill_manager_unittest.cc
+++ b/chrome/browser/autofill/autofill_manager_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -2864,8 +2864,9 @@ namespace {
class MockAutofillExternalDelegate : public AutofillExternalDelegate {
public:
- explicit MockAutofillExternalDelegate(TabContentsWrapper* wrapper)
- : AutofillExternalDelegate(wrapper) {}
+ explicit MockAutofillExternalDelegate(TabContentsWrapper* wrapper,
+ AutofillManager* autofill_manager)
+ : AutofillExternalDelegate(wrapper, autofill_manager) {}
virtual ~MockAutofillExternalDelegate() {}
MOCK_METHOD5(OnQuery, void(int query_id,
@@ -2883,10 +2884,10 @@ class MockAutofillExternalDelegate : public AutofillExternalDelegate {
const std::vector<int>& autofill_unique_ids,
int separator_index) OVERRIDE {}
- virtual void OnQueryPlatformSpecific(
- int query_id,
- const webkit::forms::FormData& form,
- const webkit::forms::FormField& field) OVERRIDE {}
+ virtual void OnQueryPlatformSpecific(int query_id,
+ const webkit::forms::FormData& form,
+ const webkit::forms::FormField& field,
+ const gfx::Rect& bounds) OVERRIDE {}
private:
DISALLOW_COPY_AND_ASSIGN(MockAutofillExternalDelegate);
@@ -2896,7 +2897,8 @@ class MockAutofillExternalDelegate : public AutofillExternalDelegate {
// Test our external delegate is called at the right time.
TEST_F(AutofillManagerTest, TestExternalDelegate) {
- MockAutofillExternalDelegate external_delegate(contents_wrapper());
+ MockAutofillExternalDelegate external_delegate(contents_wrapper(),
+ autofill_manager_);
EXPECT_CALL(external_delegate, OnQuery(_, _, _, _, _));
autofill_manager_->SetExternalDelegate(&external_delegate);
@@ -2910,8 +2912,8 @@ TEST_F(AutofillManagerTest, TestExternalDelegate) {
autofill_manager_->SetExternalDelegate(NULL);
}
-#if defined(OS_ANDROID)
-// Only OS_ANDROID defines an external delegate, but prerequisites for
+#if defined(OS_ANDROID) || defined(TOOLKIT_GTK)
+// OS_ANDROID defines an external delegate, but prerequisites for
// landing autofill_external_delegate_android.cc in the Chromium tree
// have not themselves landed.
diff --git a/chrome/browser/autofill/autofill_popup_view.cc b/chrome/browser/autofill/autofill_popup_view.cc
new file mode 100644
index 0000000..9a2ea79
--- /dev/null
+++ b/chrome/browser/autofill/autofill_popup_view.cc
@@ -0,0 +1,32 @@
+// Copyright (c) 2012 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 "chrome/browser/autofill/autofill_popup_view.h"
+
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_source.h"
+#include "content/public/browser/notification_types.h"
+
+AutofillPopupView::AutofillPopupView(content::WebContents* web_contents) {
+ registrar_.Add(this,
+ content::NOTIFICATION_WEB_CONTENTS_HIDDEN,
+ content::Source<content::WebContents>(web_contents));
+ registrar_.Add(
+ this,
+ content::NOTIFICATION_NAV_ENTRY_COMMITTED,
+ content::Source<content::NavigationController>(
+ &(web_contents->GetController())));
+}
+
+AutofillPopupView::~AutofillPopupView() {}
+
+void AutofillPopupView::Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ if (type == content::NOTIFICATION_WEB_CONTENTS_HIDDEN
+ || type == content::NOTIFICATION_NAV_ENTRY_COMMITTED)
+ Hide();
+}
diff --git a/chrome/browser/autofill/autofill_popup_view.h b/chrome/browser/autofill/autofill_popup_view.h
new file mode 100644
index 0000000..bde5cd2
--- /dev/null
+++ b/chrome/browser/autofill/autofill_popup_view.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2012 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 CHROME_BROWSER_AUTOFILL_AUTOFILL_POPUP_VIEW_H_
+#define CHROME_BROWSER_AUTOFILL_AUTOFILL_POPUP_VIEW_H_
+#pragma once
+
+#include "base/compiler_specific.h"
+#include "base/string16.h"
+#include "content/public/browser/notification_registrar.h"
+#include "content/public/browser/notification_observer.h"
+#include "ui/gfx/rect.h"
+
+namespace content {
+class WebContents;
+}
+
+class AutofillPopupView : public content::NotificationObserver {
+ public:
+ explicit AutofillPopupView(content::WebContents* web_contents);
+ virtual ~AutofillPopupView();
+
+ // Hide the popup from view.
+ virtual void Hide() = 0;
+
+ // Display the autofill popup and fill it in with the values passed in.
+ virtual void Show(const std::vector<string16>& autofill_values,
+ const std::vector<string16>& autofill_labels,
+ const std::vector<string16>& autofill_icons,
+ const std::vector<int>& autofill_unique_ids,
+ int separator_index) = 0;
+
+
+ void set_element_bounds(const gfx::Rect& bounds) {
+ element_bounds_ = bounds;
+ }
+
+ const gfx::Rect& element_bounds() { return element_bounds_; }
+
+ private:
+ // content::NotificationObserver method override.
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ // A scoped container for notification registries.
+ content::NotificationRegistrar registrar_;
+
+ // The bounds of the text element that is the focus of the Autofill.
+ gfx::Rect element_bounds_;
+};
+
+#endif // CHROME_BROWSER_AUTOFILL_AUTOFILL_POPUP_VIEW_H_
diff --git a/chrome/browser/autofill/autofill_popup_view_browsertest.cc b/chrome/browser/autofill/autofill_popup_view_browsertest.cc
new file mode 100644
index 0000000..52f6421
--- /dev/null
+++ b/chrome/browser/autofill/autofill_popup_view_browsertest.cc
@@ -0,0 +1,87 @@
+// Copyright (c) 2012 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 "chrome/browser/autofill/autofill_popup_view.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/browser/tab_contents/tab_contents.h"
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_types.h"
+#include "content/public/browser/page_navigator.h"
+#include "content/public/common/url_constants.h"
+#include "content/test/browser_test.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class TestAutofillPopupView : public AutofillPopupView {
+ public:
+ explicit TestAutofillPopupView(content::WebContents* web_contents)
+ : AutofillPopupView(web_contents) {}
+ virtual ~TestAutofillPopupView() {}
+
+ MOCK_METHOD0(Hide, void());
+
+ virtual void Show(const std::vector<string16>& autofill_values,
+ const std::vector<string16>& autofill_labels,
+ const std::vector<string16>& autofill_icons,
+ const std::vector<int>& autofill_unique_ids,
+ int separator_index) OVERRIDE {}
+};
+
+class AutofillPopupViewBrowserTest : public InProcessBrowserTest {
+ public:
+ AutofillPopupViewBrowserTest() {}
+ virtual ~AutofillPopupViewBrowserTest() {}
+
+ protected:
+ scoped_ptr<TestAutofillPopupView> autofill_popup_view_;
+};
+
+
+#if defined(OS_WIN)
+// http://crbug.com/109269
+#define MAYBE_SwitchTabAndHideAutofillPopup \
+ DISABLED_SwitchTabAndHideAutofillPopup
+#else
+#define MAYBE_SwitchTabAndHideAutofillPopup SwitchTabAndHideAutofillPopup
+#endif
+IN_PROC_BROWSER_TEST_F(InProcessBrowserTest,
+ MAYBE_SwitchTabAndHideAutofillPopup) {
+ content::WebContents* web_contents = browser()->GetSelectedWebContents();
+ TestAutofillPopupView autofill_popup_view(web_contents);
+ EXPECT_CALL(autofill_popup_view, Hide());
+
+ ui_test_utils::WindowedNotificationObserver observer(
+ content::NOTIFICATION_WEB_CONTENTS_HIDDEN,
+ content::Source<content::WebContents>(web_contents));
+ browser()->AddSelectedTabWithURL(GURL(chrome::kAboutBlankURL),
+ content::PAGE_TRANSITION_START_PAGE);
+ observer.Wait();
+
+ // The mock verifies that the call was made.
+}
+
+IN_PROC_BROWSER_TEST_F(InProcessBrowserTest,
+ TestPageNavigationHidingAutofillPopup) {
+ content::WebContents* web_contents = browser()->GetSelectedWebContents();
+ TestAutofillPopupView autofill_popup_view(web_contents);
+ EXPECT_CALL(autofill_popup_view, Hide());
+
+ ui_test_utils::WindowedNotificationObserver observer(
+ content::NOTIFICATION_NAV_ENTRY_COMMITTED,
+ content::Source<content::NavigationController>(
+ &(web_contents->GetController())));
+ browser()->OpenURL(content::OpenURLParams(
+ GURL(chrome::kAboutBlankURL), content::Referrer(),
+ CURRENT_TAB, content::PAGE_TRANSITION_TYPED, false));
+ browser()->OpenURL(content::OpenURLParams(
+ GURL(chrome::kAboutCrashURL), content::Referrer(),
+ CURRENT_TAB, content::PAGE_TRANSITION_TYPED, false));
+ observer.Wait();
+
+ // The mock verifies that the call was made.
+}
diff --git a/chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.cc b/chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.cc
new file mode 100644
index 0000000..5df1bdc
--- /dev/null
+++ b/chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.cc
@@ -0,0 +1,62 @@
+// Copyright (c) 2012 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 "autofill_popup_view_gtk.h"
+
+#include "base/logging.h"
+#include "ui/base/gtk/gtk_windowing.h"
+
+AutofillPopupViewGtk::AutofillPopupViewGtk(content::WebContents* web_contents,
+ GtkWidget* parent)
+ : AutofillPopupView(web_contents),
+ parent_(parent),
+ window_(gtk_window_new(GTK_WINDOW_POPUP)) {
+ CHECK(parent != NULL);
+ gtk_window_set_resizable(GTK_WINDOW(window_), FALSE);
+ gtk_widget_set_app_paintable(window_, TRUE);
+ gtk_widget_set_double_buffered(window_, TRUE);
+
+ // Setup the window to ensure it recieves the expose event.
+ gtk_widget_add_events(window_, GDK_EXPOSURE_MASK);
+ g_signal_connect(window_, "expose-event",
+ G_CALLBACK(HandleExposeThunk), this);
+}
+
+AutofillPopupViewGtk::~AutofillPopupViewGtk() {
+ gtk_widget_destroy(window_);
+}
+
+void AutofillPopupViewGtk::Hide() {
+ gtk_widget_hide(window_);
+}
+
+// TODO(csharp): Actually show the values.
+void AutofillPopupViewGtk::Show(const std::vector<string16>& autofill_values,
+ const std::vector<string16>& autofill_labels,
+ const std::vector<string16>& autofill_icons,
+ const std::vector<int>& autofill_unique_ids,
+ int separator_index) {
+ gint origin_x, origin_y;
+ gdk_window_get_origin(gtk_widget_get_window(parent_), &origin_x, &origin_y);
+
+ gtk_window_move(GTK_WINDOW(window_),
+ origin_x + element_bounds().x(),
+ origin_y + element_bounds().y() + element_bounds().height());
+
+ gtk_widget_set_size_request(
+ window_,
+ element_bounds().width(),
+ element_bounds().height() * autofill_values.size());
+
+ gtk_widget_show(window_);
+
+ GtkWidget* toplevel = gtk_widget_get_toplevel(parent_);
+ CHECK(gtk_widget_is_toplevel(toplevel));
+ ui::StackPopupWindow(window_, toplevel);
+}
+
+gboolean AutofillPopupViewGtk::HandleExpose(GtkWidget* widget,
+ GdkEventExpose* event) {
+ return TRUE;
+}
diff --git a/chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.h b/chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.h
new file mode 100644
index 0000000..d45b0a4
--- /dev/null
+++ b/chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2012 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 CHROME_BROWSER_UI_GTK_AUTOFILL_AUTOFILL_POPUP_VIEW_GTK_H_
+#define CHROME_BROWSER_UI_GTK_AUTOFILL_AUTOFILL_POPUP_VIEW_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "base/string16.h"
+#include "chrome/browser/autofill/autofill_popup_view.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+#include <vector>
+
+class AutofillPopupViewGtk : public AutofillPopupView {
+ public:
+ AutofillPopupViewGtk(content::WebContents* web_contents, GtkWidget* parent);
+ virtual ~AutofillPopupViewGtk();
+
+ // AutofillPopupView implementations.
+ virtual void Hide() OVERRIDE;
+ virtual void Show(const std::vector<string16>& autofill_values,
+ const std::vector<string16>& autofill_labels,
+ const std::vector<string16>& autofill_icons,
+ const std::vector<int>& autofill_unique_ids,
+ int separator_index) OVERRIDE;
+
+ private:
+ CHROMEGTK_CALLBACK_1(AutofillPopupViewGtk, gboolean, HandleExpose,
+ GdkEventExpose*);
+
+ GtkWidget* parent_; // Weak reference.
+ GtkWidget* window_; // Strong refence.
+};
+
+#endif // CHROME_BROWSER_UI_GTK_AUTOFILL_AUTOFILL_POPUP_VIEW_GTK_H_
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index bc1ff6d..acb765b 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -151,6 +151,8 @@
'browser/autofill/autofill_download.h',
'browser/autofill/autofill_external_delegate.cc',
'browser/autofill/autofill_external_delegate.h',
+ 'browser/autofill/autofill_external_delegate_gtk.cc',
+ 'browser/autofill/autofill_external_delegate_gtk.h',
'browser/autofill/autofill_feedback_infobar_delegate.cc',
'browser/autofill/autofill_feedback_infobar_delegate.h',
'browser/autofill/autofill_field.cc',
@@ -161,6 +163,8 @@
'browser/autofill/autofill_manager.h',
'browser/autofill/autofill_metrics.cc',
'browser/autofill/autofill_metrics.h',
+ 'browser/autofill/autofill_popup_view.cc',
+ 'browser/autofill/autofill_popup_view.h',
'browser/autofill/autofill_profile.cc',
'browser/autofill/autofill_profile.h',
'browser/autofill/autofill_regex_constants.cc.utf8',
@@ -2987,6 +2991,8 @@
'browser/ui/gtk/about_chrome_dialog.h',
'browser/ui/gtk/accelerators_gtk.cc',
'browser/ui/gtk/accelerators_gtk.h',
+ 'browser/ui/gtk/autofill/autofill_popup_view_gtk.cc',
+ 'browser/ui/gtk/autofill/autofill_popup_view_gtk.h',
'browser/ui/gtk/avatar_menu_bubble_gtk.cc',
'browser/ui/gtk/avatar_menu_bubble_gtk.h',
'browser/ui/gtk/avatar_menu_button_gtk.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index bb4c46a..c506fd2 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1255,6 +1255,7 @@
'browser/autofill/address_unittest.cc',
'browser/autofill/autofill_country_unittest.cc',
'browser/autofill/autofill_download_unittest.cc',
+ 'browser/autofill/autofill_external_delegate_unittest.cc',
'browser/autofill/autofill_field_unittest.cc',
'browser/autofill/autofill_ie_toolbar_import_win_unittest.cc',
'browser/autofill/autofill_manager_unittest.cc',
@@ -2460,6 +2461,7 @@
'browser/accessibility/dump_accessibility_tree_browsertest.cc',
'browser/autocomplete/autocomplete_browsertest.cc',
'browser/autofill/form_structure_browsertest.cc',
+ 'browser/autofill/autofill_popup_view_browsertest.cc',
'browser/automation/automation_tab_helper_browsertest.cc',
'browser/bookmarks/bookmark_extension_apitest.cc',
'browser/bookmarks/bookmark_manager_extension_apitest.cc',