summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-14 04:28:34 +0000
committerestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-14 04:28:34 +0000
commitdbd4b1dc9829c4afa9d59a7121d8df1f57f50b98 (patch)
tree3ede245f81fe1ebbd0958f8cc47a762830412ac5
parentc004d650005cf121332b36c4707dbe67afda53a0 (diff)
downloadchromium_src-dbd4b1dc9829c4afa9d59a7121d8df1f57f50b98.zip
chromium_src-dbd4b1dc9829c4afa9d59a7121d8df1f57f50b98.tar.gz
chromium_src-dbd4b1dc9829c4afa9d59a7121d8df1f57f50b98.tar.bz2
Refactor AutofillPopupView and friends
Before: AutofillPopupViewViews extends AutofillPopupView AutofillExternalDelegateViews extends AutofillExternalDelegate, and owns AutofillPopupViewViews After: AutofillPopupController owns AutofillPopupViewViews which implements AutofillPopupView interface AutofillExternalDelegate implements AutofillPopupDelegate, and creates / interacts with AutofillPopupController (no platform subclasses for AutofillExternalDelegate) no dependency of AutofillPopupView and subclasses on content/ BUG=164966 Review URL: https://codereview.chromium.org/11446077 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@173084 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/autofill/autofill_external_delegate.cc109
-rw-r--r--chrome/browser/autofill/autofill_external_delegate.h74
-rw-r--r--chrome/browser/autofill/autofill_external_delegate_browsertest.cc (renamed from chrome/browser/autofill/autofill_popup_view_browsertest.cc)104
-rw-r--r--chrome/browser/autofill/autofill_external_delegate_unittest.cc51
-rw-r--r--chrome/browser/autofill/autofill_popup_delegate.h37
-rw-r--r--chrome/browser/autofill/autofill_popup_unittest.cc205
-rw-r--r--chrome/browser/autofill/autofill_popup_view.h195
-rw-r--r--chrome/browser/autofill/test_autofill_external_delegate.cc4
-rw-r--r--chrome/browser/autofill/test_autofill_external_delegate.h4
-rw-r--r--chrome/browser/ui/android/autofill/autofill_external_delegate.cc58
-rw-r--r--chrome/browser/ui/android/autofill/autofill_external_delegate.h37
-rw-r--r--chrome/browser/ui/android/autofill/autofill_popup_view_android.cc77
-rw-r--r--chrome/browser/ui/android/autofill/autofill_popup_view_android.h28
-rw-r--r--chrome/browser/ui/autofill/autofill_popup_controller.h93
-rw-r--r--chrome/browser/ui/autofill/autofill_popup_controller_impl.cc (renamed from chrome/browser/autofill/autofill_popup_view.cc)385
-rw-r--r--chrome/browser/ui/autofill/autofill_popup_controller_impl.h150
-rw-r--r--chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc208
-rw-r--r--chrome/browser/ui/autofill/autofill_popup_view.cc22
-rw-r--r--chrome/browser/ui/autofill/autofill_popup_view.h64
-rw-r--r--chrome/browser/ui/gtk/autofill/autofill_external_delegate_gtk.cc86
-rw-r--r--chrome/browser/ui/gtk/autofill/autofill_external_delegate_gtk.h55
-rw-r--r--chrome/browser/ui/gtk/autofill/autofill_external_delegate_gtk_browsertest.cc62
-rw-r--r--chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.cc181
-rw-r--r--chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.h39
-rw-r--r--chrome/browser/ui/views/autofill/autofill_external_delegate_views.cc62
-rw-r--r--chrome/browser/ui/views/autofill/autofill_external_delegate_views.h50
-rw-r--r--chrome/browser/ui/views/autofill/autofill_external_delegate_views_browsertest.cc105
-rw-r--r--chrome/browser/ui/views/autofill/autofill_popup_view_views.cc186
-rw-r--r--chrome/browser/ui/views/autofill/autofill_popup_view_views.h43
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/chrome_browser_ui.gypi11
-rw-r--r--chrome/chrome_tests.gypi4
-rw-r--r--chrome/chrome_tests_unit.gypi6
-rw-r--r--content/browser/renderer_host/render_widget_host_impl.cc22
-rw-r--r--content/browser/renderer_host/render_widget_host_impl.h8
-rw-r--r--content/browser/renderer_host/render_widget_host_view_gtk.cc4
-rw-r--r--content/browser/renderer_host/render_widget_host_view_win.cc7
-rw-r--r--content/public/browser/keyboard_listener.h21
38 files changed, 1272 insertions, 1587 deletions
diff --git a/chrome/browser/autofill/autofill_external_delegate.cc b/chrome/browser/autofill/autofill_external_delegate.cc
index 03a2e20..4afc3d6 100644
--- a/chrome/browser/autofill/autofill_external_delegate.cc
+++ b/chrome/browser/autofill/autofill_external_delegate.cc
@@ -6,6 +6,7 @@
#include "chrome/browser/autofill/autocomplete_history_manager.h"
#include "chrome/browser/autofill/autofill_external_delegate.h"
#include "chrome/browser/autofill/autofill_manager.h"
+#include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h"
#include "chrome/common/autofill_messages.h"
#include "chrome/common/chrome_constants.h"
#include "content/public/browser/navigation_controller.h"
@@ -14,28 +15,42 @@
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_view.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebAutofillClient.h"
#include "ui/base/l10n/l10n_util.h"
+#if defined(OS_ANDROID)
+#include "content/public/browser/android/content_view_core.h"
+#endif
+
using content::RenderViewHost;
using WebKit::WebAutofillClient;
DEFINE_WEB_CONTENTS_USER_DATA_KEY(AutofillExternalDelegate)
-AutofillExternalDelegate::~AutofillExternalDelegate() {}
+void AutofillExternalDelegate::CreateForWebContentsAndManager(
+ content::WebContents* web_contents,
+ AutofillManager* autofill_manager) {
+ if (FromWebContents(web_contents))
+ return;
+
+ web_contents->SetUserData(
+ UserDataKey(),
+ new AutofillExternalDelegate(web_contents, autofill_manager));
+}
AutofillExternalDelegate::AutofillExternalDelegate(
content::WebContents* web_contents,
AutofillManager* autofill_manager)
: web_contents_(web_contents),
autofill_manager_(autofill_manager),
+ controller_(NULL),
password_autofill_manager_(web_contents),
autofill_query_id_(0),
display_warning_if_disabled_(false),
- has_shown_autofill_popup_for_current_edit_(false),
- popup_visible_(false) {
+ has_shown_autofill_popup_for_current_edit_(false) {
registrar_.Add(this,
content::NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED,
content::Source<content::WebContents>(web_contents));
@@ -48,6 +63,11 @@ AutofillExternalDelegate::AutofillExternalDelegate(
}
}
+AutofillExternalDelegate::~AutofillExternalDelegate() {
+ if (controller_)
+ controller_->DelegateDestroyed();
+}
+
void AutofillExternalDelegate::SelectAutofillSuggestionAtIndex(int unique_id) {
ClearPreviewedForm();
@@ -59,14 +79,14 @@ void AutofillExternalDelegate::SelectAutofillSuggestionAtIndex(int unique_id) {
void AutofillExternalDelegate::OnQuery(int query_id,
const FormData& form,
const FormFieldData& field,
- const gfx::Rect& bounds,
+ const gfx::Rect& element_bounds,
bool display_warning_if_disabled) {
autofill_query_form_ = form;
autofill_query_field_ = field;
display_warning_if_disabled_ = display_warning_if_disabled;
autofill_query_id_ = query_id;
- CreatePopupForElement(bounds);
+ EnsurePopupForElement(element_bounds);
}
void AutofillExternalDelegate::OnSuggestionsReturned(
@@ -122,7 +142,6 @@ void AutofillExternalDelegate::OnSuggestionsReturned(
// Send to display.
if (autofill_query_field_.is_focusable) {
- popup_visible_ = true;
ApplyAutofillSuggestions(values, labels, icons, ids);
if (autofill_manager_) {
@@ -136,11 +155,9 @@ void AutofillExternalDelegate::OnSuggestionsReturned(
void AutofillExternalDelegate::OnShowPasswordSuggestions(
const std::vector<string16>& suggestions,
const FormFieldData& field,
- const gfx::Rect& bounds) {
- if (!popup_visible_) {
- autofill_query_field_ = field;
- CreatePopupForElement(bounds);
- }
+ const gfx::Rect& element_bounds) {
+ autofill_query_field_ = field;
+ EnsurePopupForElement(element_bounds);
if (suggestions.empty()) {
HideAutofillPopup();
@@ -150,24 +167,44 @@ void AutofillExternalDelegate::OnShowPasswordSuggestions(
std::vector<string16> empty(suggestions.size());
std::vector<int> password_ids(suggestions.size(),
WebAutofillClient::MenuItemIDPasswordEntry);
- popup_visible_ = true;
ApplyAutofillSuggestions(suggestions, empty, empty, password_ids);
}
+void AutofillExternalDelegate::EnsurePopupForElement(
+ const gfx::Rect& element_bounds) {
+ if (controller_)
+ return;
+
+ // |controller_| owns itself.
+ controller_ = new AutofillPopupControllerImpl(
+ this,
+ // web_contents() may be NULL during testing.
+ web_contents() ? web_contents()->GetView()->GetContentNativeView() : NULL,
+ element_bounds);
+}
+
+void AutofillExternalDelegate::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) {
+ controller_->Show(autofill_values,
+ autofill_labels,
+ autofill_icons,
+ autofill_unique_ids);
+
+ web_contents()->GetRenderViewHost()->AddKeyboardListener(controller_);
+}
+
void AutofillExternalDelegate::SetCurrentDataListValues(
const std::vector<string16>& data_list_values,
const std::vector<string16>& data_list_labels,
const std::vector<string16>& data_list_icons,
const std::vector<int>& data_list_unique_ids) {
- // TODO(csharp): Modify the code to allow the data list values to change
- // even if the popup is visible.
- // http://crbug.com/131003
- if (!popup_visible_) {
- data_list_values_ = data_list_values;
- data_list_labels_ = data_list_labels;
- data_list_icons_ = data_list_icons;
- data_list_unique_ids_ = data_list_unique_ids;
- }
+ data_list_values_ = data_list_values;
+ data_list_labels_ = data_list_labels;
+ data_list_icons_ = data_list_icons;
+ data_list_unique_ids_ = data_list_unique_ids;
}
void AutofillExternalDelegate::RemoveAutocompleteEntry(const string16& value) {
@@ -182,14 +219,13 @@ void AutofillExternalDelegate::RemoveAutofillProfileOrCreditCard(
autofill_manager_->RemoveAutofillProfileOrCreditCard(unique_id);
}
-
void AutofillExternalDelegate::DidEndTextFieldEditing() {
HideAutofillPopup();
has_shown_autofill_popup_for_current_edit_ = false;
}
-bool AutofillExternalDelegate::DidAcceptAutofillSuggestions(
+bool AutofillExternalDelegate::DidAcceptAutofillSuggestion(
const string16& value,
int unique_id,
unsigned index) {
@@ -236,14 +272,16 @@ void AutofillExternalDelegate::ClearPreviewedForm() {
}
}
-void AutofillExternalDelegate::HideAutofillPopup() {
- if (!popup_visible_)
- return;
-
- popup_visible_ = false;
+void AutofillExternalDelegate::ControllerDestroyed() {
+ web_contents()->GetRenderViewHost()->RemoveKeyboardListener(controller_);
+ controller_ = NULL;
+}
- ClearPreviewedForm();
- HideAutofillPopupInternal();
+void AutofillExternalDelegate::HideAutofillPopup() {
+ if (controller_) {
+ ClearPreviewedForm();
+ controller_->Hide();
+ }
}
void AutofillExternalDelegate::Reset() {
@@ -255,7 +293,7 @@ void AutofillExternalDelegate::Reset() {
void AutofillExternalDelegate::AddPasswordFormMapping(
const FormFieldData& form,
const PasswordFormFillData& fill_data) {
- password_autofill_manager_.AddPasswordFormMapping(form, fill_data);
+ password_autofill_manager_.AddPasswordFormMapping(form, fill_data);
}
void AutofillExternalDelegate::FillAutofillFormData(int unique_id,
@@ -383,12 +421,3 @@ void AutofillExternalDelegate::Observe(
}
-
-#if defined(OS_MACOSX)
-
-void AutofillExternalDelegate::CreateForWebContentsAndManager(
- content::WebContents* web_contents,
- AutofillManager* autofill_manager) {
-}
-
-#endif
diff --git a/chrome/browser/autofill/autofill_external_delegate.h b/chrome/browser/autofill/autofill_external_delegate.h
index 13692d1..2f278e5 100644
--- a/chrome/browser/autofill/autofill_external_delegate.h
+++ b/chrome/browser/autofill/autofill_external_delegate.h
@@ -9,16 +9,18 @@
#include "base/compiler_specific.h"
#include "base/string16.h"
+#include "chrome/browser/autofill/autofill_popup_delegate.h"
#include "chrome/browser/autofill/password_autofill_manager.h"
#include "chrome/common/form_data.h"
#include "chrome/common/form_field_data.h"
#include "chrome/common/password_form_fill_data.h"
-#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/web_contents_user_data.h"
#include "ui/gfx/rect.h"
class AutofillManager;
+class AutofillPopupControllerImpl;
namespace gfx {
class Rect;
@@ -32,25 +34,27 @@ class WebContents;
// Once Autofill is moved out of WebKit this class should be the only home for
// this logic. See http://crbug.com/51644
-// Delegate for external processing of Autocomplete and Autofill
-// display and selection.
+// Delegate for in-browser Autocomplete and Autofill display and selection.
class AutofillExternalDelegate
: public content::WebContentsUserData<AutofillExternalDelegate>,
- public content::NotificationObserver {
+ public content::NotificationObserver,
+ public AutofillPopupDelegate {
public:
// Creates an AutofillExternalDelegate and attaches it to the specified
// contents; the second argument is an AutofillManager managing Autofill for
// that WebContents.
- //
- // This call is implemented per-platform.
static void CreateForWebContentsAndManager(content::WebContents* web_contents,
AutofillManager* autofill_manager);
- virtual ~AutofillExternalDelegate();
-
- // When using an external Autofill delegate. Allows Chrome to tell
- // WebKit which Autofill selection has been chosen.
- virtual void SelectAutofillSuggestionAtIndex(int unique_id);
+ // AutofillPopupDelegate implementation.
+ virtual void SelectAutofillSuggestionAtIndex(int unique_id) OVERRIDE;
+ virtual bool DidAcceptAutofillSuggestion(const string16& value,
+ int unique_id,
+ unsigned index) OVERRIDE;
+ virtual void ClearPreviewedForm() OVERRIDE;
+ virtual void RemoveAutocompleteEntry(const string16& value) OVERRIDE;
+ virtual void RemoveAutofillProfileOrCreditCard(int unique_id) OVERRIDE;
+ virtual void ControllerDestroyed() OVERRIDE;
// Records and associates a query_id with web form data. Called
// when the renderer posts an Autofill query to the browser. |bounds|
@@ -62,7 +66,7 @@ class AutofillExternalDelegate
virtual void OnQuery(int query_id,
const FormData& form,
const FormFieldData& field,
- const gfx::Rect& bounds,
+ const gfx::Rect& element_bounds,
bool display_warning_if_disabled);
// Records query results and correctly formats them before sending them off
@@ -85,28 +89,10 @@ class AutofillExternalDelegate
const std::vector<string16>& autofill_icons,
const std::vector<int>& autofill_unique_ids);
- // Remove the given Autocomplete entry from the DB.
- virtual void RemoveAutocompleteEntry(const string16& value);
-
- // Remove the given Autofill profile or credit credit.
- virtual void RemoveAutofillProfileOrCreditCard(int unique_id);
-
// Inform the delegate that the text field editing has ended. This is
// used to help record the metrics of when a new popup is shown.
void DidEndTextFieldEditing();
- // Inform the delegate that an Autofill suggestion has been chosen. Returns
- // true if the suggestion was selected.
- bool DidAcceptAutofillSuggestions(const string16& value,
- int unique_id,
- unsigned index);
-
- // Informs the delegate that the Autofill previewed form should be cleared.
- virtual void ClearPreviewedForm();
-
- // Hide the Autofill poup.
- virtual void HideAutofillPopup();
-
// Returns the delegate to its starting state by removing any page specific
// values or settings.
void Reset();
@@ -116,10 +102,13 @@ class AutofillExternalDelegate
const FormFieldData& form,
const PasswordFormFillData& fill_data);
+ virtual void HideAutofillPopup();
+
protected:
friend class content::WebContentsUserData<AutofillExternalDelegate>;
AutofillExternalDelegate(content::WebContents* web_contents,
AutofillManager* autofill_manager);
+ virtual ~AutofillExternalDelegate();
// Displays the Autofill results to the user with an external Autofill popup
// that lives completely in the browser. The suggestions have been correctly
@@ -128,22 +117,15 @@ class AutofillExternalDelegate
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) = 0;
-
- // Handle platform-dependent hiding.
- virtual void HideAutofillPopupInternal() = 0;
+ const std::vector<int>& autofill_unique_ids);
- // Create and position the popup given the bounds of the element it is
- // popping up for.
- virtual void CreatePopupForElement(const gfx::Rect& element_bounds) = 0;
+ // Create the popup if it doesn't already exist. |element_bounds| is the
+ // bounding rect for the element it is popping up for.
+ virtual void EnsurePopupForElement(const gfx::Rect& element_bounds);
- // Return the web_contents associated with this delegate.
content::WebContents* web_contents() { return web_contents_; }
- // Return the bounds of the field currently selected.
- const gfx::Rect& field_bounds() { return field_bounds_; }
-
- bool popup_visible() const { return popup_visible_; }
+ AutofillPopupControllerImpl* controller() { return controller_; }
private:
// Fills the form with the Autofill data corresponding to |unique_id|.
@@ -178,8 +160,10 @@ class AutofillExternalDelegate
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;
+ // The web_contents associated with this delegate.
content::WebContents* web_contents_; // weak; owns me.
AutofillManager* autofill_manager_; // weak.
+ AutofillPopupControllerImpl* controller_; // weak.
// Password Autofill manager, handles all password-related Autofilling.
PasswordAutofillManager password_autofill_manager_;
@@ -202,12 +186,6 @@ class AutofillExternalDelegate
// currently editing? Used to keep track of state for metrics logging.
bool has_shown_autofill_popup_for_current_edit_;
- // Used to indicate if a popup is currently being shown or not.
- bool popup_visible_;
-
- // The bounds of the field currently selected.
- gfx::Rect field_bounds_;
-
// The current data list values.
std::vector<string16> data_list_values_;
std::vector<string16> data_list_labels_;
diff --git a/chrome/browser/autofill/autofill_popup_view_browsertest.cc b/chrome/browser/autofill/autofill_external_delegate_browsertest.cc
index 3d23608..2cef3e0 100644
--- a/chrome/browser/autofill/autofill_popup_view_browsertest.cc
+++ b/chrome/browser/autofill/autofill_external_delegate_browsertest.cc
@@ -2,11 +2,11 @@
// 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/autofill/autofill_manager.h"
#include "chrome/browser/autofill/test_autofill_external_delegate.h"
+#include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h"
+#include "chrome/browser/ui/autofill/autofill_popup_view.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/common/url_constants.h"
@@ -27,13 +27,12 @@ using testing::_;
namespace {
-class MockAutofillExternalDelegate :
- public autofill::TestAutofillExternalDelegate {
+class MockAutofillExternalDelegate : public AutofillExternalDelegate {
public:
- explicit MockAutofillExternalDelegate(content::WebContents* web_contents) :
- TestAutofillExternalDelegate(
- web_contents,
- AutofillManager::FromWebContents(web_contents)) {}
+ explicit MockAutofillExternalDelegate(content::WebContents* web_contents)
+ : AutofillExternalDelegate(
+ web_contents,
+ AutofillManager::FromWebContents(web_contents)) {}
~MockAutofillExternalDelegate() {}
virtual void SelectAutofillSuggestionAtIndex(int unique_id)
@@ -41,57 +40,64 @@ class MockAutofillExternalDelegate :
virtual void ClearPreviewedForm() OVERRIDE {}
- MOCK_METHOD0(HideAutofillPopupInternal, void());
-};
-
-class TestAutofillPopupView : public AutofillPopupView {
- public:
- TestAutofillPopupView(
- content::WebContents* web_contents,
- AutofillExternalDelegate* autofill_external_delegate)
- : AutofillPopupView(web_contents,
- autofill_external_delegate,
- gfx::Rect()) {}
- virtual ~TestAutofillPopupView() {}
-
- MOCK_METHOD0(Hide, void());
-
- protected:
- virtual void ShowInternal() OVERRIDE {}
-
- virtual void InvalidateRow(size_t row) OVERRIDE {}
+ AutofillPopupControllerImpl* GetController() {
+ return controller();
+ }
- virtual void UpdateBoundsAndRedrawPopupInternal() OVERRIDE {}
+ MOCK_METHOD0(HideAutofillPopup, void());
};
} // namespace
-class AutofillPopupViewBrowserTest : public InProcessBrowserTest {
+class AutofillExternalDelegateBrowserTest
+ : public InProcessBrowserTest,
+ public content::WebContentsObserver {
public:
- AutofillPopupViewBrowserTest() {}
- virtual ~AutofillPopupViewBrowserTest() {}
+ AutofillExternalDelegateBrowserTest() {}
+ virtual ~AutofillExternalDelegateBrowserTest() {}
virtual void SetUpOnMainThread() OVERRIDE {
web_contents_ = chrome::GetActiveWebContents(browser());
ASSERT_TRUE(web_contents_ != NULL);
+ Observe(web_contents_);
- autofill_external_delegate_.reset(new MockAutofillExternalDelegate(
- web_contents_));
- autofill_popup_view_.reset(new TestAutofillPopupView(
- web_contents_,
- autofill_external_delegate_.get()));
+ autofill_external_delegate_.reset(
+ new MockAutofillExternalDelegate(web_contents_));
+ }
+
+ // Normally the WebContents will automatically delete the delegate, but here
+ // the delegate is owned by this test, so we have to manually destroy.
+ virtual void WebContentsDestroyed(content::WebContents* web_contents)
+ OVERRIDE {
+ DCHECK_EQ(web_contents_, web_contents);
+ autofill_external_delegate_.reset();
}
protected:
content::WebContents* web_contents_;
- scoped_ptr<TestAutofillPopupView> autofill_popup_view_;
scoped_ptr<MockAutofillExternalDelegate> autofill_external_delegate_;
};
-IN_PROC_BROWSER_TEST_F(AutofillPopupViewBrowserTest,
- SwitchTabAndHideAutofillPopup) {
+#if defined(OS_MACOSX)
+// TODO(estade): Mac doesn't have an implementation for the view yet, so these
+// are disabled.
+#define MAYBE_SwitchTabAndHideAutofillPopup \
+ DISABLED_SwitchTabAndHideAutofillPopup
+#define MAYBE_TestPageNavigationHidingAutofillPopup \
+ DISABLED_TestPageNavigationHidingAutofillPopup
+#define MAYBE_CloseWidgetAndNoLeaking \
+ DISABLED_CloseWidgetAndNoLeaking
+#else
+#define MAYBE_SwitchTabAndHideAutofillPopup SwitchTabAndHideAutofillPopup
+#define MAYBE_TestPageNavigationHidingAutofillPopup \
+ TestPageNavigationHidingAutofillPopup
+#define MAYBE_CloseWidgetAndNoLeaking CloseWidgetAndNoLeaking
+#endif
+
+IN_PROC_BROWSER_TEST_F(AutofillExternalDelegateBrowserTest,
+ MAYBE_SwitchTabAndHideAutofillPopup) {
EXPECT_CALL(*autofill_external_delegate_,
- HideAutofillPopupInternal()).Times(AtLeast(1));
+ HideAutofillPopup()).Times(AtLeast(1));
autofill::GenerateTestAutofillPopup(autofill_external_delegate_.get());
@@ -105,10 +111,10 @@ IN_PROC_BROWSER_TEST_F(AutofillPopupViewBrowserTest,
// The mock verifies that the call was made.
}
-IN_PROC_BROWSER_TEST_F(AutofillPopupViewBrowserTest,
- TestPageNavigationHidingAutofillPopup) {
+IN_PROC_BROWSER_TEST_F(AutofillExternalDelegateBrowserTest,
+ MAYBE_TestPageNavigationHidingAutofillPopup) {
EXPECT_CALL(*autofill_external_delegate_,
- HideAutofillPopupInternal()).Times(AtLeast(1));
+ HideAutofillPopup()).Times(AtLeast(1));
autofill::GenerateTestAutofillPopup(autofill_external_delegate_.get());
@@ -126,3 +132,15 @@ IN_PROC_BROWSER_TEST_F(AutofillPopupViewBrowserTest,
// The mock verifies that the call was made.
}
+
+IN_PROC_BROWSER_TEST_F(AutofillExternalDelegateBrowserTest,
+ MAYBE_CloseWidgetAndNoLeaking) {
+ EXPECT_CALL(*autofill_external_delegate_,
+ HideAutofillPopup()).Times(AtLeast(1));
+
+ autofill::GenerateTestAutofillPopup(autofill_external_delegate_.get());
+
+ // Delete the view from under the delegate to ensure that the
+ // delegate and the controller can handle the popup getting deleted elsewhere.
+ autofill_external_delegate_->GetController()->view()->Hide();
+}
diff --git a/chrome/browser/autofill/autofill_external_delegate_unittest.cc b/chrome/browser/autofill/autofill_external_delegate_unittest.cc
index a1b834a..0b6f3fd 100644
--- a/chrome/browser/autofill/autofill_external_delegate_unittest.cc
+++ b/chrome/browser/autofill/autofill_external_delegate_unittest.cc
@@ -40,10 +40,6 @@ class MockAutofillExternalDelegate :
: TestAutofillExternalDelegate(web_contents, autofill_manger) {}
~MockAutofillExternalDelegate() {}
- bool popup_visible() {
- return autofill::TestAutofillExternalDelegate::popup_visible();
- }
-
MOCK_METHOD4(ApplyAutofillSuggestions, void(
const std::vector<string16>& autofill_values,
const std::vector<string16>& autofill_labels,
@@ -52,10 +48,9 @@ class MockAutofillExternalDelegate :
MOCK_METHOD0(ClearPreviewedForm, void());
- MOCK_METHOD1(CreatePopupForElement, void(const gfx::Rect& element_bounds));
+ MOCK_METHOD1(EnsurePopupForElement, void(const gfx::Rect& element_bounds));
- private:
- virtual void HideAutofillPopupInternal() {};
+ MOCK_METHOD0(HideAutofillPopup, void());
};
class MockAutofillManager : public AutofillManager {
@@ -96,12 +91,13 @@ class AutofillExternalDelegateUnitTest
field.should_autocomplete = true;
const gfx::Rect element_bounds;
- EXPECT_CALL(*external_delegate_, CreatePopupForElement(element_bounds));
+ EXPECT_CALL(*external_delegate_, EnsurePopupForElement(element_bounds));
external_delegate_->OnQuery(query_id, form, field, element_bounds, false);
}
scoped_refptr<MockAutofillManager> autofill_manager_;
- scoped_ptr<MockAutofillExternalDelegate> external_delegate_;
+ scoped_ptr<testing::NiceMock<MockAutofillExternalDelegate> >
+ external_delegate_;
private:
virtual void SetUp() OVERRIDE {
@@ -110,9 +106,10 @@ class AutofillExternalDelegateUnitTest
autofill_manager_ = new MockAutofillManager(
web_contents(),
TabAutofillManagerDelegate::FromWebContents(web_contents()));
- external_delegate_.reset(new MockAutofillExternalDelegate(
- web_contents(),
- autofill_manager_));
+ external_delegate_.reset(
+ new testing::NiceMock<MockAutofillExternalDelegate>(
+ web_contents(),
+ autofill_manager_));
}
virtual void TearDown() OVERRIDE {
@@ -151,19 +148,16 @@ TEST_F(AutofillExternalDelegateUnitTest, TestExternalDelegateVirtualCalls) {
autofill_item,
autofill_item,
autofill_ids);
- EXPECT_TRUE(external_delegate_->popup_visible());
-
- // Called when hiding the popup.
- EXPECT_CALL(*external_delegate_, ClearPreviewedForm());
// Called by DidAutofillSuggestions, add expectation to remove warning.
EXPECT_CALL(*autofill_manager_, OnFillAutofillFormData(_, _, _, _));
+ EXPECT_CALL(*external_delegate_, HideAutofillPopup());
+
// This should trigger a call to hide the popup since
// we've selected an option.
- external_delegate_->DidAcceptAutofillSuggestions(autofill_item[0],
- autofill_ids[0], 0);
- EXPECT_FALSE(external_delegate_->popup_visible());
+ external_delegate_->DidAcceptAutofillSuggestion(autofill_item[0],
+ autofill_ids[0], 0);
}
// Test that data list elements for a node will appear in the Autofill popup.
@@ -231,7 +225,7 @@ TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateInvalidUniqueId) {
// Ensure it doesn't try to fill the form in with the negative id.
EXPECT_CALL(*autofill_manager_, OnFillAutofillFormData(_, _, _, _)).Times(0);
- external_delegate_->DidAcceptAutofillSuggestions(string16(), -1, 0);
+ external_delegate_->DidAcceptAutofillSuggestion(string16(), -1, 0);
}
// Test that the ClearPreview IPC is only sent the form was being previewed
@@ -254,18 +248,14 @@ TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateClearPreviewedForm) {
// Test that the popup is hidden once we are done editing the autofill field.
TEST_F(AutofillExternalDelegateUnitTest,
ExternalDelegateHidePopupAfterEditing) {
- EXPECT_CALL(*external_delegate_, CreatePopupForElement(_));
+ EXPECT_CALL(*external_delegate_, EnsurePopupForElement(_));
EXPECT_CALL(*external_delegate_, ApplyAutofillSuggestions(_, _, _, _));
autofill::GenerateTestAutofillPopup(external_delegate_.get());
- EXPECT_TRUE(external_delegate_->popup_visible());
- // Called when hiding the popup.
- EXPECT_CALL(*external_delegate_, ClearPreviewedForm());
+ EXPECT_CALL(*external_delegate_, HideAutofillPopup());
external_delegate_->DidEndTextFieldEditing();
-
- EXPECT_FALSE(external_delegate_->popup_visible());
}
// Test that the popup is marked as visible after recieving password
@@ -279,7 +269,7 @@ TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegatePasswordSuggestions) {
field.should_autocomplete = true;
const gfx::Rect element_bounds;
- EXPECT_CALL(*external_delegate_, CreatePopupForElement(element_bounds));
+ EXPECT_CALL(*external_delegate_, EnsurePopupForElement(element_bounds));
// The enums must be cast to ints to prevent compile errors on linux_rel.
EXPECT_CALL(*external_delegate_,
@@ -290,19 +280,16 @@ TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegatePasswordSuggestions) {
external_delegate_->OnShowPasswordSuggestions(suggestions,
field,
element_bounds);
- EXPECT_TRUE(external_delegate_->popup_visible());
// Called by DidAutofillSuggestions, add expectation to remove warning.
EXPECT_CALL(*autofill_manager_, OnFillAutofillFormData(_, _, _, _));
- // Called when hiding the popup.
- EXPECT_CALL(*external_delegate_, ClearPreviewedForm());
+ EXPECT_CALL(*external_delegate_, HideAutofillPopup());
// This should trigger a call to hide the popup since
// we've selected an option.
- external_delegate_->DidAcceptAutofillSuggestions(
+ external_delegate_->DidAcceptAutofillSuggestion(
suggestions[0],
WebAutofillClient::MenuItemIDPasswordEntry,
0);
- EXPECT_FALSE(external_delegate_->popup_visible());
}
diff --git a/chrome/browser/autofill/autofill_popup_delegate.h b/chrome/browser/autofill/autofill_popup_delegate.h
new file mode 100644
index 0000000..6411766
--- /dev/null
+++ b/chrome/browser/autofill/autofill_popup_delegate.h
@@ -0,0 +1,37 @@
+// 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_DELEGATE_H_
+#define CHROME_BROWSER_AUTOFILL_AUTOFILL_POPUP_DELEGATE_H_
+
+#include "base/string16.h"
+
+// An interface for interaction with AutofillPopupController. Will be notified
+// of events by the controller.
+class AutofillPopupDelegate {
+ public:
+ // Called when the autofill suggestion indicated by |unique_id| has been
+ // temporarily selected (e.g., hovered).
+ virtual void SelectAutofillSuggestionAtIndex(int unique_id) = 0;
+
+ // Inform the delegate that an Autofill suggestion has been chosen. Returns
+ // true if the suggestion was selected.
+ virtual bool DidAcceptAutofillSuggestion(const string16& value,
+ int unique_id,
+ unsigned index) = 0;
+
+ // Remove the given Autocomplete entry from the DB.
+ virtual void RemoveAutocompleteEntry(const string16& value) = 0;
+
+ // Remove the given Autofill profile or credit credit.
+ virtual void RemoveAutofillProfileOrCreditCard(int unique_id) = 0;
+
+ // Informs the delegate that the Autofill previewed form should be cleared.
+ virtual void ClearPreviewedForm() = 0;
+
+ // Called to inform the delegate the controller is experiencing destruction.
+ virtual void ControllerDestroyed() = 0;
+};
+
+#endif // CHROME_BROWSER_AUTOFILL_AUTOFILL_POPUP_DELEGATE_H_
diff --git a/chrome/browser/autofill/autofill_popup_unittest.cc b/chrome/browser/autofill/autofill_popup_unittest.cc
deleted file mode 100644
index c4a99eb..0000000
--- a/chrome/browser/autofill/autofill_popup_unittest.cc
+++ /dev/null
@@ -1,205 +0,0 @@
-// 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 "base/memory/scoped_ptr.h"
-#include "chrome/browser/autofill/autofill_popup_view.h"
-#include "chrome/browser/autofill/test_autofill_external_delegate.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebAutofillClient.h"
-#include "ui/gfx/rect.h"
-
-using ::testing::_;
-using ::testing::AtLeast;
-using WebKit::WebAutofillClient;
-
-namespace {
-
-class MockAutofillExternalDelegate :
- public autofill::TestAutofillExternalDelegate {
- public:
- MockAutofillExternalDelegate() : TestAutofillExternalDelegate(NULL, NULL) {};
- virtual ~MockAutofillExternalDelegate() {};
-
- virtual void SelectAutofillSuggestionAtIndex(int unique_id)
- OVERRIDE {}
- virtual void RemoveAutocompleteEntry(const string16& value) OVERRIDE {}
- virtual void RemoveAutofillProfileOrCreditCard(int unique_id) OVERRIDE {}
- virtual void ClearPreviewedForm() OVERRIDE {}
-
- MOCK_METHOD0(HideAutofillPopupInternal, void());
-};
-
-class TestAutofillPopupView : public AutofillPopupView {
- public:
- explicit TestAutofillPopupView(AutofillExternalDelegate* external_delegate) :
- AutofillPopupView(NULL, external_delegate, gfx::Rect()) {}
- virtual ~TestAutofillPopupView() {}
-
- // Making protected functions public for testing
- const std::vector<string16>& autofill_values() const {
- return AutofillPopupView::autofill_values();
- }
- int selected_line() const {
- return AutofillPopupView::selected_line();
- }
- void SetSelectedLine(size_t selected_line) {
- AutofillPopupView::SetSelectedLine(selected_line);
- }
- void SelectNextLine() {
- AutofillPopupView::SelectNextLine();
- }
- void SelectPreviousLine() {
- AutofillPopupView::SelectPreviousLine();
- }
- bool RemoveSelectedLine() {
- return AutofillPopupView::RemoveSelectedLine();
- }
-
- MOCK_METHOD1(InvalidateRow, void(size_t));
- MOCK_METHOD0(Hide, void());
- MOCK_METHOD0(UpdateBoundsAndRedrawPopupInternal, void());
-
- private:
- virtual void ShowInternal() OVERRIDE {}
-};
-
-} // namespace
-
-class AutofillPopupViewUnitTest : public ::testing::Test {
- public:
- AutofillPopupViewUnitTest() {
- autofill_popup_view_.reset(new TestAutofillPopupView(&external_delegate_));
- }
- virtual ~AutofillPopupViewUnitTest() {}
-
-protected:
- scoped_ptr<TestAutofillPopupView> autofill_popup_view_;
- MockAutofillExternalDelegate external_delegate_;
-};
-
-TEST_F(AutofillPopupViewUnitTest, SetBounds) {
- // Ensure the popup size can be set and causes a redraw.
- gfx::Rect popup_bounds(10, 10, 100, 100);
-
- EXPECT_CALL(*autofill_popup_view_, UpdateBoundsAndRedrawPopupInternal());
-
- autofill_popup_view_->SetPopupBounds(popup_bounds);
-
- EXPECT_EQ(popup_bounds, autofill_popup_view_->popup_bounds());
-}
-
-TEST_F(AutofillPopupViewUnitTest, ChangeSelectedLine) {
- // Set up the popup.
- std::vector<string16> autofill_values(2, string16());
- std::vector<int> autofill_ids(2, 0);
- autofill_popup_view_->Show(autofill_values, autofill_values, autofill_values,
- autofill_ids);
-
- // To remove warnings.
- EXPECT_CALL(*autofill_popup_view_, InvalidateRow(_)).Times(AtLeast(0));
-
- EXPECT_LT(autofill_popup_view_->selected_line(), 0);
- // Check that there are at least 2 values so that the first and last selection
- // are different.
- EXPECT_GE(2,
- static_cast<int>(autofill_popup_view_->autofill_values().size()));
-
- // Test wrapping before the front.
- autofill_popup_view_->SelectPreviousLine();
- EXPECT_EQ(
- static_cast<int>(autofill_popup_view_->autofill_values().size() - 1),
- autofill_popup_view_->selected_line());
-
- // Test wrapping after the end.
- autofill_popup_view_->SelectNextLine();
- EXPECT_EQ(0, autofill_popup_view_->selected_line());
-}
-
-TEST_F(AutofillPopupViewUnitTest, RedrawSelectedLine) {
- // Set up the popup.
- std::vector<string16> autofill_values(2, string16());
- std::vector<int> autofill_ids(2, 0);
- autofill_popup_view_->Show(autofill_values, autofill_values, autofill_values,
- autofill_ids);
-
- // Make sure that when a new line is selected, it is invalidated so it can
- // be updated to show it is selected.
- int selected_line = 0;
- EXPECT_CALL(*autofill_popup_view_, InvalidateRow(selected_line));
- autofill_popup_view_->SetSelectedLine(selected_line);
-
- // Ensure that the row isn't invalidated if it didn't change.
- EXPECT_CALL(*autofill_popup_view_, InvalidateRow(selected_line)).Times(0);
- autofill_popup_view_->SetSelectedLine(selected_line);
-
- // Change back to no selection.
- EXPECT_CALL(*autofill_popup_view_, InvalidateRow(selected_line));
- autofill_popup_view_->SetSelectedLine(-1);
-}
-
-TEST_F(AutofillPopupViewUnitTest, RemoveLine) {
- // Set up the popup.
- std::vector<string16> autofill_values(3, string16());
- std::vector<int> autofill_ids;
- autofill_ids.push_back(1);
- autofill_ids.push_back(1);
- autofill_ids.push_back(WebAutofillClient::MenuItemIDAutofillOptions);
- autofill_popup_view_->Show(autofill_values, autofill_values, autofill_values,
- autofill_ids);
-
- // Generate a popup, so it can be hidden later. It doesn't matter what the
- // external_delegate thinks is being shown in the process, since we are just
- // testing the popup here.
- autofill::GenerateTestAutofillPopup(&external_delegate_);
-
- // To remove warnings.
- EXPECT_CALL(*autofill_popup_view_, InvalidateRow(_)).Times(AtLeast(0));
-
- // No line is selected so the removal should fail.
- EXPECT_FALSE(autofill_popup_view_->RemoveSelectedLine());
-
- // Try to remove the last entry and ensure it fails (it is an option).
- autofill_popup_view_->SetSelectedLine(
- autofill_popup_view_->autofill_values().size() - 1);
- EXPECT_FALSE(autofill_popup_view_->RemoveSelectedLine());
- EXPECT_LE(0, autofill_popup_view_->selected_line());
-
- // Remove the first entry. The popup should be redrawn since its size has
- // changed.
- EXPECT_CALL(*autofill_popup_view_, UpdateBoundsAndRedrawPopupInternal());
- autofill_popup_view_->SetSelectedLine(0);
- EXPECT_TRUE(autofill_popup_view_->RemoveSelectedLine());
-
- // Remove the last entry. The popup should then be hidden since there are
- // no Autofill entries left.
- EXPECT_CALL(external_delegate_, HideAutofillPopupInternal());
-
- autofill_popup_view_->SetSelectedLine(0);
- EXPECT_TRUE(autofill_popup_view_->RemoveSelectedLine());
-}
-
-TEST_F(AutofillPopupViewUnitTest, SkipSeparator) {
- // Set up the popup.
- std::vector<string16> autofill_values(3, string16());
- std::vector<int> autofill_ids;
- autofill_ids.push_back(1);
- autofill_ids.push_back(WebAutofillClient::MenuItemIDSeparator);
- autofill_ids.push_back(WebAutofillClient::MenuItemIDAutofillOptions);
- autofill_popup_view_->Show(autofill_values, autofill_values, autofill_values,
- autofill_ids);
-
- // To remove warnings.
- EXPECT_CALL(*autofill_popup_view_, InvalidateRow(_)).Times(AtLeast(0));
-
- autofill_popup_view_->SetSelectedLine(0);
-
- // Make sure next skips the unselectable separator.
- autofill_popup_view_->SelectNextLine();
- EXPECT_EQ(2, autofill_popup_view_->selected_line());
-
- // Make sure previous skips the unselectable separator.
- autofill_popup_view_->SelectPreviousLine();
- EXPECT_EQ(0, autofill_popup_view_->selected_line());
-}
diff --git a/chrome/browser/autofill/autofill_popup_view.h b/chrome/browser/autofill/autofill_popup_view.h
deleted file mode 100644
index aabbc2f..0000000
--- a/chrome/browser/autofill/autofill_popup_view.h
+++ /dev/null
@@ -1,195 +0,0 @@
-// 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_
-
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/string16.h"
-#include "ui/gfx/font.h"
-#include "ui/gfx/rect.h"
-
-namespace content {
-class WebContents;
-}
-
-class AutofillExternalDelegate;
-
-class AutofillPopupView {
- public:
- explicit AutofillPopupView(content::WebContents* web_contents,
- AutofillExternalDelegate* external_delegate_,
- const gfx::Rect& element_bounds);
- virtual ~AutofillPopupView();
-
- // Hide the popup from view. Platform-indepent work.
- virtual void Hide() = 0;
-
- // Display the autofill popup and fill it in with the values passed in.
- // Platform-independent work.
- 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);
-
- // Update the bounds of the popup.
- void SetPopupBounds(const gfx::Rect& bounds);
-
- // Sets the current Autofill pointer to NULL, used when the popup can outlive
- // the delegate.
- void ClearExternalDelegate();
-
- const gfx::Rect& popup_bounds() { return popup_bounds_; }
-
- protected:
- // Display the autofill popup and fill it in with the values passed in.
- // Platform-dependent work.
- virtual void ShowInternal() = 0;
-
- // Invalidate the given row and redraw it.
- virtual void InvalidateRow(size_t row) = 0;
-
- // Ensure the popup is properly placed at |element_bounds_|.
- virtual void UpdateBoundsAndRedrawPopupInternal() = 0;
-
- AutofillExternalDelegate* external_delegate() { return external_delegate_; }
-
- const gfx::Rect& element_bounds() const { return element_bounds_; }
-
- const std::vector<string16>& autofill_values() const {
- return autofill_values_;
- }
- const std::vector<string16>& autofill_labels() const {
- return autofill_labels_;
- }
- const std::vector<string16>& autofill_icons() const {
- return autofill_icons_;
- }
- const std::vector<int>& autofill_unique_ids() const {
- return autofill_unique_ids_;
- }
-
-#if !defined(OS_ANDROID)
- const gfx::Font& label_font() const { return label_font_; }
- const gfx::Font& value_font() const { return value_font_; }
-#endif
-
- int selected_line() const { return selected_line_; }
- bool delete_icon_selected() const { return delete_icon_selected_; }
-
- // Recalculate the height and width of the popup and trigger a redraw.
- void UpdateBoundsAndRedrawPopup();
-
- // Change which line is selected by the user, based on coordinates.
- void SetSelectedPosition(int x, int y);
-
- // Select the value at the given position.
- void AcceptSelectedPosition(int x, int y);
-
- // Change which line is currently selected by the user.
- void SetSelectedLine(int selected_line);
-
- // Clear the currently selected line so that nothing is selected.
- void ClearSelectedLine();
-
- // Increase the selected line by 1, properly handling wrapping.
- void SelectNextLine();
-
- // Decrease the selected line by 1, properly handling wrapping.
- void SelectPreviousLine();
-
- // The user has choosen the selected line.
- bool AcceptSelectedLine();
-
- // The user has removed a suggestion.
- bool RemoveSelectedLine();
-
- // Get the resource value for the given resource, returning -1 if the
- // resource isn't recognized.
- int GetIconResourceID(const string16& resource_name);
-
- // Returns true if the given id refers to an element that can be deleted.
- bool CanDelete(int id);
-
-#if !defined(OS_ANDROID)
- // Get width of popup needed by values.
- int GetPopupRequiredWidth();
-
- // Get height of popup needed by values.
- int GetPopupRequiredHeight();
-#endif
-
- // Convert a y-coordinate to the closest line.
- int LineFromY(int y);
-
- // Get the height of the given row.
- int GetRowHeightFromId(int unique_id);
-
- // Returns the rectangle containing the item at position |index| in the popup.
- gfx::Rect GetRectForRow(size_t row, int width);
-
- // Returns true if the given |x| and |y| coordinates refer to a point that
- // hits the delete icon in the current selected line.
- bool DeleteIconIsSelected(int x, int y);
-
- // Constants that are needed by the subclasses.
- // The size of the boarder around the entire results popup, in pixels.
- static const size_t kBorderThickness;
-
- // The amount of padding between icons in pixels.
- static const size_t kIconPadding;
-
- // The amount of padding at the end of the popup in pixels.
- static const size_t kEndPadding;
-
- // Height of the delete icon in pixels.
- static const size_t kDeleteIconHeight;
-
- // Width of the delete icon in pixels.
- static const size_t kDeleteIconWidth;
-
- // Height of the Autofill icons in pixels.
- static const size_t kAutofillIconHeight;
-
- // Width of the Autofill icons in pixels.
- static const size_t kAutofillIconWidth;
-
- private:
- // Returns true if the given id refers to an element that can be accepted.
- bool CanAccept(int id);
-
- // Returns true if the popup still has non-options entries to show the user.
- bool HasAutofillEntries();
-
- AutofillExternalDelegate* external_delegate_;
-
- // The bounds of the text element that is the focus of the Autofill.
- const gfx::Rect element_bounds_;
-
- // The bounds of the Autofill popup.
- gfx::Rect popup_bounds_;
-
- // The current Autofill query values.
- std::vector<string16> autofill_values_;
- std::vector<string16> autofill_labels_;
- std::vector<string16> autofill_icons_;
- std::vector<int> autofill_unique_ids_;
-
-#if !defined(OS_ANDROID)
- // The fonts for the popup text.
- gfx::Font value_font_;
- gfx::Font label_font_;
-#endif
-
- // The line that is currently selected by the user.
- // |kNoSelection| indicates that no line is currently selected.
- int selected_line_;
-
- // Used to indicate if the delete icon within a row is currently selected.
- bool delete_icon_selected_;
-};
-
-#endif // CHROME_BROWSER_AUTOFILL_AUTOFILL_POPUP_VIEW_H_
diff --git a/chrome/browser/autofill/test_autofill_external_delegate.cc b/chrome/browser/autofill/test_autofill_external_delegate.cc
index 2610c58..90a03d5 100644
--- a/chrome/browser/autofill/test_autofill_external_delegate.cc
+++ b/chrome/browser/autofill/test_autofill_external_delegate.cc
@@ -40,9 +40,11 @@ void TestAutofillExternalDelegate::ApplyAutofillSuggestions(
const std::vector<string16>& autofill_icons,
const std::vector<int>& autofill_unique_ids) {}
-void TestAutofillExternalDelegate::HideAutofillPopupInternal() {}
+void TestAutofillExternalDelegate::HideAutofillPopup() {}
void TestAutofillExternalDelegate::CreatePopupForElement(
const gfx::Rect& element_bounds) {}
+void TestAutofillExternalDelegate::ControllerDestroyed() {}
+
} // namespace autofill
diff --git a/chrome/browser/autofill/test_autofill_external_delegate.h b/chrome/browser/autofill/test_autofill_external_delegate.h
index 186a30a..3a6ff22 100644
--- a/chrome/browser/autofill/test_autofill_external_delegate.h
+++ b/chrome/browser/autofill/test_autofill_external_delegate.h
@@ -31,10 +31,12 @@ class TestAutofillExternalDelegate : public AutofillExternalDelegate {
const std::vector<string16>& autofill_icons,
const std::vector<int>& autofill_unique_ids) OVERRIDE;
- virtual void HideAutofillPopupInternal() OVERRIDE;
+ virtual void HideAutofillPopup() OVERRIDE;
virtual void CreatePopupForElement(const gfx::Rect& element_bounds) OVERRIDE;
+ virtual void ControllerDestroyed() OVERRIDE;
+
private:
DISALLOW_COPY_AND_ASSIGN(TestAutofillExternalDelegate);
};
diff --git a/chrome/browser/ui/android/autofill/autofill_external_delegate.cc b/chrome/browser/ui/android/autofill/autofill_external_delegate.cc
deleted file mode 100644
index b4f7336..0000000
--- a/chrome/browser/ui/android/autofill/autofill_external_delegate.cc
+++ /dev/null
@@ -1,58 +0,0 @@
-// 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/ui/android/autofill/autofill_external_delegate.h"
-
-#include "base/string_util.h"
-#include "chrome/browser/autofill/autofill_manager.h"
-#include "chrome/browser/ui/android/autofill/autofill_popup_view_android.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/web_contents.h"
-
-void AutofillExternalDelegate::CreateForWebContentsAndManager(
- content::WebContents* web_contents,
- AutofillManager* autofill_manager) {
- if (FromWebContents(web_contents))
- return;
-
- web_contents->SetUserData(
- UserDataKey(),
- new AutofillExternalDelegateAndroid(web_contents, autofill_manager));
-}
-
-AutofillExternalDelegateAndroid::AutofillExternalDelegateAndroid(
- content::WebContents* web_contents, AutofillManager* manager)
- : AutofillExternalDelegate(web_contents, manager) {
-}
-
-AutofillExternalDelegateAndroid::~AutofillExternalDelegateAndroid() {
-}
-
-void AutofillExternalDelegateAndroid::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) {
- view_->Show(autofill_values,
- autofill_labels,
- autofill_icons,
- autofill_unique_ids);
-}
-
-void AutofillExternalDelegateAndroid::HideAutofillPopupInternal() {
- if (!view_.get())
- return;
-
- view_->Hide();
- view_.reset();
-}
-
-void AutofillExternalDelegateAndroid::CreatePopupForElement(
- const gfx::Rect& element_bounds) {
- // TODO(aurimas): remove temporary fix for crbug.com/164900
- HideAutofillPopupInternal();
-
- content::WebContents* contents = web_contents();
- view_.reset(new AutofillPopupViewAndroid(contents, this, element_bounds));
-}
diff --git a/chrome/browser/ui/android/autofill/autofill_external_delegate.h b/chrome/browser/ui/android/autofill/autofill_external_delegate.h
deleted file mode 100644
index e93b14b..0000000
--- a/chrome/browser/ui/android/autofill/autofill_external_delegate.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// 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_ANDROID_AUTOFILL_AUTOFILL_EXTERNAL_DELEGATE_H_
-#define CHROME_BROWSER_UI_ANDROID_AUTOFILL_AUTOFILL_EXTERNAL_DELEGATE_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "chrome/browser/autofill/autofill_external_delegate.h"
-
-class AutofillPopupViewAndroid;
-
-// Android implementation of external delegate for display and selection of
-// Autofill suggestions.
-class AutofillExternalDelegateAndroid : public AutofillExternalDelegate {
- public:
- AutofillExternalDelegateAndroid(content::WebContents* web_contents,
- AutofillManager* manager);
- virtual ~AutofillExternalDelegateAndroid();
-
- protected:
- // AutofillExternalDelegate implementations.
- 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) OVERRIDE;
- virtual void CreatePopupForElement(const gfx::Rect& element_bounds) OVERRIDE;
- virtual void HideAutofillPopupInternal() OVERRIDE;
-
- private:
- scoped_ptr<AutofillPopupViewAndroid> view_;
-
- DISALLOW_COPY_AND_ASSIGN(AutofillExternalDelegateAndroid);
-};
-
-#endif // CHROME_BROWSER_UI_ANDROID_AUTOFILL_AUTOFILL_EXTERNAL_DELEGATE_H_
diff --git a/chrome/browser/ui/android/autofill/autofill_popup_view_android.cc b/chrome/browser/ui/android/autofill/autofill_popup_view_android.cc
index fc0a28b..ef09d7d 100644
--- a/chrome/browser/ui/android/autofill/autofill_popup_view_android.cc
+++ b/chrome/browser/ui/android/autofill/autofill_popup_view_android.cc
@@ -2,44 +2,37 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "autofill_popup_view_android.h"
+#include "chrome/browser/ui/android/autofill/autofill_popup_view_android.h"
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
-#include "base/android/scoped_java_ref.h"
-#include "chrome/browser/ui/android/autofill/autofill_external_delegate.h"
#include "chrome/browser/ui/android/window_android_helper.h"
+#include "chrome/browser/ui/autofill/autofill_popup_controller.h"
#include "content/public/browser/android/content_view_core.h"
-#include "content/public/browser/browser_thread.h"
#include "jni/AutofillPopupGlue_jni.h"
#include "ui/gfx/android/window_android.h"
#include "ui/gfx/rect.h"
using base::android::MethodID;
-using content::BrowserThread;
AutofillPopupViewAndroid::AutofillPopupViewAndroid(
- content::WebContents* web_contents,
- AutofillExternalDelegate* external_delegate,
- const gfx::Rect& element_bounds)
- : AutofillPopupView(web_contents, external_delegate, element_bounds),
- web_contents_(web_contents) {
+ AutofillPopupController* controller)
+ : controller_(controller) {
JNIEnv* env = base::android::AttachCurrentThread();
- content::ContentViewCore* content_view_core =
- content::ContentViewCore::FromWebContents(web_contents);
- ui::WindowAndroid* window_android =
- WindowAndroidHelper::FromWebContents(web_contents_)->GetWindowAndroid();
+ content::ContentViewCore* content_view_core = controller_->container_view();
- java_object_.Reset(Java_AutofillPopupGlue_create(env,
- reinterpret_cast<jint>(this), window_android->GetJavaObject().obj(),
+ java_object_.Reset(Java_AutofillPopupGlue_create(
+ env,
+ reinterpret_cast<jint>(this),
+ content_view_core->GetWindowAndroid()->GetJavaObject().obj(),
content_view_core->GetContainerViewDelegate().obj()));
}
AutofillPopupViewAndroid::~AutofillPopupViewAndroid() {
+ controller_->ViewDestroyed();
}
-void AutofillPopupViewAndroid::ShowInternal() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+void AutofillPopupViewAndroid::Show() {
UpdateBoundsAndRedrawPopup();
// We need an array of AutofillSuggestion.
@@ -48,15 +41,17 @@ void AutofillPopupViewAndroid::ShowInternal() {
base::android::GetClass(env,
"org/chromium/chrome/browser/autofill/AutofillSuggestion");
ScopedJavaLocalRef<jobjectArray> data_array(env,
- env->NewObjectArray(autofill_values().size(),
+ env->NewObjectArray(controller_->autofill_values().size(),
autofill_suggestion_clazz.obj(), NULL));
base::android::CheckException(env);
- for (size_t i = 0; i < autofill_values().size(); ++i) {
+ for (size_t i = 0; i < controller_->autofill_values().size(); ++i) {
ScopedJavaLocalRef<jstring> value =
- base::android::ConvertUTF16ToJavaString(env, autofill_values()[i]);
+ base::android::ConvertUTF16ToJavaString(
+ env, controller_->autofill_values()[i]);
ScopedJavaLocalRef<jstring> label =
- base::android::ConvertUTF16ToJavaString(env, autofill_labels()[i]);
- int unique_id = autofill_unique_ids()[i];
+ base::android::ConvertUTF16ToJavaString(
+ env, controller_->autofill_labels()[i]);
+ int unique_id = controller_->autofill_unique_ids()[i];
ScopedJavaLocalRef<jobject> data =
Java_AutofillPopupGlue_createAutofillSuggestion(env,
value.obj(),
@@ -68,42 +63,46 @@ void AutofillPopupViewAndroid::ShowInternal() {
Java_AutofillPopupGlue_show(env, java_object_.obj(), data_array.obj());
}
+
void AutofillPopupViewAndroid::Hide() {
JNIEnv* env = base::android::AttachCurrentThread();
Java_AutofillPopupGlue_dismissFromNative(env, java_object_.obj());
}
-void AutofillPopupViewAndroid::UpdateBoundsAndRedrawPopupInternal() {
+void AutofillPopupViewAndroid::UpdateBoundsAndRedrawPopup() {
JNIEnv* env = base::android::AttachCurrentThread();
Java_AutofillPopupGlue_setAnchorRect(env,
java_object_.obj(),
- element_bounds().x(),
- element_bounds().y(),
- element_bounds().width(),
- element_bounds().height());
+ controller_->element_bounds().x(),
+ controller_->element_bounds().y(),
+ controller_->element_bounds().width(),
+ controller_->element_bounds().height());
}
-void AutofillPopupViewAndroid::SuggestionSelected(JNIEnv *env,
+void AutofillPopupViewAndroid::SuggestionSelected(JNIEnv* env,
jobject obj,
jint list_index,
jstring value,
jint unique_id) {
string16 value_utf16 = base::android::ConvertJavaStringToUTF16(env, value);
- external_delegate()->DidAcceptAutofillSuggestions(value_utf16,
- unique_id,
- list_index);
+ controller_->AcceptAutofillSuggestion(value_utf16,
+ unique_id,
+ list_index);
}
-void AutofillPopupViewAndroid::Dismiss(JNIEnv *env,
- jobject obj) {
- external_delegate()->HideAutofillPopup();
+void AutofillPopupViewAndroid::Dismiss(JNIEnv* env, jobject obj) {
+ delete this;
}
-void AutofillPopupViewAndroid::InvalidateRow(size_t) {
-}
+void AutofillPopupViewAndroid::InvalidateRow(size_t) {}
// static
-bool AutofillPopupViewAndroid::RegisterAutofillPopupViewAndroid(
- JNIEnv* env) {
+bool AutofillPopupViewAndroid::RegisterAutofillPopupViewAndroid(JNIEnv* env) {
return RegisterNativesImpl(env);
}
+
+// static
+AutofillPopupView* AutofillPopupView::Create(
+ AutofillPopupController* controller) {
+ return new AutofillPopupViewAndroid(controller);
+}
diff --git a/chrome/browser/ui/android/autofill/autofill_popup_view_android.h b/chrome/browser/ui/android/autofill/autofill_popup_view_android.h
index b4f4d18..764abd6f 100644
--- a/chrome/browser/ui/android/autofill/autofill_popup_view_android.h
+++ b/chrome/browser/ui/android/autofill/autofill_popup_view_android.h
@@ -8,11 +8,10 @@
#include <jni.h>
#include "base/android/scoped_java_ref.h"
-#include "chrome/browser/autofill/autofill_popup_view.h"
+#include "base/compiler_specific.h"
+#include "chrome/browser/ui/autofill/autofill_popup_view.h"
-namespace content {
-class WebContents;
-}
+class AutofillPopupController;
namespace gfx {
class Rect;
@@ -20,10 +19,7 @@ class Rect;
class AutofillPopupViewAndroid : public AutofillPopupView {
public:
- AutofillPopupViewAndroid(content::WebContents* web_contents,
- AutofillExternalDelegate* external_delegate,
- const gfx::Rect& element_bounds);
- virtual ~AutofillPopupViewAndroid();
+ explicit AutofillPopupViewAndroid(AutofillPopupController* controller);
// --------------------------------------------------------------------------
// Methods called from Java via JNI
@@ -35,23 +31,23 @@ class AutofillPopupViewAndroid : public AutofillPopupView {
jstring value,
jint unique_id);
- // AutofillPopupView implementation.
- virtual void Hide() OVERRIDE;
-
void Dismiss(JNIEnv *env, jobject obj);
static bool RegisterAutofillPopupViewAndroid(JNIEnv* env);
protected:
- // AutofillPopupView implementations.
- virtual void ShowInternal() OVERRIDE;
+ // AutofillPopupView implementation.
+ virtual void Show() OVERRIDE;
+ virtual void Hide() OVERRIDE;
virtual void InvalidateRow(size_t row) OVERRIDE;
- virtual void UpdateBoundsAndRedrawPopupInternal() OVERRIDE;
+ virtual void UpdateBoundsAndRedrawPopup() OVERRIDE;
private:
- content::WebContents* web_contents_; // weak; owns me.
+ virtual ~AutofillPopupViewAndroid();
+
+ AutofillPopupController* controller_; // weak.
- // The corresponding AutofillExternalDelegate java object.
+ // The corresponding java object.
base::android::ScopedJavaGlobalRef<jobject> java_object_;
DISALLOW_COPY_AND_ASSIGN(AutofillPopupViewAndroid);
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller.h b/chrome/browser/ui/autofill/autofill_popup_controller.h
new file mode 100644
index 0000000..67f2ca9
--- /dev/null
+++ b/chrome/browser/ui/autofill/autofill_popup_controller.h
@@ -0,0 +1,93 @@
+// 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_AUTOFILL_AUTOFILL_POPUP_CONTROLLER_H_
+#define CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_POPUP_CONTROLLER_H_
+
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "ui/gfx/native_widget_types.h"
+
+namespace gfx {
+class Font;
+class Point;
+class Rect;
+}
+
+// This interface provides data to an AutofillPopupView.
+class AutofillPopupController {
+ public:
+ // Called when the view is going down.
+ virtual void ViewDestroyed() = 0;
+
+ // Recalculate the height and width of the popup and trigger a redraw.
+ virtual void UpdateBoundsAndRedrawPopup() = 0;
+
+ // Change which line is selected by the user, based on coordinates.
+ virtual void SetSelectedPosition(int x, int y) = 0;
+
+ // Accepts the described Autofill suggestion.
+ virtual bool AcceptAutofillSuggestion(const string16& value,
+ int unique_id,
+ unsigned index) = 0;
+
+ // Select the value at the given position.
+ virtual void AcceptSelectedPosition(int x, int y) = 0;
+
+ // Clear the currently selected line so that nothing is selected.
+ virtual void ClearSelectedLine() = 0;
+
+ // Get the resource value for the given resource, returning -1 if the
+ // resource isn't recognized.
+ virtual int GetIconResourceID(const string16& resource_name) = 0;
+
+ // Returns true if the given id refers to an element that can be deleted.
+ virtual bool CanDelete(int id) = 0;
+
+#if !defined(OS_ANDROID)
+ // Get width of popup needed by values.
+ virtual int GetPopupRequiredWidth() = 0;
+
+ // Get height of popup needed by values.
+ virtual int GetPopupRequiredHeight() = 0;
+#endif
+
+ // Updates the bounds of the popup and initiates a redraw.
+ virtual void SetPopupBounds(const gfx::Rect& bounds) = 0;
+
+ // Get the height of the given row.
+ virtual int GetRowHeightFromId(int unique_id) = 0;
+
+ // Returns the rectangle containing the item at position |row| in the popup.
+ // |row| is the index of the row, and |width| is its width.
+ virtual gfx::Rect GetRectForRow(size_t row, int width) = 0;
+
+ // The actual bounds of the popup.
+ virtual const gfx::Rect& popup_bounds() const = 0;
+
+ // The view that the form field element sits in.
+ virtual gfx::NativeView container_view() const = 0;
+
+ // The bounds of the form field element (relative to |container_origin|).
+ virtual const gfx::Rect& element_bounds() const = 0;
+
+ virtual const std::vector<string16>& autofill_values() const = 0;
+ virtual const std::vector<string16>& autofill_labels() const = 0;
+ virtual const std::vector<string16>& autofill_icons() const = 0;
+ virtual const std::vector<int>& autofill_unique_ids() const = 0;
+
+#if !defined(OS_ANDROID)
+ virtual const gfx::Font& label_font() const = 0;
+ virtual const gfx::Font& value_font() const = 0;
+#endif
+
+ virtual int selected_line() const = 0;
+ virtual bool delete_icon_hovered() const = 0;
+
+ protected:
+ virtual ~AutofillPopupController() {}
+};
+
+#endif // CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_POPUP_CONTROLLER_H_
diff --git a/chrome/browser/autofill/autofill_popup_view.cc b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
index 9713d3e..ae01eb0 100644
--- a/chrome/browser/autofill/autofill_popup_view.cc
+++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
@@ -2,14 +2,15 @@
// 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 "chrome/browser/ui/autofill/autofill_popup_controller_impl.h"
#include "base/logging.h"
#include "base/utf_string_conversions.h"
-#include "chrome/browser/autofill/autofill_external_delegate.h"
-#include "content/public/browser/web_contents.h"
+#include "chrome/browser/ui/autofill/autofill_popup_view.h"
+#include "content/public/browser/native_web_keyboard_event.h"
#include "grit/webkit_resources.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebAutofillClient.h"
+#include "ui/base/events/event.h"
using WebKit::WebAutofillClient;
@@ -33,6 +34,14 @@ const size_t kLabelPadding = 15;
// The maximum amount of characters to display from either the label or value.
const size_t kMaxTextLength = 15;
+#if !defined(OS_ANDROID)
+const size_t kIconPadding = AutofillPopupView::kIconPadding;
+const size_t kEndPadding = AutofillPopupView::kEndPadding;
+const size_t kDeleteIconHeight = AutofillPopupView::kDeleteIconHeight;
+const size_t kDeleteIconWidth = AutofillPopupView::kDeleteIconWidth;
+const size_t kAutofillIconWidth = AutofillPopupView::kAutofillIconWidth;
+#endif
+
struct DataResource {
const char* name;
int id;
@@ -51,36 +60,31 @@ const DataResource kDataResources[] = {
} // end namespace
-const size_t AutofillPopupView::kBorderThickness = 1;
-const size_t AutofillPopupView::kIconPadding = 5;
-const size_t AutofillPopupView::kEndPadding = 3;
-const size_t AutofillPopupView::kDeleteIconHeight = 16;
-const size_t AutofillPopupView::kDeleteIconWidth = 16;
-const size_t AutofillPopupView::kAutofillIconHeight = 16;
-const size_t AutofillPopupView::kAutofillIconWidth = 25;
-
-AutofillPopupView::AutofillPopupView(
- content::WebContents* web_contents,
- AutofillExternalDelegate* external_delegate,
+AutofillPopupControllerImpl::AutofillPopupControllerImpl(
+ AutofillPopupDelegate* delegate,
+ gfx::NativeView container_view,
const gfx::Rect& element_bounds)
- : external_delegate_(external_delegate),
+ : view_(NULL),
+ delegate_(delegate),
+ container_view_(container_view),
element_bounds_(element_bounds),
selected_line_(kNoSelection),
- delete_icon_selected_(false) {
- if (!web_contents)
- return;
-
+ delete_icon_hovered_(false) {
#if !defined(OS_ANDROID)
label_font_ = value_font_.DeriveFont(kLabelFontSizeDelta);
#endif
}
-AutofillPopupView::~AutofillPopupView() {}
+AutofillPopupControllerImpl::~AutofillPopupControllerImpl() {
+ if (delegate_)
+ delegate_->ControllerDestroyed();
+}
-void AutofillPopupView::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) {
+void AutofillPopupControllerImpl::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) {
autofill_values_ = autofill_values;
autofill_labels_ = autofill_labels;
autofill_icons_ = autofill_icons;
@@ -98,49 +102,233 @@ void AutofillPopupView::Show(const std::vector<string16>& autofill_values,
}
#endif
- ShowInternal();
+ if (!view_) {
+ view_ = AutofillPopupView::Create(this);
+ ShowView();
+ } else {
+ UpdateBoundsAndRedrawPopup();
+ }
}
-void AutofillPopupView::SetPopupBounds(const gfx::Rect& bounds) {
- popup_bounds_ = bounds;
- UpdateBoundsAndRedrawPopupInternal();
+void AutofillPopupControllerImpl::Hide() {
+ if (view_)
+ view_->Hide();
+ else
+ delete this;
+}
+
+void AutofillPopupControllerImpl::DelegateDestroyed() {
+ delegate_ = NULL;
+ Hide();
}
-void AutofillPopupView::ClearExternalDelegate() {
- external_delegate_ = NULL;
+void AutofillPopupControllerImpl::ViewDestroyed() {
+ delete this;
}
-void AutofillPopupView::UpdateBoundsAndRedrawPopup() {
+void AutofillPopupControllerImpl::UpdateBoundsAndRedrawPopup() {
#if !defined(OS_ANDROID)
popup_bounds_.set_width(GetPopupRequiredWidth());
popup_bounds_.set_height(GetPopupRequiredHeight());
#endif
- UpdateBoundsAndRedrawPopupInternal();
+ view_->UpdateBoundsAndRedrawPopup();
}
-void AutofillPopupView::SetSelectedPosition(int x, int y) {
+void AutofillPopupControllerImpl::SetSelectedPosition(int x, int y) {
int line = LineFromY(y);
SetSelectedLine(line);
- bool delete_icon_selected = DeleteIconIsSelected(x, y);
- if (delete_icon_selected != delete_icon_selected_) {
- delete_icon_selected_ = delete_icon_selected;
+ bool delete_icon_hovered = DeleteIconIsUnder(x, y);
+ if (delete_icon_hovered != delete_icon_hovered_) {
+ delete_icon_hovered_ = delete_icon_hovered;
InvalidateRow(selected_line());
}
}
-void AutofillPopupView::AcceptSelectedPosition(int x, int y) {
+bool AutofillPopupControllerImpl::AcceptAutofillSuggestion(
+ const string16& value,
+ int unique_id,
+ unsigned index) {
+ return delegate_->DidAcceptAutofillSuggestion(value, unique_id, index);
+}
+
+void AutofillPopupControllerImpl::AcceptSelectedPosition(int x, int y) {
DCHECK_EQ(selected_line(), LineFromY(y));
- if (DeleteIconIsSelected(x, y))
+ if (DeleteIconIsUnder(x, y))
RemoveSelectedLine();
else
AcceptSelectedLine();
}
-void AutofillPopupView::SetSelectedLine(int selected_line) {
+void AutofillPopupControllerImpl::ClearSelectedLine() {
+ SetSelectedLine(kNoSelection);
+}
+
+int AutofillPopupControllerImpl::GetIconResourceID(
+ const string16& resource_name) {
+ for (size_t i = 0; i < arraysize(kDataResources); ++i) {
+ if (resource_name == ASCIIToUTF16(kDataResources[i].name))
+ return kDataResources[i].id;
+ }
+
+ return -1;
+}
+
+bool AutofillPopupControllerImpl::CanDelete(int id) {
+ return id > 0 ||
+ id == WebAutofillClient::MenuItemIDAutocompleteEntry ||
+ id == WebAutofillClient::MenuItemIDPasswordEntry;
+}
+
+#if !defined(OS_ANDROID)
+int AutofillPopupControllerImpl::GetPopupRequiredWidth() {
+ if (value_font_.platform_font() == NULL ||
+ label_font_.platform_font() == NULL) {
+ // We can't calculate the size of the popup if the fonts
+ // aren't present.
+ return 0;
+ }
+
+ int popup_width = element_bounds().width();
+ DCHECK_EQ(autofill_values().size(), autofill_labels().size());
+ for (size_t i = 0; i < autofill_values().size(); ++i) {
+ int row_size = kEndPadding +
+ value_font_.GetStringWidth(autofill_values()[i]) +
+ kLabelPadding +
+ label_font_.GetStringWidth(autofill_labels()[i]);
+
+ // Add the Autofill icon size, if required.
+ if (!autofill_icons()[i].empty())
+ row_size += kAutofillIconWidth + kIconPadding;
+
+ // Add delete icon, if required.
+ if (CanDelete(autofill_unique_ids()[i]))
+ row_size += kDeleteIconWidth + kIconPadding;
+
+ // Add the padding at the end
+ row_size += kEndPadding;
+
+ popup_width = std::max(popup_width, row_size);
+ }
+
+ return popup_width;
+}
+
+int AutofillPopupControllerImpl::GetPopupRequiredHeight() {
+ int popup_height = 0;
+
+ for (size_t i = 0; i < autofill_unique_ids().size(); ++i) {
+ popup_height += GetRowHeightFromId(autofill_unique_ids()[i]);
+ }
+
+ return popup_height;
+}
+#endif // !defined(OS_ANDROID)
+
+int AutofillPopupControllerImpl::GetRowHeightFromId(int unique_id) {
+ if (unique_id == WebAutofillClient::MenuItemIDSeparator)
+ return kSeparatorHeight;
+
+ return kRowHeight;
+}
+
+gfx::Rect AutofillPopupControllerImpl::GetRectForRow(size_t row, int width) {
+ int top = 0;
+ for (size_t i = 0; i < row; ++i) {
+ top += GetRowHeightFromId(autofill_unique_ids()[i]);
+ }
+
+ return gfx::Rect(
+ 0, top, width, GetRowHeightFromId(autofill_unique_ids()[row]));
+}
+
+void AutofillPopupControllerImpl::SetPopupBounds(const gfx::Rect& bounds) {
+ popup_bounds_ = bounds;
+ UpdateBoundsAndRedrawPopup();
+}
+
+const gfx::Rect& AutofillPopupControllerImpl::popup_bounds() const {
+ return popup_bounds_;
+}
+
+gfx::NativeView AutofillPopupControllerImpl::container_view() const {
+ return container_view_;
+}
+
+const gfx::Rect& AutofillPopupControllerImpl::element_bounds() const {
+ return element_bounds_;
+}
+
+const std::vector<string16>& AutofillPopupControllerImpl::
+ autofill_values() const {
+ return autofill_values_;
+}
+
+const std::vector<string16>& AutofillPopupControllerImpl::
+ autofill_labels() const {
+ return autofill_labels_;
+}
+
+const std::vector<string16>& AutofillPopupControllerImpl::
+ autofill_icons() const {
+ return autofill_icons_;
+}
+
+const std::vector<int>& AutofillPopupControllerImpl::
+ autofill_unique_ids() const {
+ return autofill_unique_ids_;
+}
+
+#if !defined(OS_ANDROID)
+const gfx::Font& AutofillPopupControllerImpl::label_font() const {
+ return label_font_;
+}
+
+const gfx::Font& AutofillPopupControllerImpl::value_font() const {
+ return value_font_;
+}
+#endif
+
+int AutofillPopupControllerImpl::selected_line() const {
+ return selected_line_;
+}
+
+bool AutofillPopupControllerImpl::delete_icon_hovered() const {
+ return delete_icon_hovered_;
+}
+
+bool AutofillPopupControllerImpl::HandleKeyPressEvent(
+ const content::NativeWebKeyboardEvent& event) {
+ switch (event.windowsKeyCode) {
+ case ui::VKEY_UP:
+ SelectPreviousLine();
+ return true;
+ case ui::VKEY_DOWN:
+ SelectNextLine();
+ return true;
+ case ui::VKEY_PRIOR: // Page up.
+ SetSelectedLine(0);
+ return true;
+ case ui::VKEY_NEXT: // Page down.
+ SetSelectedLine(autofill_values().size() - 1);
+ return true;
+ case ui::VKEY_ESCAPE:
+ Hide();
+ return true;
+ case ui::VKEY_DELETE:
+ return (event.modifiers & content::NativeWebKeyboardEvent::ShiftKey) &&
+ RemoveSelectedLine();
+ case ui::VKEY_RETURN:
+ return AcceptSelectedLine();
+ default:
+ return false;
+ }
+}
+
+void AutofillPopupControllerImpl::SetSelectedLine(int selected_line) {
if (selected_line_ == selected_line)
return;
@@ -153,16 +341,12 @@ void AutofillPopupView::SetSelectedLine(int selected_line) {
selected_line_ = selected_line;
if (selected_line_ != kNoSelection) {
- external_delegate_->SelectAutofillSuggestionAtIndex(
+ delegate_->SelectAutofillSuggestionAtIndex(
autofill_unique_ids_[selected_line_]);
}
}
-void AutofillPopupView::ClearSelectedLine() {
- SetSelectedLine(kNoSelection);
-}
-
-void AutofillPopupView::SelectNextLine() {
+void AutofillPopupControllerImpl::SelectNextLine() {
int new_selected_line = selected_line_ + 1;
// Skip over any lines that can't be selected.
@@ -177,7 +361,7 @@ void AutofillPopupView::SelectNextLine() {
SetSelectedLine(new_selected_line);
}
-void AutofillPopupView::SelectPreviousLine() {
+void AutofillPopupControllerImpl::SelectPreviousLine() {
int new_selected_line = selected_line_ - 1;
// Skip over any lines that can't be selected.
@@ -192,7 +376,7 @@ void AutofillPopupView::SelectPreviousLine() {
SetSelectedLine(new_selected_line);
}
-bool AutofillPopupView::AcceptSelectedLine() {
+bool AutofillPopupControllerImpl::AcceptSelectedLine() {
if (selected_line_ == kNoSelection)
return false;
@@ -202,13 +386,13 @@ bool AutofillPopupView::AcceptSelectedLine() {
if (!CanAccept(autofill_unique_ids_[selected_line_]))
return false;
- return external_delegate()->DidAcceptAutofillSuggestions(
+ return AcceptAutofillSuggestion(
autofill_values_[selected_line_],
autofill_unique_ids_[selected_line_],
selected_line_);
}
-bool AutofillPopupView::RemoveSelectedLine() {
+bool AutofillPopupControllerImpl::RemoveSelectedLine() {
if (selected_line_ == kNoSelection)
return false;
@@ -219,10 +403,10 @@ bool AutofillPopupView::RemoveSelectedLine() {
return false;
if (autofill_unique_ids_[selected_line_] > 0) {
- external_delegate()->RemoveAutofillProfileOrCreditCard(
+ delegate_->RemoveAutofillProfileOrCreditCard(
autofill_unique_ids_[selected_line_]);
} else {
- external_delegate()->RemoveAutocompleteEntry(
+ delegate_->RemoveAutocompleteEntry(
autofill_values_[selected_line_]);
}
@@ -235,76 +419,16 @@ bool AutofillPopupView::RemoveSelectedLine() {
SetSelectedLine(kNoSelection);
if (HasAutofillEntries()) {
- external_delegate_->ClearPreviewedForm();
+ delegate_->ClearPreviewedForm();
UpdateBoundsAndRedrawPopup();
} else {
- external_delegate_->HideAutofillPopup();
+ Hide();
}
return true;
}
-int AutofillPopupView::GetIconResourceID(const string16& resource_name) {
- for (size_t i = 0; i < arraysize(kDataResources); ++i) {
- if (resource_name == ASCIIToUTF16(kDataResources[i].name))
- return kDataResources[i].id;
- }
-
- return -1;
-}
-
-bool AutofillPopupView::CanDelete(int id) {
- return id > 0 ||
- id == WebAutofillClient::MenuItemIDAutocompleteEntry ||
- id == WebAutofillClient::MenuItemIDPasswordEntry;
-}
-
-#if !defined(OS_ANDROID)
-int AutofillPopupView::GetPopupRequiredWidth() {
- if (value_font_.platform_font() == NULL ||
- label_font_.platform_font() == NULL) {
- // We can't calculate the size of the popup if the fonts
- // aren't present.
- return 0;
- }
-
- int popup_width = element_bounds().width();
- DCHECK_EQ(autofill_values().size(), autofill_labels().size());
- for (size_t i = 0; i < autofill_values().size(); ++i) {
- int row_size = kEndPadding +
- value_font_.GetStringWidth(autofill_values()[i]) +
- kLabelPadding +
- label_font_.GetStringWidth(autofill_labels()[i]);
-
- // Add the Autofill icon size, if required.
- if (!autofill_icons()[i].empty())
- row_size += kAutofillIconWidth + kIconPadding;
-
- // Add delete icon, if required.
- if (CanDelete(autofill_unique_ids()[i]))
- row_size += kDeleteIconWidth + kIconPadding;
-
- // Add the padding at the end
- row_size += kEndPadding;
-
- popup_width = std::max(popup_width, row_size);
- }
-
- return popup_width;
-}
-
-int AutofillPopupView::GetPopupRequiredHeight() {
- int popup_height = 0;
-
- for (size_t i = 0; i < autofill_unique_ids().size(); ++i) {
- popup_height += GetRowHeightFromId(autofill_unique_ids()[i]);
- }
-
- return popup_height;
-}
-#endif // !defined(OS_ANDROID)
-
-int AutofillPopupView::LineFromY(int y) {
+int AutofillPopupControllerImpl::LineFromY(int y) {
int current_height = 0;
for (size_t i = 0; i < autofill_unique_ids().size(); ++i) {
@@ -318,24 +442,7 @@ int AutofillPopupView::LineFromY(int y) {
return autofill_unique_ids().size() - 1;
}
-int AutofillPopupView::GetRowHeightFromId(int unique_id) {
- if (unique_id == WebAutofillClient::MenuItemIDSeparator)
- return kSeparatorHeight;
-
- return kRowHeight;
-}
-
-gfx::Rect AutofillPopupView::GetRectForRow(size_t row, int width) {
- int top = 0;
- for (size_t i = 0; i < row; ++i) {
- top += GetRowHeightFromId(autofill_unique_ids()[i]);
- }
-
- return gfx::Rect(
- 0, top, width, GetRowHeightFromId(autofill_unique_ids()[row]));
-}
-
-bool AutofillPopupView::DeleteIconIsSelected(int x, int y) {
+bool AutofillPopupControllerImpl::DeleteIconIsUnder(int x, int y) {
#if defined(OS_ANDROID)
return false;
#else
@@ -357,15 +464,23 @@ bool AutofillPopupView::DeleteIconIsSelected(int x, int y) {
#endif
}
-bool AutofillPopupView::CanAccept(int id) {
+bool AutofillPopupControllerImpl::CanAccept(int id) {
return id != WebAutofillClient::MenuItemIDSeparator;
}
-bool AutofillPopupView::HasAutofillEntries() {
+bool AutofillPopupControllerImpl::HasAutofillEntries() {
return autofill_values_.size() != 0 &&
(autofill_unique_ids_[0] > 0 ||
autofill_unique_ids_[0] ==
- WebAutofillClient::MenuItemIDAutocompleteEntry ||
+ WebAutofillClient::MenuItemIDAutocompleteEntry ||
autofill_unique_ids_[0] == WebAutofillClient::MenuItemIDPasswordEntry ||
autofill_unique_ids_[0] == WebAutofillClient::MenuItemIDDataListEntry);
}
+
+void AutofillPopupControllerImpl::ShowView() {
+ view_->Show();
+}
+
+void AutofillPopupControllerImpl::InvalidateRow(size_t row) {
+ view_->InvalidateRow(row);
+}
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl.h b/chrome/browser/ui/autofill/autofill_popup_controller_impl.h
new file mode 100644
index 0000000..54cda77
--- /dev/null
+++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl.h
@@ -0,0 +1,150 @@
+// 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_AUTOFILL_AUTOFILL_POPUP_CONTROLLER_IMPL_H_
+#define CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_POPUP_CONTROLLER_IMPL_H_
+
+#include "base/gtest_prod_util.h"
+#include "base/string16.h"
+#include "chrome/browser/autofill/autofill_popup_delegate.h"
+#include "chrome/browser/ui/autofill/autofill_popup_controller.h"
+#include "content/public/browser/keyboard_listener.h"
+#include "ui/gfx/font.h"
+#include "ui/gfx/rect.h"
+
+class AutofillPopupView;
+
+namespace ui {
+class KeyEvent;
+}
+
+// This class is a controller for an AutofillPopupView. It implements
+// AutofillPopupController to allow calls from AutofillPopupView. The
+// other, public functions are available to its instantiator.
+class AutofillPopupControllerImpl : public AutofillPopupController,
+ public content::KeyboardListener {
+ public:
+ AutofillPopupControllerImpl(AutofillPopupDelegate* delegate,
+ gfx::NativeView container_view,
+ const gfx::Rect& element_bounds);
+
+ // Shows the popup, or updates the existing popup with the given values.
+ 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);
+
+ // Hides the popup and destroys the controller.
+ void Hide();
+
+ // Called when |delegate_| is no longer valid.
+ void DelegateDestroyed();
+
+ protected:
+ FRIEND_TEST_ALL_PREFIXES(AutofillExternalDelegateBrowserTest,
+ CloseWidgetAndNoLeaking);
+ virtual ~AutofillPopupControllerImpl();
+
+ // AutofillPopupController implementation.
+ virtual void ViewDestroyed() OVERRIDE;
+ virtual void UpdateBoundsAndRedrawPopup() OVERRIDE;
+ virtual void SetSelectedPosition(int x, int y) OVERRIDE;
+ virtual bool AcceptAutofillSuggestion(const string16& value,
+ int unique_id,
+ unsigned index) OVERRIDE;
+ virtual void AcceptSelectedPosition(int x, int y) OVERRIDE;
+ virtual void ClearSelectedLine() OVERRIDE;
+ virtual int GetIconResourceID(const string16& resource_name) OVERRIDE;
+ virtual bool CanDelete(int id) OVERRIDE;
+#if !defined(OS_ANDROID)
+ virtual int GetPopupRequiredWidth() OVERRIDE;
+ virtual int GetPopupRequiredHeight() OVERRIDE;
+#endif
+ virtual int GetRowHeightFromId(int unique_id) OVERRIDE;
+ virtual gfx::Rect GetRectForRow(size_t row, int width) OVERRIDE;
+ virtual void SetPopupBounds(const gfx::Rect& bounds) OVERRIDE;
+ virtual const gfx::Rect& popup_bounds() const OVERRIDE;
+ virtual gfx::NativeView container_view() const OVERRIDE;
+ virtual const gfx::Rect& element_bounds() const OVERRIDE;
+ virtual const std::vector<string16>& autofill_values() const OVERRIDE;
+ virtual const std::vector<string16>& autofill_labels() const OVERRIDE;
+ virtual const std::vector<string16>& autofill_icons() const OVERRIDE;
+ virtual const std::vector<int>& autofill_unique_ids() const OVERRIDE;
+#if !defined(OS_ANDROID)
+ virtual const gfx::Font& label_font() const OVERRIDE;
+ virtual const gfx::Font& value_font() const OVERRIDE;
+#endif
+ virtual int selected_line() const OVERRIDE;
+ virtual bool delete_icon_hovered() const OVERRIDE;
+
+ // KeyboardListener implementation.
+ virtual bool HandleKeyPressEvent(
+ const content::NativeWebKeyboardEvent& event) OVERRIDE;
+
+ // Change which line is currently selected by the user.
+ void SetSelectedLine(int selected_line);
+
+ // Increase the selected line by 1, properly handling wrapping.
+ void SelectNextLine();
+
+ // Decrease the selected line by 1, properly handling wrapping.
+ void SelectPreviousLine();
+
+ // The user has choosen the selected line.
+ bool AcceptSelectedLine();
+
+ // The user has removed a suggestion.
+ bool RemoveSelectedLine();
+
+ // Convert a y-coordinate to the closest line.
+ int LineFromY(int y);
+
+ // Returns true if the given |x| and |y| coordinates refer to a point that
+ // hits the delete icon in the current selected line.
+ bool DeleteIconIsUnder(int x, int y);
+
+ // Returns true if the given id refers to an element that can be accepted.
+ bool CanAccept(int id);
+
+ // Returns true if the popup still has non-options entries to show the user.
+ bool HasAutofillEntries();
+
+ AutofillPopupView* view() { return view_; }
+
+ // |view_| pass throughs (virtual for testing).
+ virtual void ShowView();
+ virtual void InvalidateRow(size_t row);
+
+ private:
+ AutofillPopupView* view_; // Weak reference.
+ AutofillPopupDelegate* delegate_; // Weak reference.
+ gfx::NativeView container_view_; // Weak reference.
+
+ // The bounds of the text element that is the focus of the Autofill.
+ const gfx::Rect element_bounds_;
+
+ // The bounds of the Autofill popup.
+ gfx::Rect popup_bounds_;
+
+ // The current Autofill query values.
+ std::vector<string16> autofill_values_;
+ std::vector<string16> autofill_labels_;
+ std::vector<string16> autofill_icons_;
+ std::vector<int> autofill_unique_ids_;
+
+#if !defined(OS_ANDROID)
+ // The fonts for the popup text.
+ gfx::Font value_font_;
+ gfx::Font label_font_;
+#endif
+
+ // The line that is currently selected by the user.
+ // |kNoSelection| indicates that no line is currently selected.
+ int selected_line_;
+
+ // Used to indicate if the delete icon within a row is currently selected.
+ bool delete_icon_hovered_;
+};
+
+#endif // CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_POPUP_CONTROLLER_IMPL_H_
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc b/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc
new file mode 100644
index 0000000..ad13318
--- /dev/null
+++ b/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc
@@ -0,0 +1,208 @@
+// 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 "base/memory/scoped_ptr.h"
+#include "chrome/browser/autofill/test_autofill_external_delegate.h"
+#include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebAutofillClient.h"
+#include "ui/gfx/rect.h"
+
+using ::testing::_;
+using ::testing::AtLeast;
+using WebKit::WebAutofillClient;
+
+namespace {
+
+class MockAutofillExternalDelegate :
+ public autofill::TestAutofillExternalDelegate {
+ public:
+ MockAutofillExternalDelegate() : TestAutofillExternalDelegate(NULL, NULL) {};
+ virtual ~MockAutofillExternalDelegate() {};
+
+ virtual void SelectAutofillSuggestionAtIndex(int unique_id)
+ OVERRIDE {}
+ virtual void RemoveAutocompleteEntry(const string16& value) OVERRIDE {}
+ virtual void RemoveAutofillProfileOrCreditCard(int unique_id) OVERRIDE {}
+ virtual void ClearPreviewedForm() OVERRIDE {}
+
+ MOCK_METHOD0(ControllerDestroyed, void());
+};
+
+class TestAutofillPopupController : public AutofillPopupControllerImpl {
+ public:
+ explicit TestAutofillPopupController(
+ AutofillExternalDelegate* external_delegate)
+ : AutofillPopupControllerImpl(external_delegate, NULL, gfx::Rect()) {}
+ virtual ~TestAutofillPopupController() {}
+
+ // Making protected functions public for testing
+ const std::vector<string16>& autofill_values() const {
+ return AutofillPopupControllerImpl::autofill_values();
+ }
+ int selected_line() const {
+ return AutofillPopupControllerImpl::selected_line();
+ }
+ void SetSelectedLine(size_t selected_line) {
+ AutofillPopupControllerImpl::SetSelectedLine(selected_line);
+ }
+ void SelectNextLine() {
+ AutofillPopupControllerImpl::SelectNextLine();
+ }
+ void SelectPreviousLine() {
+ AutofillPopupControllerImpl::SelectPreviousLine();
+ }
+ bool RemoveSelectedLine() {
+ return AutofillPopupControllerImpl::RemoveSelectedLine();
+ }
+
+ MOCK_METHOD1(InvalidateRow, void(size_t));
+ MOCK_METHOD0(Hide, void());
+ MOCK_METHOD0(UpdateBoundsAndRedrawPopup, void());
+
+ private:
+ virtual void ShowView() OVERRIDE {}
+};
+
+} // namespace
+
+class AutofillPopupControllerUnitTest : public ::testing::Test {
+ public:
+ AutofillPopupControllerUnitTest() {
+ autofill_popup_controller_.reset(
+ new testing::NiceMock<TestAutofillPopupController>(
+ &external_delegate_));
+ }
+ virtual ~AutofillPopupControllerUnitTest() {}
+
+ AutofillPopupController* popup_controller() {
+ return autofill_popup_controller_.get();
+ }
+
+protected:
+ testing::NiceMock<MockAutofillExternalDelegate> external_delegate_;
+ scoped_ptr<testing::NiceMock<TestAutofillPopupController> >
+ autofill_popup_controller_;
+};
+
+TEST_F(AutofillPopupControllerUnitTest, SetBounds) {
+ // Ensure the popup size can be set and causes a redraw.
+ gfx::Rect popup_bounds(10, 10, 100, 100);
+
+ EXPECT_CALL(*autofill_popup_controller_,
+ UpdateBoundsAndRedrawPopup());
+
+ popup_controller()->SetPopupBounds(popup_bounds);
+
+ EXPECT_EQ(popup_bounds, popup_controller()->popup_bounds());
+}
+
+TEST_F(AutofillPopupControllerUnitTest, ChangeSelectedLine) {
+ // Set up the popup.
+ std::vector<string16> autofill_values(2, string16());
+ std::vector<int> autofill_ids(2, 0);
+ autofill_popup_controller_->Show(
+ autofill_values, autofill_values, autofill_values, autofill_ids);
+
+ EXPECT_LT(autofill_popup_controller_->selected_line(), 0);
+ // Check that there are at least 2 values so that the first and last selection
+ // are different.
+ EXPECT_GE(2,
+ static_cast<int>(autofill_popup_controller_->autofill_values().size()));
+
+ // Test wrapping before the front.
+ autofill_popup_controller_->SelectPreviousLine();
+ EXPECT_EQ(static_cast<int>(
+ autofill_popup_controller_->autofill_values().size() - 1),
+ autofill_popup_controller_->selected_line());
+
+ // Test wrapping after the end.
+ autofill_popup_controller_->SelectNextLine();
+ EXPECT_EQ(0, autofill_popup_controller_->selected_line());
+}
+
+TEST_F(AutofillPopupControllerUnitTest, RedrawSelectedLine) {
+ // Set up the popup.
+ std::vector<string16> autofill_values(2, string16());
+ std::vector<int> autofill_ids(2, 0);
+ autofill_popup_controller_->Show(
+ autofill_values, autofill_values, autofill_values,
+ autofill_ids);
+
+ // Make sure that when a new line is selected, it is invalidated so it can
+ // be updated to show it is selected.
+ int selected_line = 0;
+ EXPECT_CALL(*autofill_popup_controller_, InvalidateRow(selected_line));
+ autofill_popup_controller_->SetSelectedLine(selected_line);
+
+ // Ensure that the row isn't invalidated if it didn't change.
+ EXPECT_CALL(*autofill_popup_controller_,
+ InvalidateRow(selected_line)).Times(0);
+ autofill_popup_controller_->SetSelectedLine(selected_line);
+
+ // Change back to no selection.
+ EXPECT_CALL(*autofill_popup_controller_, InvalidateRow(selected_line));
+ autofill_popup_controller_->SetSelectedLine(-1);
+}
+
+TEST_F(AutofillPopupControllerUnitTest, RemoveLine) {
+ // Set up the popup.
+ std::vector<string16> autofill_values(3, string16());
+ std::vector<int> autofill_ids;
+ autofill_ids.push_back(1);
+ autofill_ids.push_back(1);
+ autofill_ids.push_back(WebAutofillClient::MenuItemIDAutofillOptions);
+ autofill_popup_controller_->Show(
+ autofill_values, autofill_values, autofill_values, autofill_ids);
+
+ // Generate a popup, so it can be hidden later. It doesn't matter what the
+ // external_delegate thinks is being shown in the process, since we are just
+ // testing the popup here.
+ autofill::GenerateTestAutofillPopup(&external_delegate_);
+
+ // No line is selected so the removal should fail.
+ EXPECT_FALSE(autofill_popup_controller_->RemoveSelectedLine());
+
+ // Try to remove the last entry and ensure it fails (it is an option).
+ autofill_popup_controller_->SetSelectedLine(
+ autofill_popup_controller_->autofill_values().size() - 1);
+ EXPECT_FALSE(autofill_popup_controller_->RemoveSelectedLine());
+ EXPECT_LE(0, autofill_popup_controller_->selected_line());
+
+ // Remove the first entry. The popup should be redrawn since its size has
+ // changed.
+ EXPECT_CALL(*autofill_popup_controller_, UpdateBoundsAndRedrawPopup());
+ autofill_popup_controller_->SetSelectedLine(0);
+ EXPECT_TRUE(autofill_popup_controller_->RemoveSelectedLine());
+
+ // Remove the last entry. The popup should then be hidden since there are
+ // no Autofill entries left.
+ EXPECT_CALL(external_delegate_, ControllerDestroyed());
+
+ autofill_popup_controller_->SetSelectedLine(0);
+ // The controller self-deletes here, don't double delete.
+ EXPECT_TRUE(autofill_popup_controller_.release()->RemoveSelectedLine());
+}
+
+TEST_F(AutofillPopupControllerUnitTest, SkipSeparator) {
+ // Set up the popup.
+ std::vector<string16> autofill_values(3, string16());
+ std::vector<int> autofill_ids;
+ autofill_ids.push_back(1);
+ autofill_ids.push_back(WebAutofillClient::MenuItemIDSeparator);
+ autofill_ids.push_back(WebAutofillClient::MenuItemIDAutofillOptions);
+ autofill_popup_controller_->Show(
+ autofill_values, autofill_values, autofill_values, autofill_ids);
+
+ autofill_popup_controller_->SetSelectedLine(0);
+
+ // Make sure next skips the unselectable separator.
+ autofill_popup_controller_->SelectNextLine();
+ EXPECT_EQ(2, autofill_popup_controller_->selected_line());
+
+ // Make sure previous skips the unselectable separator.
+ autofill_popup_controller_->SelectPreviousLine();
+ EXPECT_EQ(0, autofill_popup_controller_->selected_line());
+}
diff --git a/chrome/browser/ui/autofill/autofill_popup_view.cc b/chrome/browser/ui/autofill/autofill_popup_view.cc
new file mode 100644
index 0000000..24e4a30
--- /dev/null
+++ b/chrome/browser/ui/autofill/autofill_popup_view.cc
@@ -0,0 +1,22 @@
+// 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 "base/logging.h"
+#include "chrome/browser/ui/autofill/autofill_popup_view.h"
+
+const size_t AutofillPopupView::kBorderThickness = 1;
+const size_t AutofillPopupView::kIconPadding = 5;
+const size_t AutofillPopupView::kEndPadding = 3;
+const size_t AutofillPopupView::kDeleteIconHeight = 16;
+const size_t AutofillPopupView::kDeleteIconWidth = 16;
+const size_t AutofillPopupView::kAutofillIconHeight = 16;
+const size_t AutofillPopupView::kAutofillIconWidth = 25;
+
+#if defined(OS_MACOSX)
+AutofillPopupView* AutofillPopupView::Create(
+ AutofillPopupController* controller) {
+ NOTIMPLEMENTED();
+ return NULL;
+}
+#endif
diff --git a/chrome/browser/ui/autofill/autofill_popup_view.h b/chrome/browser/ui/autofill/autofill_popup_view.h
new file mode 100644
index 0000000..8b977b5
--- /dev/null
+++ b/chrome/browser/ui/autofill/autofill_popup_view.h
@@ -0,0 +1,64 @@
+// 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_AUTOFILL_AUTOFILL_POPUP_VIEW_H_
+#define CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_POPUP_VIEW_H_
+
+#include "ui/gfx/native_widget_types.h"
+
+class AutofillPopupController;
+
+namespace gfx {
+class Rect;
+}
+
+namespace ui {
+class KeyEvent;
+}
+
+// The interface for creating and controlling a platform-dependent
+// AutofillPopupView.
+class AutofillPopupView {
+ public:
+ // The size of the border around the entire results popup, in pixels.
+ static const size_t kBorderThickness;
+
+ // The amount of padding between icons in pixels.
+ static const size_t kIconPadding;
+
+ // The amount of padding at the end of the popup in pixels.
+ static const size_t kEndPadding;
+
+ // Height of the delete icon in pixels.
+ static const size_t kDeleteIconHeight;
+
+ // Width of the delete icon in pixels.
+ static const size_t kDeleteIconWidth;
+
+ // Height of the Autofill icons in pixels.
+ static const size_t kAutofillIconHeight;
+
+ // Width of the Autofill icons in pixels.
+ static const size_t kAutofillIconWidth;
+
+ // Displays the Autofill popup and fills it in with data from the controller.
+ virtual void Show() = 0;
+
+ // Hides the popup from view. This will cause the popup to be deleted.
+ virtual void Hide() = 0;
+
+ // Invalidates the given row and redraw it.
+ virtual void InvalidateRow(size_t row) = 0;
+
+ // Refreshes the position of the popup.
+ virtual void UpdateBoundsAndRedrawPopup() = 0;
+
+ // Factory function for creating the view.
+ static AutofillPopupView* Create(AutofillPopupController* controller);
+
+ protected:
+ virtual ~AutofillPopupView() {}
+};
+
+#endif // CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_POPUP_VIEW_H_
diff --git a/chrome/browser/ui/gtk/autofill/autofill_external_delegate_gtk.cc b/chrome/browser/ui/gtk/autofill/autofill_external_delegate_gtk.cc
deleted file mode 100644
index fe134ec..0000000
--- a/chrome/browser/ui/gtk/autofill/autofill_external_delegate_gtk.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-// 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/ui/gtk/autofill/autofill_external_delegate_gtk.h"
-
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.h"
-#include "chrome/browser/ui/gtk/gtk_theme_service.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_view.h"
-
-void AutofillExternalDelegate::CreateForWebContentsAndManager(
- content::WebContents* web_contents,
- AutofillManager* autofill_manager) {
- if (FromWebContents(web_contents))
- return;
-
- web_contents->SetUserData(
- UserDataKey(),
- new AutofillExternalDelegateGtk(web_contents, autofill_manager));
-}
-
-AutofillExternalDelegateGtk::AutofillExternalDelegateGtk(
- content::WebContents* web_contents,
- AutofillManager* autofill_manager)
- : AutofillExternalDelegate(web_contents, autofill_manager),
- event_handler_id_(0) {
- tab_native_view_ = web_contents->GetView()->GetNativeView();
-}
-
-AutofillExternalDelegateGtk::~AutofillExternalDelegateGtk() {
-}
-
-void AutofillExternalDelegateGtk::HideAutofillPopupInternal() {
- if (!view_.get())
- return;
-
- view_->Hide();
- view_.reset();
-
- GtkWidget* toplevel = gtk_widget_get_toplevel(tab_native_view_);
- if (g_signal_handler_is_connected(toplevel, event_handler_id_))
- g_signal_handler_disconnect(toplevel, event_handler_id_);
-}
-
-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) {
- view_->Show(autofill_values,
- autofill_labels,
- autofill_icons,
- autofill_unique_ids);
-}
-
-void AutofillExternalDelegateGtk::CreatePopupForElement(
- const gfx::Rect& element_bounds) {
- content::WebContents* contents = web_contents();
- Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
- view_.reset(new AutofillPopupViewGtk(contents,
- GtkThemeService::GetFrom(profile),
- this,
- element_bounds,
- 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) {
- if (!popup_visible())
- return FALSE;
-
- HideAutofillPopup();
-
- return TRUE;
-}
diff --git a/chrome/browser/ui/gtk/autofill/autofill_external_delegate_gtk.h b/chrome/browser/ui/gtk/autofill/autofill_external_delegate_gtk.h
deleted file mode 100644
index 8b39994..0000000
--- a/chrome/browser/ui/gtk/autofill/autofill_external_delegate_gtk.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// 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_EXTERNAL_DELEGATE_GTK_H_
-#define CHROME_BROWSER_UI_GTK_AUTOFILL_AUTOFILL_EXTERNAL_DELEGATE_GTK_H_
-
-#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;
-
-class AutofillExternalDelegateGtk : public AutofillExternalDelegate {
- public:
- AutofillExternalDelegateGtk(content::WebContents* web_contents,
- AutofillManager* autofill_manager);
-
- virtual ~AutofillExternalDelegateGtk();
-
- protected:
- // AutofillExternalDelegate implementations.
- virtual void HideAutofillPopupInternal() 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) OVERRIDE;
- virtual void CreatePopupForElement(const gfx::Rect& element_bounds) 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*);
-
- // Unlike in the Views implementation, the popup is always destroyed when
- // this class is.
- scoped_ptr<AutofillPopupViewGtk> view_;
-
- 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_UI_GTK_AUTOFILL_AUTOFILL_EXTERNAL_DELEGATE_GTK_H_
diff --git a/chrome/browser/ui/gtk/autofill/autofill_external_delegate_gtk_browsertest.cc b/chrome/browser/ui/gtk/autofill/autofill_external_delegate_gtk_browsertest.cc
deleted file mode 100644
index ceef438..0000000
--- a/chrome/browser/ui/gtk/autofill/autofill_external_delegate_gtk_browsertest.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 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/ui/gtk/autofill/autofill_external_delegate_gtk.h"
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "chrome/browser/autofill/autofill_manager.h"
-#include "chrome/browser/autofill/test_autofill_external_delegate.h"
-#include "chrome/browser/ui/browser_commands.h"
-#include "chrome/browser/ui/browser_tabstrip.h"
-#include "chrome/test/base/in_process_browser_test.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-class MockAutofillExternalDelegateGtk : public AutofillExternalDelegateGtk {
- public:
- explicit MockAutofillExternalDelegateGtk(content::WebContents* web_contents)
- : AutofillExternalDelegateGtk(
- web_contents,
- AutofillManager::FromWebContents(web_contents)) {}
- ~MockAutofillExternalDelegateGtk() {}
-
- virtual void ClearPreviewedForm() OVERRIDE {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockAutofillExternalDelegateGtk);
-};
-
-} // namespace
-
-class AutofillExternalDelegateGtkBrowserTest : public InProcessBrowserTest {
- public:
- AutofillExternalDelegateGtkBrowserTest() {}
- virtual ~AutofillExternalDelegateGtkBrowserTest() {}
-
- virtual void SetUpOnMainThread() OVERRIDE {
- web_contents_ = chrome::GetActiveWebContents(browser());
- ASSERT_TRUE(web_contents_ != NULL);
-
- autofill_external_delegate_.reset(
- new MockAutofillExternalDelegateGtk(web_contents_));
- }
-
- protected:
- content::WebContents* web_contents_;
- scoped_ptr<MockAutofillExternalDelegateGtk> autofill_external_delegate_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(AutofillExternalDelegateGtkBrowserTest);
-};
-
-// Ensure that the Autofill code doesn't crash if the window is closed while
-// the Autofill popup is still visible. See http://crbug.com/160866
-IN_PROC_BROWSER_TEST_F(AutofillExternalDelegateGtkBrowserTest,
- CloseBrowserWithPopupOpen) {
- autofill::GenerateTestAutofillPopup(autofill_external_delegate_.get());
-
- chrome::CloseWindow(browser());
-}
diff --git a/chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.cc b/chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.cc
index d927583..c231156 100644
--- a/chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.cc
+++ b/chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.cc
@@ -2,23 +2,21 @@
// 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 "chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.h"
#include <gdk/gdkkeysyms.h>
#include "base/i18n/rtl.h"
#include "base/logging.h"
#include "base/utf_string_conversions.h"
-#include "chrome/browser/autofill/autofill_external_delegate.h"
+#include "chrome/browser/ui/autofill/autofill_popup_controller.h"
#include "chrome/browser/ui/gtk/gtk_util.h"
-#include "chrome/browser/ui/gtk/gtk_theme_service.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/web_contents.h"
#include "grit/ui_resources.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebAutofillClient.h"
#include "ui/base/gtk/gtk_compat.h"
#include "ui/base/gtk/gtk_hig_constants.h"
#include "ui/base/gtk/gtk_windowing.h"
+#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/pango_util.h"
@@ -40,17 +38,9 @@ gfx::Rect GetWindowRect(GdkWindow* window) {
} // namespace
AutofillPopupViewGtk::AutofillPopupViewGtk(
- content::WebContents* web_contents,
- GtkThemeService* theme_service,
- AutofillExternalDelegate* external_delegate,
- const gfx::Rect& element_bounds,
- GtkWidget* parent)
- : AutofillPopupView(web_contents, external_delegate, element_bounds),
- parent_(parent),
- window_(gtk_window_new(GTK_WINDOW_POPUP)),
- theme_service_(theme_service),
- render_view_host_(web_contents->GetRenderViewHost()) {
- CHECK(parent != NULL);
+ AutofillPopupController* controller)
+ : controller_(controller),
+ window_(gtk_window_new(GTK_WINDOW_POPUP)) {
gtk_window_set_resizable(GTK_WINDOW(window_), FALSE);
gtk_widget_set_app_paintable(window_, TRUE);
gtk_widget_set_double_buffered(window_, TRUE);
@@ -74,47 +64,44 @@ AutofillPopupViewGtk::AutofillPopupViewGtk(
}
AutofillPopupViewGtk::~AutofillPopupViewGtk() {
+ controller_->ViewDestroyed();
g_object_unref(layout_);
gtk_widget_destroy(window_);
}
void AutofillPopupViewGtk::Hide() {
- render_view_host_->RemoveKeyboardListener(this);
-
- gtk_widget_hide(window_);
+ delete this;
}
-void AutofillPopupViewGtk::ShowInternal() {
+void AutofillPopupViewGtk::Show() {
SetInitialBounds();
UpdateBoundsAndRedrawPopup();
- render_view_host_->AddKeyboardListener(this);
-
gtk_widget_show(window_);
- GtkWidget* toplevel = gtk_widget_get_toplevel(parent_);
- CHECK(gtk_widget_is_toplevel(toplevel));
- ui::StackPopupWindow(window_, toplevel);
+ GtkWidget* parent_window =
+ gtk_widget_get_toplevel(controller_->container_view());
+ ui::StackPopupWindow(window_, parent_window);
}
void AutofillPopupViewGtk::InvalidateRow(size_t row) {
- GdkRectangle row_rect = GetRectForRow(
+ GdkRectangle row_rect = controller_->GetRectForRow(
row,
- popup_bounds().width()).ToGdkRectangle();
+ controller_->popup_bounds().width()).ToGdkRectangle();
GdkWindow* gdk_window = gtk_widget_get_window(window_);
gdk_window_invalidate_rect(gdk_window, &row_rect, FALSE);
}
-void AutofillPopupViewGtk::UpdateBoundsAndRedrawPopupInternal() {
+void AutofillPopupViewGtk::UpdateBoundsAndRedrawPopup() {
gtk_widget_set_size_request(window_,
- popup_bounds().width(),
- popup_bounds().height());
+ controller_->popup_bounds().width(),
+ controller_->popup_bounds().height());
gtk_window_move(GTK_WINDOW(window_),
- popup_bounds().x(),
- popup_bounds().y());
+ controller_->popup_bounds().x(),
+ controller_->popup_bounds().y());
GdkWindow* gdk_window = gtk_widget_get_window(window_);
- GdkRectangle popup_rect = popup_bounds().ToGdkRectangle();
+ GdkRectangle popup_rect = controller_->popup_bounds().ToGdkRectangle();
if (gdk_window != NULL)
gdk_window_invalidate_rect(gdk_window, &popup_rect, FALSE);
}
@@ -125,7 +112,7 @@ gboolean AutofillPopupViewGtk::HandleButtonRelease(GtkWidget* widget,
if (event->button != 1)
return FALSE;
- AcceptSelectedPosition(event->x, event->y);
+ controller_->AcceptSelectedPosition(event->x, event->y);
return TRUE;
}
@@ -149,16 +136,18 @@ gboolean AutofillPopupViewGtk::HandleExpose(GtkWidget* widget,
SetupLayout(window_rect);
- for (size_t i = 0; i < autofill_values().size(); ++i) {
- gfx::Rect line_rect = GetRectForRow(i, window_rect.width());
+ for (size_t i = 0; i < controller_->autofill_values().size(); ++i) {
+ gfx::Rect line_rect = controller_->GetRectForRow(i, window_rect.width());
// Only repaint and layout damaged lines.
if (!line_rect.Intersects(damage_rect))
continue;
- if (autofill_unique_ids()[i] == WebAutofillClient::MenuItemIDSeparator)
+ if (controller_->autofill_unique_ids()[i] ==
+ WebAutofillClient::MenuItemIDSeparator) {
DrawSeparator(cr, line_rect);
- else
+ } else {
DrawAutofillEntry(cr, i, line_rect);
+ }
}
cairo_destroy(cr);
@@ -168,49 +157,18 @@ gboolean AutofillPopupViewGtk::HandleExpose(GtkWidget* widget,
gboolean AutofillPopupViewGtk::HandleLeave(GtkWidget* widget,
GdkEventCrossing* event) {
- ClearSelectedLine();
+ controller_->ClearSelectedLine();
return FALSE;
}
gboolean AutofillPopupViewGtk::HandleMotion(GtkWidget* widget,
GdkEventMotion* event) {
- SetSelectedPosition(event->x, event->y);
+ controller_->SetSelectedPosition(event->x, event->y);
return TRUE;
}
-bool AutofillPopupViewGtk::HandleKeyPressEvent(GdkEventKey* event) {
- // Filter modifier to only include accelerator modifiers.
- guint modifier = event->state & gtk_accelerator_get_default_mod_mask();
-
- switch (event->keyval) {
- case GDK_Up:
- SelectPreviousLine();
- return true;
- case GDK_Down:
- SelectNextLine();
- return true;
- case GDK_Page_Up:
- SetSelectedLine(0);
- return true;
- case GDK_Page_Down:
- SetSelectedLine(autofill_values().size() - 1);
- return true;
- case GDK_Escape:
- external_delegate()->HideAutofillPopup();
- return true;
- case GDK_Delete:
- case GDK_KP_Delete:
- return (modifier == GDK_SHIFT_MASK) && RemoveSelectedLine();
- case GDK_Return:
- case GDK_KP_Enter:
- return AcceptSelectedLine();
- }
-
- return false;
-}
-
void AutofillPopupViewGtk::SetupLayout(const gfx::Rect& window_rect) {
pango_layout_set_width(layout_, window_rect.width() * PANGO_SCALE);
pango_layout_set_height(layout_, window_rect.height() * PANGO_SCALE);
@@ -255,7 +213,7 @@ void AutofillPopupViewGtk::DrawSeparator(cairo_t* cairo_context,
void AutofillPopupViewGtk::DrawAutofillEntry(cairo_t* cairo_context,
size_t index,
const gfx::Rect& entry_rect) {
- if (selected_line() == static_cast<int>(index)) {
+ if (controller_->selected_line() == static_cast<int>(index)) {
gdk_cairo_set_source_color(cairo_context, &kHoveredBackgroundColor);
cairo_rectangle(cairo_context, entry_rect.x(), entry_rect.y(),
entry_rect.width(), entry_rect.height());
@@ -263,14 +221,19 @@ void AutofillPopupViewGtk::DrawAutofillEntry(cairo_t* cairo_context,
}
// Draw the value.
- SetLayoutText(autofill_values()[index], value_font(), kValueTextColor);
- int value_text_width = value_font().GetStringWidth(autofill_values()[index]);
+ SetLayoutText(controller_->autofill_values()[index],
+ controller_->value_font(),
+ kValueTextColor);
+ int value_text_width = controller_->value_font().GetStringWidth(
+ controller_->autofill_values()[index]);
// Center the text within the line.
- int row_height = GetRowHeightFromId(autofill_unique_ids()[index]);
+ int row_height = controller_->GetRowHeightFromId(
+ controller_->autofill_unique_ids()[index]);
int value_content_y = std::max(
entry_rect.y(),
- entry_rect.y() + ((row_height - value_font().GetHeight()) / 2));
+ entry_rect.y() +
+ (row_height - controller_->value_font().GetHeight()) / 2);
bool is_rtl = base::i18n::IsRTL();
int value_content_x = is_rtl ?
@@ -284,15 +247,19 @@ void AutofillPopupViewGtk::DrawAutofillEntry(cairo_t* cairo_context,
// Use this to figure out where all the other Autofill items should be placed.
int x_align_left = is_rtl ? kEndPadding : entry_rect.width() - kEndPadding;
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+
// Draw the delete icon, if one is needed.
- if (CanDelete(autofill_unique_ids()[index])) {
+ if (controller_->CanDelete(controller_->autofill_unique_ids()[index])) {
x_align_left += is_rtl ? 0 : -kDeleteIconWidth;
gfx::Image delete_icon;
- if (static_cast<int>(index) == selected_line() && delete_icon_selected())
- delete_icon = theme_service_->GetImageNamed(IDR_CLOSE_BAR_H);
- else
- delete_icon = theme_service_->GetImageNamed(IDR_CLOSE_BAR);
+ if (static_cast<int>(index) == controller_->selected_line() &&
+ controller_->delete_icon_hovered()) {
+ delete_icon = rb.GetImageNamed(IDR_CLOSE_BAR_H);
+ } else {
+ delete_icon = rb.GetImageNamed(IDR_CLOSE_BAR);
+ }
// TODO(csharp): Create a custom resource for the delete icon.
// http://crbug.com/131801
@@ -311,8 +278,9 @@ void AutofillPopupViewGtk::DrawAutofillEntry(cairo_t* cairo_context,
}
// Draw the Autofill icon, if one exists
- if (!autofill_icons()[index].empty()) {
- int icon = GetIconResourceID(autofill_icons()[index]);
+ if (!controller_->autofill_icons()[index].empty()) {
+ int icon =
+ controller_->GetIconResourceID(controller_->autofill_icons()[index]);
DCHECK_NE(-1, icon);
int icon_y = entry_rect.y() + (row_height - kAutofillIconHeight) / 2;
@@ -321,7 +289,7 @@ void AutofillPopupViewGtk::DrawAutofillEntry(cairo_t* cairo_context,
cairo_save(cairo_context);
gtk_util::DrawFullImage(cairo_context,
window_,
- theme_service_->GetImageNamed(icon),
+ rb.GetImageNamed(icon),
x_align_left,
icon_y);
cairo_restore(cairo_context);
@@ -330,14 +298,19 @@ void AutofillPopupViewGtk::DrawAutofillEntry(cairo_t* cairo_context,
}
// Draw the label text.
- SetLayoutText(autofill_labels()[index], label_font(), kLabelTextColor);
- x_align_left +=
- is_rtl ? 0 : -label_font().GetStringWidth(autofill_labels()[index]);
+ SetLayoutText(controller_->autofill_labels()[index],
+ controller_->label_font(),
+ kLabelTextColor);
+ if (!is_rtl) {
+ x_align_left -= controller_->label_font().GetStringWidth(
+ controller_->autofill_labels()[index]);
+ }
// Center the text within the line.
int label_content_y = std::max(
entry_rect.y(),
- entry_rect.y() + ((row_height - label_font().GetHeight()) / 2));
+ entry_rect.y() +
+ (row_height - controller_->label_font().GetHeight()) / 2);
cairo_save(cairo_context);
cairo_move_to(cairo_context, x_align_left, label_content_y);
@@ -346,29 +319,37 @@ void AutofillPopupViewGtk::DrawAutofillEntry(cairo_t* cairo_context,
}
void AutofillPopupViewGtk::SetInitialBounds() {
- gint origin_x, origin_y;
- gdk_window_get_origin(gtk_widget_get_window(parent_), &origin_x, &origin_y);
-
- GdkScreen* screen = gtk_widget_get_screen(parent_);
+ GdkScreen* screen =
+ gtk_widget_get_screen(GTK_WIDGET(controller_->container_view()));
gint screen_height = gdk_screen_get_height(screen);
- int bottom_of_field = origin_y + element_bounds().y() +
- element_bounds().height();
- int popup_height = GetPopupRequiredHeight();
+ int x = 0;
+ int y = 0;
+ gdk_window_get_origin(
+ gtk_widget_get_window(controller_->container_view()), &x, &y);
+
+ int bottom_of_field = y + controller_->element_bounds().bottom();
+ int popup_height = controller_->GetPopupRequiredHeight();
// Find the correct top position of the popup so that is doesn't go off
// the screen.
int top_of_popup = 0;
if (screen_height < bottom_of_field + popup_height) {
// The popup must appear above the field.
- top_of_popup = origin_y + element_bounds().y() - popup_height;
+ top_of_popup = y + controller_->element_bounds().y() - popup_height;
} else {
// The popup can appear below the field.
top_of_popup = bottom_of_field;
}
- SetPopupBounds(gfx::Rect(origin_x + element_bounds().x(),
- top_of_popup,
- GetPopupRequiredWidth(),
- popup_height));
+ controller_->SetPopupBounds(gfx::Rect(
+ x + controller_->element_bounds().x(),
+ top_of_popup,
+ controller_->GetPopupRequiredWidth(),
+ popup_height));
+}
+
+AutofillPopupView* AutofillPopupView::Create(
+ AutofillPopupController* controller) {
+ return new AutofillPopupViewGtk(controller);
}
diff --git a/chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.h b/chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.h
index 261b96f..24664c5 100644
--- a/chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.h
+++ b/chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.h
@@ -8,12 +8,14 @@
#include <pango/pango.h>
#include <vector>
-#include "chrome/browser/autofill/autofill_popup_view.h"
-#include "content/public/browser/keyboard_listener.h"
+#include "base/compiler_specific.h"
+#include "base/string16.h"
+#include "chrome/browser/ui/autofill/autofill_popup_view.h"
#include "ui/base/glib/glib_integers.h"
#include "ui/base/gtk/gtk_signal.h"
+#include "ui/gfx/font.h"
-class GtkThemeService;
+class AutofillPopupController;
class Profile;
namespace content {
@@ -32,26 +34,20 @@ typedef struct _GdkEventMotion GdkEventMotion;
typedef struct _GdkColor GdkColor;
typedef struct _GtkWidget GtkWidget;
-class AutofillPopupViewGtk : public AutofillPopupView,
- public KeyboardListener {
+// Gtk implementation for AutofillPopupView interface.
+class AutofillPopupViewGtk : public AutofillPopupView {
public:
- AutofillPopupViewGtk(content::WebContents* web_contents,
- GtkThemeService* theme_service,
- AutofillExternalDelegate* external_delegate,
- const gfx::Rect& element_bounds,
- GtkWidget* parent);
+ explicit AutofillPopupViewGtk(AutofillPopupController* controller);
+
+ private:
virtual ~AutofillPopupViewGtk();
// AutofillPopupView implementation.
virtual void Hide() OVERRIDE;
-
- protected:
- // AutofillPopupView implementations.
- virtual void ShowInternal() OVERRIDE;
+ virtual void Show() OVERRIDE;
virtual void InvalidateRow(size_t row) OVERRIDE;
- virtual void UpdateBoundsAndRedrawPopupInternal() OVERRIDE;
+ virtual void UpdateBoundsAndRedrawPopup() OVERRIDE;
- private:
CHROMEGTK_CALLBACK_1(AutofillPopupViewGtk, gboolean, HandleButtonRelease,
GdkEventButton*);
CHROMEGTK_CALLBACK_1(AutofillPopupViewGtk, gboolean, HandleExpose,
@@ -61,9 +57,6 @@ class AutofillPopupViewGtk : public AutofillPopupView,
CHROMEGTK_CALLBACK_1(AutofillPopupViewGtk, gboolean, HandleMotion,
GdkEventMotion*);
- // KeyboardListener implementation.
- virtual bool HandleKeyPressEvent(GdkEventKey* event) OVERRIDE;
-
// Set up the pango layout to display the autofill results.
void SetupLayout(const gfx::Rect& window_rect);
@@ -85,12 +78,10 @@ class AutofillPopupViewGtk : public AutofillPopupView,
// of it.
void SetInitialBounds();
- GtkWidget* parent_; // Weak reference.
- GtkWidget* window_; // Strong reference.
- PangoLayout* layout_; // Strong reference
- GtkThemeService* theme_service_;
+ AutofillPopupController* controller_; // Weak reference.
- content::RenderViewHost* render_view_host_; // Weak reference.
+ GtkWidget* window_; // Strong reference.
+ PangoLayout* layout_; // Strong reference.
DISALLOW_COPY_AND_ASSIGN(AutofillPopupViewGtk);
};
diff --git a/chrome/browser/ui/views/autofill/autofill_external_delegate_views.cc b/chrome/browser/ui/views/autofill/autofill_external_delegate_views.cc
deleted file mode 100644
index ebbb77f..0000000
--- a/chrome/browser/ui/views/autofill/autofill_external_delegate_views.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-// 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/ui/views/autofill/autofill_external_delegate_views.h"
-
-#include "chrome/browser/ui/views/autofill/autofill_popup_view_views.h"
-
-void AutofillExternalDelegate::CreateForWebContentsAndManager(
- content::WebContents* web_contents,
- AutofillManager* autofill_manager) {
- if (FromWebContents(web_contents))
- return;
-
- web_contents->SetUserData(
- UserDataKey(),
- new AutofillExternalDelegateViews(web_contents, autofill_manager));
-}
-
-AutofillExternalDelegateViews::AutofillExternalDelegateViews(
- content::WebContents* web_contents,
- AutofillManager* autofill_manager)
- : AutofillExternalDelegate(web_contents, autofill_manager),
- popup_view_(NULL) {
-}
-
-AutofillExternalDelegateViews::~AutofillExternalDelegateViews() {
- if (popup_view_) {
- popup_view_->ClearExternalDelegate();
- }
-}
-
-void AutofillExternalDelegateViews::InvalidateView() {
- popup_view_ = NULL;
- HideAutofillPopup();
-}
-
-void AutofillExternalDelegateViews::HideAutofillPopupInternal() {
- if (!popup_view_)
- return;
-
- popup_view_->Hide();
- popup_view_ = NULL;
-}
-
-void AutofillExternalDelegateViews::CreatePopupForElement(
- const gfx::Rect& element_bounds) {
- DCHECK(!popup_view_);
- popup_view_ = new AutofillPopupViewViews(
- web_contents(), this, element_bounds);
-}
-
-void AutofillExternalDelegateViews::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) {
- popup_view_->Show(autofill_values,
- autofill_labels,
- autofill_icons,
- autofill_unique_ids);
-}
diff --git a/chrome/browser/ui/views/autofill/autofill_external_delegate_views.h b/chrome/browser/ui/views/autofill/autofill_external_delegate_views.h
deleted file mode 100644
index 26b66f2..0000000
--- a/chrome/browser/ui/views/autofill/autofill_external_delegate_views.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// 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_VIEWS_AUTOFILL_AUTOFILL_EXTERNAL_DELEGATE_VIEWS_H_
-#define CHROME_BROWSER_UI_VIEWS_AUTOFILL_AUTOFILL_EXTERNAL_DELEGATE_VIEWS_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "chrome/browser/autofill/autofill_external_delegate.h"
-
-class AutofillPopupViewViews;
-
-// The View specific implementations of the AutofillExternalDelegate,
-// handling the communication between the Autofill and Autocomplete
-// selection and the popup that shows the values.
-class AutofillExternalDelegateViews : public AutofillExternalDelegate {
- public:
- AutofillExternalDelegateViews(content::WebContents* web_contents,
- AutofillManager* autofill_manager);
-
- virtual ~AutofillExternalDelegateViews();
-
- // Used by the popup view to indicate it has been destroyed.
- void InvalidateView();
-
- protected:
- AutofillPopupViewViews* popup_view() { return popup_view_; }
-
- // AutofillExternalDelegate implementation.
- // Make protected to allow tests to override.
- virtual void HideAutofillPopupInternal() OVERRIDE;
- virtual void CreatePopupForElement(const gfx::Rect& element_bounds) OVERRIDE;
-
- private:
- // AutofillExternalDelegate implementation.
- 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) OVERRIDE;
-
- // We use a raw pointer here because even though we usually create the view,
- // its widget handles deleting it (which means it may outlive this object).
- AutofillPopupViewViews* popup_view_;
-
- DISALLOW_COPY_AND_ASSIGN(AutofillExternalDelegateViews);
-};
-
-#endif // CHROME_BROWSER_UI_VIEWS_AUTOFILL_AUTOFILL_EXTERNAL_DELEGATE_VIEWS_H_
diff --git a/chrome/browser/ui/views/autofill/autofill_external_delegate_views_browsertest.cc b/chrome/browser/ui/views/autofill/autofill_external_delegate_views_browsertest.cc
deleted file mode 100644
index 0837349..0000000
--- a/chrome/browser/ui/views/autofill/autofill_external_delegate_views_browsertest.cc
+++ /dev/null
@@ -1,105 +0,0 @@
-// 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/ui/views/autofill/autofill_external_delegate_views.h"
-
-#include "base/memory/scoped_ptr.h"
-#include "chrome/browser/autofill/autofill_manager.h"
-#include "chrome/browser/autofill/test_autofill_external_delegate.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_tabstrip.h"
-#include "chrome/browser/ui/views/autofill/autofill_popup_view_views.h"
-#include "chrome/test/base/in_process_browser_test.h"
-#include "content/public/browser/navigation_controller.h"
-#include "content/public/browser/notification_types.h"
-#include "content/public/common/url_constants.h"
-#include "content/public/test/test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/views/widget/widget.h"
-
-namespace {
-
-class MockAutofillExternalDelegateViews : public AutofillExternalDelegateViews {
- public:
- explicit MockAutofillExternalDelegateViews(content::WebContents* web_contents)
- : AutofillExternalDelegateViews(
- web_contents,
- AutofillManager::FromWebContents(web_contents)),
- popup_hidden_(false) {}
- ~MockAutofillExternalDelegateViews() {}
-
- void HideAutofillPopupInternal() OVERRIDE {
- popup_hidden_ = true;
- AutofillExternalDelegateViews::HideAutofillPopupInternal();
- }
-
- AutofillPopupViewViews* popup_view() {
- return AutofillExternalDelegateViews::popup_view();
- }
-
- virtual void ClearPreviewedForm() OVERRIDE {}
-
- bool popup_hidden_;
-};
-
-} // namespace
-
-class AutofillExternalDelegateViewsBrowserTest : public InProcessBrowserTest {
- public:
- AutofillExternalDelegateViewsBrowserTest() {}
- virtual ~AutofillExternalDelegateViewsBrowserTest() {}
-
- virtual void SetUpOnMainThread() OVERRIDE {
- web_contents_ = chrome::GetActiveWebContents(browser());
- ASSERT_TRUE(web_contents_ != NULL);
-
- autofill_external_delegate_.reset(
- new MockAutofillExternalDelegateViews(web_contents_));
- }
-
- protected:
- content::WebContents* web_contents_;
- scoped_ptr<MockAutofillExternalDelegateViews> autofill_external_delegate_;
-};
-
-IN_PROC_BROWSER_TEST_F(AutofillExternalDelegateViewsBrowserTest,
- OpenAndClosePopup) {
- autofill::GenerateTestAutofillPopup(autofill_external_delegate_.get());
-
- autofill_external_delegate_->HideAutofillPopup();
- EXPECT_TRUE(autofill_external_delegate_->popup_hidden_);
-}
-
-// See http://crbug.com/164019
-#if !defined(USE_AURA)
-IN_PROC_BROWSER_TEST_F(AutofillExternalDelegateViewsBrowserTest,
- CloseWidgetAndNoLeaking) {
- autofill::GenerateTestAutofillPopup(autofill_external_delegate_.get());
- // Delete the widget to ensure that the external delegate can handle the
- // popup getting deleted elsewhere.
- views::Widget* popup_widget =
- autofill_external_delegate_->popup_view()->GetWidget();
- popup_widget->CloseNow();
-
- EXPECT_TRUE(autofill_external_delegate_->popup_hidden_);
-}
-#endif // !defined(USE_AURA)
-
-IN_PROC_BROWSER_TEST_F(AutofillExternalDelegateViewsBrowserTest,
- HandlePopupClosingAndChangingPages) {
- autofill::GenerateTestAutofillPopup(autofill_external_delegate_.get());
-
- // Close popup.
- autofill_external_delegate_->HideAutofillPopup();
-
- // Navigate to a new page
- content::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));
- observer.Wait();
-}
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_view_views.cc b/chrome/browser/ui/views/autofill/autofill_popup_view_views.cc
index 81845e2..224ca81 100644
--- a/chrome/browser/ui/views/autofill/autofill_popup_view_views.cc
+++ b/chrome/browser/ui/views/autofill/autofill_popup_view_views.cc
@@ -2,12 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "autofill_popup_view_views.h"
+#include "chrome/browser/ui/views/autofill/autofill_popup_view_views.h"
-#include "chrome/browser/ui/views/autofill/autofill_external_delegate_views.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_view.h"
+#include "chrome/browser/ui/autofill/autofill_popup_controller.h"
#include "grit/ui_resources.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebAutofillClient.h"
#include "ui/base/keycodes/keyboard_codes.h"
@@ -24,6 +21,7 @@
using WebKit::WebAutofillClient;
namespace {
+
const SkColor kBorderColor = SkColorSetARGB(0xFF, 0xC7, 0xCA, 0xCE);
const SkColor kHoveredBackgroundColor = SkColorSetARGB(0xFF, 0xCD, 0xCD, 0xCD);
const SkColor kLabelTextColor = SkColorSetARGB(0xFF, 0x7F, 0x7F, 0x7F);
@@ -33,50 +31,49 @@ const SkColor kValueTextColor = SkColorSetARGB(0xFF, 0x00, 0x00, 0x00);
} // namespace
AutofillPopupViewViews::AutofillPopupViewViews(
- content::WebContents* web_contents,
- AutofillExternalDelegateViews* external_delegate,
- const gfx::Rect& element_bounds)
- : AutofillPopupView(web_contents, external_delegate, element_bounds),
- external_delegate_(external_delegate),
- web_contents_(web_contents) {
-}
+ AutofillPopupController* controller)
+ : controller_(controller),
+ observing_widget_(NULL) {}
AutofillPopupViewViews::~AutofillPopupViewViews() {
- external_delegate_->InvalidateView();
+ if (observing_widget_)
+ observing_widget_->RemoveObserver(this);
+
+ controller_->ViewDestroyed();
}
void AutofillPopupViewViews::Hide() {
- if (GetWidget())
+ if (GetWidget()) {
+ // This deletes |this|.
GetWidget()->Close();
- web_contents_->GetRenderViewHost()->RemoveKeyboardListener(this);
-
- views::Widget* browser_widget =
- views::Widget::GetTopLevelWidgetForNativeView(
- web_contents_->GetView()->GetTopLevelNativeWindow());
- browser_widget->RemoveObserver(this);
+ } else {
+ delete this;
+ }
}
void AutofillPopupViewViews::OnPaint(gfx::Canvas* canvas) {
canvas->DrawColor(kPopupBackground);
OnPaintBorder(canvas);
- for (size_t i = 0; i < autofill_values().size(); ++i) {
- gfx::Rect line_rect = GetRectForRow(i, width());
+ for (size_t i = 0; i < controller_->autofill_values().size(); ++i) {
+ gfx::Rect line_rect = controller_->GetRectForRow(i, width());
- if (autofill_unique_ids()[i] == WebAutofillClient::MenuItemIDSeparator)
+ if (controller_->autofill_unique_ids()[i] ==
+ WebAutofillClient::MenuItemIDSeparator) {
canvas->DrawRect(line_rect, kLabelTextColor);
- else
+ } else {
DrawAutofillEntry(canvas, i, line_rect);
+ }
}
}
void AutofillPopupViewViews::OnMouseCaptureLost() {
- ClearSelectedLine();
+ controller_->ClearSelectedLine();
}
bool AutofillPopupViewViews::OnMouseDragged(const ui::MouseEvent& event) {
if (HitTestPoint(gfx::Point(event.x(), event.y()))) {
- SetSelectedPosition(event.x(), event.y());
+ controller_->SetSelectedPosition(event.x(), event.y());
// We must return true in order to get future OnMouseDragged and
// OnMouseReleased events.
@@ -84,16 +81,16 @@ bool AutofillPopupViewViews::OnMouseDragged(const ui::MouseEvent& event) {
}
// If we move off of the popup, we lose the selection.
- ClearSelectedLine();
+ controller_->ClearSelectedLine();
return false;
}
void AutofillPopupViewViews::OnMouseExited(const ui::MouseEvent& event) {
- ClearSelectedLine();
+ controller_->ClearSelectedLine();
}
void AutofillPopupViewViews::OnMouseMoved(const ui::MouseEvent& event) {
- SetSelectedPosition(event.x(), event.y());
+ controller_->SetSelectedPosition(event.x(), event.y());
}
bool AutofillPopupViewViews::OnMousePressed(const ui::MouseEvent& event) {
@@ -105,42 +102,16 @@ void AutofillPopupViewViews::OnMouseReleased(const ui::MouseEvent& event) {
// We only care about the left click.
if (event.IsOnlyLeftMouseButton() &&
HitTestPoint(gfx::Point(event.x(), event.y())))
- AcceptSelectedPosition(event.x(), event.y());
+ controller_->AcceptSelectedPosition(event.x(), event.y());
}
void AutofillPopupViewViews::OnWidgetBoundsChanged(
views::Widget* widget,
const gfx::Rect& new_bounds) {
- external_delegate()->HideAutofillPopup();
+ Hide();
}
-bool AutofillPopupViewViews::HandleKeyPressEvent(ui::KeyEvent* event) {
- switch (event->key_code()) {
- case ui::VKEY_UP:
- SelectPreviousLine();
- return true;
- case ui::VKEY_DOWN:
- SelectNextLine();
- return true;
- case ui::VKEY_PRIOR:
- SetSelectedLine(0);
- return true;
- case ui::VKEY_NEXT:
- SetSelectedLine(autofill_values().size() - 1);
- return true;
- case ui::VKEY_ESCAPE:
- external_delegate()->HideAutofillPopup();
- return true;
- case ui::VKEY_DELETE:
- return event->IsShiftDown() && RemoveSelectedLine();
- case ui::VKEY_RETURN:
- return AcceptSelectedLine();
- default:
- return false;
- }
-}
-
-void AutofillPopupViewViews::ShowInternal() {
+void AutofillPopupViewViews::Show() {
if (!GetWidget()) {
// The widget is destroyed by the corresponding NativeWidget, so we use
// a weak pointer to hold the reference and don't have to worry about
@@ -150,47 +121,37 @@ void AutofillPopupViewViews::ShowInternal() {
params.delegate = this;
params.can_activate = false;
params.transparent = true;
- params.parent = web_contents_->GetView()->GetTopLevelNativeWindow();
+ params.parent = controller_->container_view();
widget->Init(params);
widget->SetContentsView(this);
widget->Show();
- gfx::Rect client_area;
- web_contents_->GetContainerBounds(&client_area);
- widget->SetBounds(client_area);
-
- // Setup an observer to check for when the browser moves or changes size,
- // since the popup should always be hidden in those cases.
- views::Widget* browser_widget =
- views::Widget::GetTopLevelWidgetForNativeView(
- web_contents_->GetView()->GetTopLevelNativeWindow());
- browser_widget->AddObserver(this);
-
// Allow the popup to appear anywhere on the screen, since it may need
// to go beyond the bounds of the window.
// TODO(csharp): allow the popup to still appear on the border of
// two screens.
- widget->SetBounds(gfx::Rect(0,
- 0,
- GetScreenSize().height(),
- GetScreenSize().width()));
+ widget->SetBounds(gfx::Rect(GetScreenSize()));
+
+ // Setup an observer to check for when the browser moves or changes size,
+ // since the popup should always be hidden in those cases.
+ observing_widget_ = views::Widget::GetTopLevelWidgetForNativeView(
+ controller_->container_view());
+ observing_widget_->AddObserver(this);
}
set_border(views::Border::CreateSolidBorder(kBorderThickness, kBorderColor));
SetInitialBounds();
UpdateBoundsAndRedrawPopup();
-
- web_contents_->GetRenderViewHost()->AddKeyboardListener(this);
}
void AutofillPopupViewViews::InvalidateRow(size_t row) {
- SchedulePaintInRect(GetRectForRow(row, width()));
+ SchedulePaintInRect(controller_->GetRectForRow(row, width()));
}
-void AutofillPopupViewViews::UpdateBoundsAndRedrawPopupInternal() {
- SetBoundsRect(popup_bounds());
- SchedulePaintInRect(popup_bounds());
+void AutofillPopupViewViews::UpdateBoundsAndRedrawPopup() {
+ SetBoundsRect(controller_->popup_bounds());
+ SchedulePaintInRect(controller_->popup_bounds());
}
void AutofillPopupViewViews::DrawAutofillEntry(gfx::Canvas* canvas,
@@ -198,16 +159,17 @@ void AutofillPopupViewViews::DrawAutofillEntry(gfx::Canvas* canvas,
const gfx::Rect& entry_rect) {
// TODO(csharp): support RTL
- if (selected_line() == index)
+ if (controller_->selected_line() == index)
canvas->FillRect(entry_rect, kHoveredBackgroundColor);
canvas->DrawStringInt(
- autofill_values()[index],
- value_font(),
+ controller_->autofill_values()[index],
+ controller_->value_font(),
kValueTextColor,
kEndPadding,
entry_rect.y(),
- canvas->GetStringWidth(autofill_values()[index], value_font()),
+ canvas->GetStringWidth(controller_->autofill_values()[index],
+ controller_->value_font()),
entry_rect.height(),
gfx::Canvas::TEXT_ALIGN_CENTER);
@@ -216,8 +178,9 @@ void AutofillPopupViewViews::DrawAutofillEntry(gfx::Canvas* canvas,
// Draw the delete icon, if one is needed.
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
- int row_height = GetRowHeightFromId(autofill_unique_ids()[index]);
- if (CanDelete(autofill_unique_ids()[index])) {
+ int row_height = controller_->GetRowHeightFromId(
+ controller_->autofill_unique_ids()[index]);
+ if (controller_->CanDelete(controller_->autofill_unique_ids()[index])) {
x_align_left -= kDeleteIconWidth;
// TODO(csharp): Create a custom resource for the delete icon.
@@ -231,10 +194,11 @@ void AutofillPopupViewViews::DrawAutofillEntry(gfx::Canvas* canvas,
}
// Draw the Autofill icon, if one exists
- if (!autofill_icons()[index].empty()) {
- int icon = GetIconResourceID(autofill_icons()[index]);
+ if (!controller_->autofill_icons()[index].empty()) {
+ int icon =
+ controller_->GetIconResourceID(controller_->autofill_icons()[index]);
DCHECK_NE(-1, icon);
- int icon_y = entry_rect.y() + ((row_height - kAutofillIconHeight) / 2);
+ int icon_y = entry_rect.y() + (row_height - kAutofillIconHeight) / 2;
x_align_left -= kAutofillIconWidth;
@@ -244,51 +208,53 @@ void AutofillPopupViewViews::DrawAutofillEntry(gfx::Canvas* canvas,
}
// Draw the label text.
- x_align_left -= canvas->GetStringWidth(autofill_labels()[index],
- label_font());
+ x_align_left -= canvas->GetStringWidth(controller_->autofill_labels()[index],
+ controller_->label_font());
canvas->DrawStringInt(
- autofill_labels()[index],
- label_font(),
+ controller_->autofill_labels()[index],
+ controller_->label_font(),
kLabelTextColor,
x_align_left + kEndPadding,
entry_rect.y(),
- canvas->GetStringWidth(autofill_labels()[index], label_font()),
+ canvas->GetStringWidth(controller_->autofill_labels()[index],
+ controller_->label_font()),
entry_rect.height(),
gfx::Canvas::TEXT_ALIGN_CENTER);
}
void AutofillPopupViewViews::SetInitialBounds() {
- // Find the client area of the contents to find our offset.
- gfx::Rect client_area;
- web_contents_->GetContainerBounds(&client_area);
-
- int bottom_of_field = client_area.y() + element_bounds().y() +
- element_bounds().height();
- int popup_height = GetPopupRequiredHeight();
+ int bottom_of_field = controller_->element_bounds().bottom();
+ int popup_height = controller_->GetPopupRequiredHeight();
// Find the correct top position of the popup so that it doesn't go off
// the screen.
int top_of_popup = 0;
if (GetScreenSize().height() < bottom_of_field + popup_height) {
// The popup must appear above the field.
- top_of_popup = element_bounds().y() - popup_height;
+ top_of_popup = controller_->element_bounds().y() - popup_height;
} else {
// The popup can appear below the field.
top_of_popup = bottom_of_field;
}
- SetPopupBounds(gfx::Rect(client_area.x() + element_bounds().x(),
- top_of_popup,
- GetPopupRequiredWidth(),
- popup_height));
+ controller_->SetPopupBounds(gfx::Rect(
+ controller_->element_bounds().x(),
+ top_of_popup,
+ controller_->GetPopupRequiredWidth(),
+ popup_height));
}
gfx::Size AutofillPopupViewViews::GetScreenSize() {
- gfx::Screen* screen = gfx::Screen::GetScreenFor(
- web_contents_->GetView()->GetTopLevelNativeWindow());
- gfx::Display display = screen->GetDisplayNearestPoint(
- gfx::Point(element_bounds().x(), element_bounds().y()));
+ gfx::Screen* screen =
+ gfx::Screen::GetScreenFor(controller_->container_view());
+ gfx::Display display =
+ screen->GetDisplayNearestPoint(controller_->element_bounds().origin());
return display.GetSizeInPixel();
}
+
+AutofillPopupView* AutofillPopupView::Create(
+ AutofillPopupController* controller) {
+ return new AutofillPopupViewViews(controller);
+}
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_view_views.h b/chrome/browser/ui/views/autofill/autofill_popup_view_views.h
index a9dd94f..c37e61b 100644
--- a/chrome/browser/ui/views/autofill/autofill_popup_view_views.h
+++ b/chrome/browser/ui/views/autofill/autofill_popup_view_views.h
@@ -5,35 +5,32 @@
#ifndef CHROME_BROWSER_UI_VIEWS_AUTOFILL_AUTOFILL_POPUP_VIEW_VIEWS_H_
#define CHROME_BROWSER_UI_VIEWS_AUTOFILL_AUTOFILL_POPUP_VIEW_VIEWS_H_
-#include "chrome/browser/autofill/autofill_popup_view.h"
-#include "content/public/browser/keyboard_listener.h"
+#include "chrome/browser/ui/autofill/autofill_popup_view.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/widget/widget_observer.h"
-class AutofillExternalDelegateViews;
+class AutofillPopupController;
namespace content {
class WebContents;
}
-// The View Autofill popup implementation.
-class AutofillPopupViewViews : public views::WidgetDelegateView,
- public AutofillPopupView,
- public views::WidgetObserver,
- public KeyboardListener {
+// Views toolkit implementation for AutofillPopupView.
+class AutofillPopupViewViews : public AutofillPopupView,
+ public views::WidgetDelegateView,
+ public views::WidgetObserver {
public:
- AutofillPopupViewViews(content::WebContents* web_contents,
- AutofillExternalDelegateViews* external_delegate,
- const gfx::Rect& element_bounds);
-
- // AutofillPopupView implementation.
- virtual void Hide() OVERRIDE;
+ explicit AutofillPopupViewViews(AutofillPopupController* controller);
private:
- class AutofillPopupWidget;
-
virtual ~AutofillPopupViewViews();
+ // AutofillPopupView implementation.
+ virtual void Show() OVERRIDE;
+ virtual void Hide() OVERRIDE;
+ virtual void InvalidateRow(size_t row) OVERRIDE;
+ virtual void UpdateBoundsAndRedrawPopup() OVERRIDE;
+
// views:Views implementation.
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
@@ -47,14 +44,6 @@ class AutofillPopupViewViews : public views::WidgetDelegateView,
virtual void OnWidgetBoundsChanged(views::Widget* widget,
const gfx::Rect& new_bounds) OVERRIDE;
- // KeyboardListener implementation.
- virtual bool HandleKeyPressEvent(ui::KeyEvent* event) OVERRIDE;
-
- // AutofillPopupView implementation.
- virtual void ShowInternal() OVERRIDE;
- virtual void InvalidateRow(size_t row) OVERRIDE;
- virtual void UpdateBoundsAndRedrawPopupInternal() OVERRIDE;
-
// Draw the given autofill entry in |entry_rect|.
void DrawAutofillEntry(gfx::Canvas* canvas,
int index,
@@ -67,8 +56,10 @@ class AutofillPopupViewViews : public views::WidgetDelegateView,
// Get the size of the screen that the popup appears of, in pixels.
gfx::Size GetScreenSize();
- AutofillExternalDelegateViews* external_delegate_; // Weak reference.
- content::WebContents* web_contents_; // Weak reference.
+ AutofillPopupController* controller_; // Weak reference.
+
+ // The widget that |this| observes. Weak reference.
+ views::Widget* observing_widget_;
DISALLOW_COPY_AND_ASSIGN(AutofillPopupViewViews);
};
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 682d7d8..a5e9683 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -202,8 +202,6 @@
'browser/autofill/autofill_manager_delegate.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',
diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi
index a172494..e005f10 100644
--- a/chrome/chrome_browser_ui.gypi
+++ b/chrome/chrome_browser_ui.gypi
@@ -70,8 +70,6 @@
'browser/ui/alternate_error_tab_observer.h',
'browser/ui/android/android_about_app_info.cc',
'browser/ui/android/android_about_app_info.h',
- 'browser/ui/android/autofill/autofill_external_delegate.cc',
- 'browser/ui/android/autofill/autofill_external_delegate.h',
'browser/ui/android/autofill/autofill_popup_view_android.cc',
'browser/ui/android/autofill/autofill_popup_view_android.h',
'browser/ui/android/certificate_viewer_android.cc',
@@ -186,6 +184,11 @@
'browser/ui/autofill/autofill_dialog_controller.h',
'browser/ui/autofill/autofill_dialog_view.cc',
'browser/ui/autofill/autofill_dialog_view.h',
+ 'browser/ui/autofill/autofill_popup_controller.h',
+ 'browser/ui/autofill/autofill_popup_controller_impl.cc',
+ 'browser/ui/autofill/autofill_popup_controller_impl.h',
+ 'browser/ui/autofill/autofill_popup_view.cc',
+ 'browser/ui/autofill/autofill_popup_view.h',
'browser/ui/autofill/tab_autofill_manager_delegate.cc',
'browser/ui/autofill/tab_autofill_manager_delegate.h',
'browser/ui/auto_login_info_bar_delegate.cc',
@@ -842,8 +845,6 @@
'browser/ui/gtk/accelerators_gtk.h',
'browser/ui/gtk/action_box_button_gtk.cc',
'browser/ui/gtk/action_box_button_gtk.h',
- 'browser/ui/gtk/autofill/autofill_external_delegate_gtk.cc',
- 'browser/ui/gtk/autofill/autofill_external_delegate_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',
@@ -1347,8 +1348,6 @@
'browser/ui/views/ash/tab_scrubber.cc',
'browser/ui/views/autofill/autofill_dialog_views.cc',
'browser/ui/views/autofill/autofill_dialog_views.h',
- 'browser/ui/views/autofill/autofill_external_delegate_views.cc',
- 'browser/ui/views/autofill/autofill_external_delegate_views.h',
'browser/ui/views/autofill/autofill_popup_view_views.cc',
'browser/ui/views/autofill/autofill_popup_view_views.h',
'browser/ui/views/avatar_menu_bubble_view.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 51a23cd..81ce1d0 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -837,7 +837,7 @@
'browser/app_controller_mac_browsertest.mm',
'browser/autocomplete/autocomplete_browsertest.cc',
'browser/autofill/autofill_browsertest.cc',
- 'browser/autofill/autofill_popup_view_browsertest.cc',
+ 'browser/autofill/autofill_external_delegate_browsertest.cc',
'browser/autofill/form_structure_browsertest.cc',
'browser/automation/automation_misc_browsertest.cc',
'browser/automation/automation_tab_helper_browsertest.cc',
@@ -1166,7 +1166,6 @@
'browser/ui/find_bar/find_bar_host_browsertest.cc',
'browser/ui/fullscreen/fullscreen_controller_browsertest.cc',
'browser/ui/global_error/global_error_service_browsertest.cc',
- 'browser/ui/gtk/autofill/autofill_external_delegate_gtk_browsertest.cc',
'browser/ui/gtk/bubble/bubble_gtk_browsertest.cc',
'browser/ui/gtk/confirm_bubble_gtk_browsertest.cc',
'browser/ui/gtk/location_bar_view_gtk_browsertest.cc',
@@ -1182,7 +1181,6 @@
'browser/ui/startup/startup_browser_creator_browsertest.cc',
'browser/ui/tab_modal_confirm_dialog_browsertest.cc',
'browser/ui/tab_modal_confirm_dialog_browsertest.h',
- 'browser/ui/views/autofill/autofill_external_delegate_views_browsertest.cc',
'browser/ui/views/browser_actions_container_browsertest.cc',
'browser/ui/views/find_bar_controller_browsertest.cc',
'browser/ui/views/frame/app_non_client_frame_view_ash_browsertest.cc',
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index 5a5d16d..561cfa0 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -459,7 +459,6 @@
'browser/autofill/autofill_merge_unittest.cc',
'browser/autofill/autofill_metrics_unittest.cc',
'browser/autofill/autofill_profile_unittest.cc',
- 'browser/autofill/autofill_popup_unittest.cc',
'browser/autofill/autofill_regexes_unittest.cc',
'browser/autofill/autofill_type_unittest.cc',
'browser/autofill/autofill_xml_parser_unittest.cc',
@@ -1163,6 +1162,7 @@
'browser/ui/ash/launcher/chrome_launcher_controller_per_browser_unittest.cc',
'browser/ui/ash/window_positioner_unittest.cc',
'browser/ui/auto_login_prompter_unittest.cc',
+ 'browser/ui/autofill/autofill_popup_controller_unittest.cc',
'browser/ui/bookmarks/bookmark_context_menu_controller_unittest.cc',
'browser/ui/bookmarks/bookmark_prompt_controller_unittest.cc',
'browser/ui/bookmarks/bookmark_ui_utils_unittest.cc',
@@ -2130,6 +2130,10 @@
# Test files cannot be opened on Android.
'browser/google_apis/gdata_wapi_operations_unittest.cc',
'browser/google_apis/gdata_wapi_parser_unittest.cc',
+
+ # The autofill popup is implemented in mostly native code on
+ # Android.
+ 'browser/ui/autofill/autofill_popup_controller_unittest.cc',
],
'sources/': [
['exclude', '^browser/captive_portal/'],
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 86cdf09..832de43 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -1162,24 +1162,9 @@ void RenderWidgetHostImpl::ForwardTouchEvent(
touch_event_queue_->QueueEvent(touch_event);
}
-#if defined(TOOLKIT_GTK)
-bool RenderWidgetHostImpl::KeyPressListenersHandleEvent(GdkEventKey* event) {
- if (event->type != GDK_KEY_PRESS)
- return false;
-
- for (std::list<KeyboardListener*>::iterator it = keyboard_listeners_.begin();
- it != keyboard_listeners_.end(); ++it) {
- if ((*it)->HandleKeyPressEvent(event))
- return true;
- }
-
- return false;
-}
-#endif // defined(TOOLKIT_GTK)
-
-#if defined(TOOLKIT_VIEWS)
-bool RenderWidgetHostImpl::KeyPressListenersHandleEvent(ui::KeyEvent* event) {
- if (event->type() != ui::ET_KEY_PRESSED)
+bool RenderWidgetHostImpl::KeyPressListenersHandleEvent(
+ const NativeWebKeyboardEvent& event) {
+ if (event.type != WebKeyboardEvent::RawKeyDown)
return false;
for (std::list<KeyboardListener*>::iterator it = keyboard_listeners_.begin();
@@ -1190,7 +1175,6 @@ bool RenderWidgetHostImpl::KeyPressListenersHandleEvent(ui::KeyEvent* event) {
return false;
}
-#endif // defined(TOOLKIT_VIEWS)
void RenderWidgetHostImpl::AddKeyboardListener(KeyboardListener* listener) {
keyboard_listeners_.push_back(listener);
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h
index 7c335f4..30c8b12 100644
--- a/content/browser/renderer_host/render_widget_host_impl.h
+++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -249,15 +249,9 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
void ForwardGestureEventImmediately(
const WebKit::WebGestureEvent& gesture_event);
-#if defined(TOOLKIT_GTK)
// Give key press listeners a chance to handle this key press. This allow
// widgets that don't have focus to still handle key presses.
- bool KeyPressListenersHandleEvent(GdkEventKey* event);
-#endif // defined(TOOLKIT_GTK)
-
-#if defined(TOOLKIT_VIEWS)
- bool KeyPressListenersHandleEvent(ui::KeyEvent* event);
-#endif // defined(TOOLKIT_VIEWS)
+ bool KeyPressListenersHandleEvent(const NativeWebKeyboardEvent& event);
void CancelUpdateTextDirection();
diff --git a/content/browser/renderer_host/render_widget_host_view_gtk.cc b/content/browser/renderer_host/render_widget_host_view_gtk.cc
index 70ab67c..0ecfb35 100644
--- a/content/browser/renderer_host/render_widget_host_view_gtk.cc
+++ b/content/browser/renderer_host/render_widget_host_view_gtk.cc
@@ -225,7 +225,9 @@ class RenderWidgetHostViewGtkWidget {
if (should_close_on_escape && GDK_Escape == event->keyval) {
host_view->host_->Shutdown();
} else if (host_view->host_ &&
- host_view->host_->KeyPressListenersHandleEvent(event)) {
+ host_view->host_->KeyPressListenersHandleEvent(
+ NativeWebKeyboardEvent(reinterpret_cast<GdkEvent*>(
+ event)))) {
return TRUE;
} else {
// Send key event to input method.
diff --git a/content/browser/renderer_host/render_widget_host_view_win.cc b/content/browser/renderer_host/render_widget_host_view_win.cc
index 2cf0cc7..d8c2855 100644
--- a/content/browser/renderer_host/render_widget_host_view_win.cc
+++ b/content/browser/renderer_host/render_widget_host_view_win.cc
@@ -1825,12 +1825,13 @@ LRESULT RenderWidgetHostViewWin::OnKeyEvent(UINT message, WPARAM wparam,
MSG msg = { m_hWnd, message, wparam, lparam };
ui::KeyEvent key_event(msg, message == WM_CHAR);
if (render_widget_host_ &&
- render_widget_host_->KeyPressListenersHandleEvent(&key_event))
+ render_widget_host_->KeyPressListenersHandleEvent(
+ NativeWebKeyboardEvent(msg)))
return 0;
- if (render_widget_host_ && !ignore_keyboard_event) {
+ if (render_widget_host_ && !ignore_keyboard_event)
render_widget_host_->ForwardKeyboardEvent(NativeWebKeyboardEvent(msg));
- }
+
return 0;
}
diff --git a/content/public/browser/keyboard_listener.h b/content/public/browser/keyboard_listener.h
index 0609b4b..e69ab49 100644
--- a/content/public/browser/keyboard_listener.h
+++ b/content/public/browser/keyboard_listener.h
@@ -7,27 +7,18 @@
#include "content/common/content_export.h"
-// All systems should support key listening through ui::KeyEvent.
-// GTK doesn't because there is no easy way to convet GdkEventKey to
-// ui::KeyEvent and since it is going away soon, it is not worth the effort.
-#if defined(TOOLKIT_GTK)
-typedef struct _GdkEventKey GdkEventKey;
-#else
-namespace ui {
-class KeyEvent;
-} // namespace ui
-#endif
+namespace content {
+
+struct NativeWebKeyboardEvent;
class CONTENT_EXPORT KeyboardListener {
public:
-#if defined(TOOLKIT_GTK)
- virtual bool HandleKeyPressEvent(GdkEventKey* event) = 0;
-#else
- virtual bool HandleKeyPressEvent(ui::KeyEvent* event) = 0;
-#endif
+ virtual bool HandleKeyPressEvent(const NativeWebKeyboardEvent& event) = 0;
protected:
virtual ~KeyboardListener() {}
};
+} // content
+
#endif // CONTENT_PUBLIC_BROWSER_KEYBOARD_LISTENER_H_