diff options
author | csharp@chromium.org <csharp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-09 22:21:01 +0000 |
---|---|---|
committer | csharp@chromium.org <csharp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-09 22:21:01 +0000 |
commit | f48cf5d684147c83aa9fd851e533e232b4c9a64e (patch) | |
tree | 123a1662ea398bd801544aa19c3fab8c9a36e5ed | |
parent | 72a2335053a0426755f4179222e6c0ee8baf786a (diff) | |
download | chromium_src-f48cf5d684147c83aa9fd851e533e232b4c9a64e.zip chromium_src-f48cf5d684147c83aa9fd851e533e232b4c9a64e.tar.gz chromium_src-f48cf5d684147c83aa9fd851e533e232b4c9a64e.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/9128001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@116927 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/autocomplete_history_manager.h | 5 | ||||
-rw-r--r-- | chrome/browser/autocomplete_history_manager_unittest.cc | 7 | ||||
-rw-r--r-- | chrome/browser/autofill/autofill_external_delegate.cc | 10 | ||||
-rw-r--r-- | chrome/browser/autofill/autofill_external_delegate.h | 14 | ||||
-rw-r--r-- | chrome/browser/autofill/autofill_external_delegate_gtk.cc | 86 | ||||
-rw-r--r-- | chrome/browser/autofill/autofill_external_delegate_gtk.h | 66 | ||||
-rw-r--r-- | chrome/browser/autofill/autofill_external_delegate_unittest.cc | 106 | ||||
-rw-r--r-- | chrome/browser/autofill/autofill_manager_unittest.cc | 22 | ||||
-rw-r--r-- | chrome/browser/autofill/autofill_popup_view.cc | 32 | ||||
-rw-r--r-- | chrome/browser/autofill/autofill_popup_view.h | 54 | ||||
-rw-r--r-- | chrome/browser/autofill/autofill_popup_view_browsertest.cc | 83 | ||||
-rw-r--r-- | chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.cc | 62 | ||||
-rw-r--r-- | chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.h | 38 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 6 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 2 |
15 files changed, 568 insertions, 25 deletions
diff --git a/chrome/browser/autocomplete_history_manager.h b/chrome/browser/autocomplete_history_manager.h index f11751e..1dfd34b 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(content::WebContents* web_contents, diff --git a/chrome/browser/autocomplete_history_manager_unittest.cc b/chrome/browser/autocomplete_history_manager_unittest.cc index 83f27c3..add04f0 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..f833bfa --- /dev/null +++ b/chrome/browser/autofill/autofill_popup_view_browsertest.cc @@ -0,0 +1,83 @@ +// 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" + +using ::testing::AtLeast; + +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_; +}; + +IN_PROC_BROWSER_TEST_F(InProcessBrowserTest, SwitchTabAndHideAutofillPopup) { + content::WebContents* web_contents = browser()->GetSelectedWebContents(); + TestAutofillPopupView autofill_popup_view(web_contents); + + // Using AtLeast here because current Hide is called once on Linux and Mac, + // and three times on Windows and ChromeOS. http://crbug.com/109269 + EXPECT_CALL(autofill_popup_view, Hide()).Times(AtLeast(1)); + + 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 b3b6d23..306e5b4 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', @@ -2981,6 +2985,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 e5a483a..7d40458 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', @@ -2462,6 +2463,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', |