summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/chrome_content_browser_client.cc2
-rw-r--r--chrome/browser/password_manager/password_generation_interactive_uitest.cc147
-rw-r--r--chrome/browser/password_manager/password_generation_manager.cc65
-rw-r--r--chrome/browser/password_manager/password_generation_manager.h35
-rw-r--r--chrome/browser/ui/autofill/password_generation_popup_controller_impl.cc14
-rw-r--r--chrome/browser/ui/autofill/password_generation_popup_controller_impl.h3
-rw-r--r--chrome/browser/ui/autofill/password_generation_popup_view.cc21
-rw-r--r--chrome/browser/ui/autofill/tab_autofill_manager_delegate.cc7
-rw-r--r--chrome/chrome_browser_ui.gypi1
-rw-r--r--chrome/chrome_tests.gypi5
-rw-r--r--chrome/chrome_tests_unit.gypi2
-rw-r--r--chrome/renderer/autofill/password_generation_agent_browsertest.cc146
-rw-r--r--chrome/renderer/chrome_content_renderer_client.cc9
-rw-r--r--chrome/test/base/chrome_render_view_test.cc12
-rw-r--r--chrome/test/base/chrome_render_view_test.h2
15 files changed, 360 insertions, 111 deletions
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 1fc665f..4863fbe 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -1545,7 +1545,7 @@ void ChromeContentBrowserClient::AppendExtraCommandLineSwitches(
autofill::switches::kEnableIgnoreAutocompleteOff,
autofill::switches::kEnableInteractiveAutocomplete,
autofill::switches::kEnablePasswordGeneration,
- autofill::switches::kNoAutofillNecessaryForPasswordGeneration,
+ autofill::switches::kLocalHeuristicsOnlyForPasswordGeneration,
extensions::switches::kAllowHTTPBackgroundPage,
extensions::switches::kAllowLegacyExtensionManifests,
extensions::switches::kAllowScriptingGallery,
diff --git a/chrome/browser/password_manager/password_generation_interactive_uitest.cc b/chrome/browser/password_manager/password_generation_interactive_uitest.cc
new file mode 100644
index 0000000..fff3b09
--- /dev/null
+++ b/chrome/browser/password_manager/password_generation_interactive_uitest.cc
@@ -0,0 +1,147 @@
+// Copyright 2014 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/command_line.h"
+#include "chrome/browser/password_manager/password_generation_manager.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/autofill/password_generation_popup_observer.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "components/autofill/core/browser/autofill_test_utils.h"
+#include "components/autofill/core/common/autofill_switches.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/browser_test_utils.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/keycodes/keyboard_codes.h"
+
+namespace {
+
+class TestPopupObserver : public autofill::PasswordGenerationPopupObserver {
+ public:
+ TestPopupObserver()
+ : popup_showing_(false) {}
+ virtual ~TestPopupObserver() {}
+
+ virtual void OnPopupShown() OVERRIDE {
+ popup_showing_ = true;
+ }
+
+ virtual void OnPopupHidden() OVERRIDE {
+ popup_showing_ = false;
+ }
+
+ bool popup_showing() { return popup_showing_; }
+
+ private:
+ bool popup_showing_;
+};
+
+} // namespace
+
+class PasswordGenerationInteractiveTest : public InProcessBrowserTest {
+ public:
+ virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ // Make sure the feature is enabled.
+ command_line->AppendSwitch(autofill::switches::kEnablePasswordGeneration);
+
+ // Don't require ping from autofill or blacklist checking.
+ command_line->AppendSwitch(
+ autofill::switches::kLocalHeuristicsOnlyForPasswordGeneration);
+ }
+
+ virtual void SetUpOnMainThread() OVERRIDE {
+ // Disable Autofill requesting access to AddressBook data. This will cause
+ // test tests to hang on Mac.
+ autofill::test::DisableSystemServices(browser()->profile());
+
+ // Set observer for popup.
+ PasswordGenerationManager* generation_manager =
+ PasswordGenerationManager::FromWebContents(GetWebContents());
+ generation_manager->SetTestObserver(&observer_);
+
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ GURL url = embedded_test_server()->GetURL("/password/signup_form.html");
+ ui_test_utils::NavigateToURL(browser(), url);
+ }
+
+ virtual void CleanUpOnMainThread() OVERRIDE {
+ // Cleanup UI.
+ PasswordGenerationManager* generation_manager =
+ PasswordGenerationManager::FromWebContents(GetWebContents());
+ generation_manager->HidePopup();
+ }
+
+ content::WebContents* GetWebContents() {
+ return browser()->tab_strip_model()->GetActiveWebContents();
+ }
+
+ content::RenderViewHost* GetRenderViewHost() {
+ return GetWebContents()->GetRenderViewHost();
+ }
+
+ std::string GetFieldValue(const std::string& field_id) {
+ std::string value;
+ EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+ GetRenderViewHost(),
+ "window.domAutomationController.send("
+ " document.getElementById('" + field_id + "').value);",
+ &value));
+ return value;
+ }
+
+ void FocusPasswordField() {
+ ASSERT_TRUE(content::ExecuteScript(
+ GetRenderViewHost(),
+ "document.getElementById('password_field').focus()"));
+ }
+
+ void SendKeyToPopup(ui::KeyboardCode key) {
+ content::NativeWebKeyboardEvent event;
+ event.windowsKeyCode = key;
+ event.type = blink::WebKeyboardEvent::RawKeyDown;
+ GetRenderViewHost()->ForwardKeyboardEvent(event);
+ }
+
+ bool popup_showing() {
+ return observer_.popup_showing();
+ }
+
+ private:
+ TestPopupObserver observer_;
+};
+
+#if defined(USE_AURA)
+// Enabled on these platforms
+#define MAYBE_PopupShownAndPasswordSelected PopupShownAndPasswordSelected
+#define MAYBE_PopupShownAndDismissed PopupShownAndDismissed
+#else
+// Popup not enabled for these platforms yet.
+#define MAYBE_PopupShownAndPasswordSelected DISABLED_PopupShownAndPasswordSelected
+#define MAYBE_PopupShownAndDismissed DISABLED_PopupShownAndDismissed
+#endif
+
+IN_PROC_BROWSER_TEST_F(PasswordGenerationInteractiveTest,
+ MAYBE_PopupShownAndPasswordSelected) {
+ FocusPasswordField();
+ EXPECT_TRUE(popup_showing());
+ SendKeyToPopup(ui::VKEY_DOWN);
+ SendKeyToPopup(ui::VKEY_RETURN);
+
+ EXPECT_FALSE(GetFieldValue("password_field").empty());
+}
+
+IN_PROC_BROWSER_TEST_F(PasswordGenerationInteractiveTest,
+ MAYBE_PopupShownAndDismissed) {
+ FocusPasswordField();
+ EXPECT_TRUE(popup_showing());
+
+ SendKeyToPopup(ui::VKEY_ESCAPE);
+
+ // Popup is dismissed.
+ EXPECT_FALSE(popup_showing());
+}
diff --git a/chrome/browser/password_manager/password_generation_manager.cc b/chrome/browser/password_manager/password_generation_manager.cc
index 0528120..d808b2f 100644
--- a/chrome/browser/password_manager/password_generation_manager.cc
+++ b/chrome/browser/password_manager/password_generation_manager.cc
@@ -8,6 +8,7 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
+#include "chrome/browser/ui/autofill/password_generation_popup_controller_impl.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_window.h"
@@ -21,6 +22,7 @@
#include "content/public/browser/browser_thread.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 "ipc/ipc_message_macros.h"
#include "ui/gfx/rect.h"
@@ -28,10 +30,16 @@ DEFINE_WEB_CONTENTS_USER_DATA_KEY(PasswordGenerationManager);
PasswordGenerationManager::PasswordGenerationManager(
content::WebContents* contents)
- : content::WebContentsObserver(contents) {}
+ : content::WebContentsObserver(contents),
+ observer_(NULL) {}
PasswordGenerationManager::~PasswordGenerationManager() {}
+void PasswordGenerationManager::SetTestObserver(
+ autofill::PasswordGenerationPopupObserver* observer) {
+ observer_ = observer;
+}
+
void PasswordGenerationManager::DetectAccountCreationForms(
const std::vector<autofill::FormStructure*>& forms) {
std::vector<autofill::FormData> account_creation_forms;
@@ -58,6 +66,10 @@ bool PasswordGenerationManager::OnMessageReceived(const IPC::Message& message) {
IPC_BEGIN_MESSAGE_MAP(PasswordGenerationManager, message)
IPC_MESSAGE_HANDLER(AutofillHostMsg_ShowPasswordGenerationPopup,
OnShowPasswordGenerationPopup)
+ IPC_MESSAGE_HANDLER(AutofillHostMsg_ShowPasswordEditingPopup,
+ OnShowPasswordEditingPopup)
+ IPC_MESSAGE_HANDLER(AutofillHostMsg_HidePasswordGenerationPopup,
+ OnHidePasswordGenerationPopup)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -102,17 +114,50 @@ void PasswordGenerationManager::SendAccountCreationFormsToRenderer(
host->GetRoutingID(), forms));
}
+gfx::RectF PasswordGenerationManager::GetBoundsInScreenSpace(
+ const gfx::RectF& bounds) {
+ gfx::Rect client_area;
+ web_contents()->GetView()->GetContainerBounds(&client_area);
+ return bounds + client_area.OffsetFromOrigin();
+}
+
void PasswordGenerationManager::OnShowPasswordGenerationPopup(
- const gfx::Rect& bounds,
+ const gfx::RectF& bounds,
int max_length,
const autofill::PasswordForm& form) {
-#if defined(OS_ANDROID)
- NOTIMPLEMENTED();
-#else
+ // TODO(gcasto): Validate data in PasswordForm.
+
+ // Only implemented for Aura right now.
+#if defined(USE_AURA)
+ // Convert element_bounds to be in screen space.
+ gfx::RectF element_bounds_in_screen_space = GetBoundsInScreenSpace(bounds);
+
password_generator_.reset(new autofill::PasswordGenerator(max_length));
- Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
- browser->window()->ShowPasswordGenerationBubble(bounds,
- form,
- password_generator_.get());
-#endif // #if defined(OS_ANDROID)
+
+ popup_controller_ =
+ autofill::PasswordGenerationPopupControllerImpl::GetOrCreate(
+ popup_controller_,
+ element_bounds_in_screen_space,
+ form,
+ password_generator_.get(),
+ PasswordManager::FromWebContents(web_contents()),
+ observer_,
+ web_contents(),
+ web_contents()->GetView()->GetNativeView());
+ popup_controller_->Show();
+#endif // #if defined(USE_AURA)
+}
+
+void PasswordGenerationManager::OnShowPasswordEditingPopup(
+ const gfx::RectF& bounds) {
+ // TODO(gcasto): Enable this.
+}
+
+void PasswordGenerationManager::OnHidePasswordGenerationPopup() {
+ HidePopup();
+}
+
+void PasswordGenerationManager::HidePopup() {
+ if (popup_controller_)
+ popup_controller_->HideAndDestroy();
}
diff --git a/chrome/browser/password_manager/password_generation_manager.h b/chrome/browser/password_manager/password_generation_manager.h
index 6d0a7ff..3eb4cbd 100644
--- a/chrome/browser/password_manager/password_generation_manager.h
+++ b/chrome/browser/password_manager/password_generation_manager.h
@@ -7,13 +7,17 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
+#include "ui/gfx/rect.h"
namespace autofill {
struct FormData;
class FormStructure;
class PasswordGenerator;
+class PasswordGenerationPopupControllerImpl;
+class PasswordGenerationPopupObserver;
struct PasswordForm;
}
@@ -46,6 +50,12 @@ class PasswordGenerationManager
void DetectAccountCreationForms(
const std::vector<autofill::FormStructure*>& forms);
+ // Hide any visible password generation related popups.
+ void HidePopup();
+
+ // Observer for PasswordGenerationPopup events. Used for testing.
+ void SetTestObserver(autofill::PasswordGenerationPopupObserver* observer);
+
protected:
explicit PasswordGenerationManager(content::WebContents* contents);
@@ -65,16 +75,33 @@ class PasswordGenerationManager
content::RenderViewHost* host,
const std::vector<autofill::FormData>& forms);
- // Causes the password generation bubble UI to be shown for the specified
- // form. The popup will be anchored at |icon_bounds|. The generated
- // password will be no longer than |max_length|.
- void OnShowPasswordGenerationPopup(const gfx::Rect& icon_bounds,
+ // Given |bounds| in the renderers coordinate system, return the same bounds
+ // in the screens coordinate system.
+ gfx::RectF GetBoundsInScreenSpace(const gfx::RectF& bounds);
+
+ // Causes the password generation UI to be shown for the specified form.
+ // The popup will be anchored at |element_bounds|. The generated password
+ // will be no longer than |max_length|.
+ void OnShowPasswordGenerationPopup(const gfx::RectF& element_bounds,
int max_length,
const autofill::PasswordForm& form);
+ // Causes the password editing UI to be shown anchored at |element_bounds|.
+ void OnShowPasswordEditingPopup(const gfx::RectF& element_bounds);
+
+ // Hide any visible UI.
+ void OnHidePasswordGenerationPopup();
+
+ // Observer for password generation popup.
+ autofill::PasswordGenerationPopupObserver* observer_;
+
// Controls how passwords are generated.
scoped_ptr<autofill::PasswordGenerator> password_generator_;
+ // Controls the popup
+ base::WeakPtr<
+ autofill::PasswordGenerationPopupControllerImpl> popup_controller_;
+
DISALLOW_COPY_AND_ASSIGN(PasswordGenerationManager);
};
diff --git a/chrome/browser/ui/autofill/password_generation_popup_controller_impl.cc b/chrome/browser/ui/autofill/password_generation_popup_controller_impl.cc
index 8d73906..1aa5dd6 100644
--- a/chrome/browser/ui/autofill/password_generation_popup_controller_impl.cc
+++ b/chrome/browser/ui/autofill/password_generation_popup_controller_impl.cc
@@ -105,7 +105,7 @@ bool PasswordGenerationPopupControllerImpl::HandleKeyPressEvent(
return true;
case ui::VKEY_RETURN:
case ui::VKEY_TAB:
- // We supress tab if the password is selected because we will
+ // We suppress tab if the password is selected because we will
// automatically advance focus anyway.
return PossiblyAcceptPassword();
default:
@@ -114,10 +114,12 @@ bool PasswordGenerationPopupControllerImpl::HandleKeyPressEvent(
}
bool PasswordGenerationPopupControllerImpl::PossiblyAcceptPassword() {
- if (password_selected_)
- PasswordAccepted();
+ if (password_selected_) {
+ PasswordAccepted(); // This will delete |this|.
+ return true;
+ }
- return password_selected_;
+ return false;
}
void PasswordGenerationPopupControllerImpl::PasswordSelected(bool selected) {
@@ -207,6 +209,10 @@ void PasswordGenerationPopupControllerImpl::Show() {
observer_->OnPopupShown();
}
+void PasswordGenerationPopupControllerImpl::HideAndDestroy() {
+ Hide();
+}
+
void PasswordGenerationPopupControllerImpl::Hide() {
controller_common_.RemoveKeyPressCallback();
diff --git a/chrome/browser/ui/autofill/password_generation_popup_controller_impl.h b/chrome/browser/ui/autofill/password_generation_popup_controller_impl.h
index 686d786..d36c884 100644
--- a/chrome/browser/ui/autofill/password_generation_popup_controller_impl.h
+++ b/chrome/browser/ui/autofill/password_generation_popup_controller_impl.h
@@ -59,6 +59,9 @@ class PasswordGenerationPopupControllerImpl
// Does not update the view if one is already showing.
void Show();
+ // Hides the popup and destroys |this|.
+ void HideAndDestroy();
+
// Accessors.
content::WebContents* web_contents() {
return controller_common_.web_contents();
diff --git a/chrome/browser/ui/autofill/password_generation_popup_view.cc b/chrome/browser/ui/autofill/password_generation_popup_view.cc
new file mode 100644
index 0000000..dd250ae
--- /dev/null
+++ b/chrome/browser/ui/autofill/password_generation_popup_view.cc
@@ -0,0 +1,21 @@
+// Copyright 2014 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 <cstddef>
+
+#include "chrome/browser/ui/autofill/password_generation_popup_view.h"
+
+// Non-aura is not implemented yet.
+#if !defined(USE_AURA)
+
+namespace autofill {
+
+PasswordGenerationPopupView* PasswordGenerationPopupView::Create(
+ PasswordGenerationPopupController* controller) {
+ return NULL;
+}
+
+} // namespace autofill
+
+#endif // #if !defined(USE_AURA)
diff --git a/chrome/browser/ui/autofill/tab_autofill_manager_delegate.cc b/chrome/browser/ui/autofill/tab_autofill_manager_delegate.cc
index 5e306e8..9c3dfdb 100644
--- a/chrome/browser/ui/autofill/tab_autofill_manager_delegate.cc
+++ b/chrome/browser/ui/autofill/tab_autofill_manager_delegate.cc
@@ -144,6 +144,13 @@ void TabAutofillManagerDelegate::UpdateAutofillPopupDataListValues(
void TabAutofillManagerDelegate::HideAutofillPopup() {
if (popup_controller_.get())
popup_controller_->Hide();
+
+ // Password generation popups behave in the same fashion and should also
+ // be hidden.
+ PasswordGenerationManager* generation_manager =
+ PasswordGenerationManager::FromWebContents(web_contents_);
+ if (generation_manager)
+ generation_manager->HidePopup();
}
bool TabAutofillManagerDelegate::IsAutocompleteEnabled() {
diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi
index 8f99bb2..8235c434 100644
--- a/chrome/chrome_browser_ui.gypi
+++ b/chrome/chrome_browser_ui.gypi
@@ -406,6 +406,7 @@
'browser/ui/autofill/password_generation_popup_controller_impl.h',
'browser/ui/autofill/password_generation_popup_controller.h',
'browser/ui/autofill/password_generation_popup_observer.h',
+ 'browser/ui/autofill/password_generation_popup_view.cc',
'browser/ui/autofill/password_generation_popup_view.h',
'browser/ui/autofill/popup_controller_common.cc',
'browser/ui/autofill/popup_controller_common.h',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 1272abe..39f6e5c 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -187,6 +187,7 @@
'browser/notifications/desktop_notifications_unittest.cc',
'browser/notifications/desktop_notifications_unittest.h',
'browser/notifications/notification_browsertest.cc',
+ 'browser/password_manager/password_generation_interactive_uitest.cc',
'browser/task_manager/task_manager_browsertest_util.cc',
'browser/ui/app_list/app_list_service_interactive_uitest.cc',
'browser/ui/app_list/app_list_service_mac_interactive_uitest.mm',
@@ -953,6 +954,8 @@
'../components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc',
'../components/autofill/content/renderer/test_password_autofill_agent.h',
'../components/autofill/content/renderer/test_password_autofill_agent.cc',
+ '../components/autofill/content/renderer/test_password_generation_agent.h',
+ '../components/autofill/content/renderer/test_password_generation_agent.cc',
'app/chrome_command_ids.h',
'app/chrome_dll.rc',
'app/chrome_dll_resource.h',
@@ -2100,6 +2103,8 @@
'sources': [
'../components/autofill/content/renderer/test_password_autofill_agent.cc',
'../components/autofill/content/renderer/test_password_autofill_agent.h',
+ '../components/autofill/content/renderer/test_password_generation_agent.cc',
+ '../components/autofill/content/renderer/test_password_generation_agent.h',
'app/chrome_command_ids.h',
'app/chrome_dll.rc',
'app/chrome_dll_resource.h',
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index e8268bf..77f8003 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -527,6 +527,8 @@
'../apps/shell_window_geometry_cache_unittest.cc',
'../components/autofill/content/renderer/test_password_autofill_agent.cc',
'../components/autofill/content/renderer/test_password_autofill_agent.h',
+ '../components/autofill/content/renderer/test_password_generation_agent.cc',
+ '../components/autofill/content/renderer/test_password_generation_agent.h',
'../extensions/browser/admin_policy_unittest.cc',
'../extensions/browser/error_map_unittest.cc',
'../extensions/browser/event_listener_map_unittest.cc',
diff --git a/chrome/renderer/autofill/password_generation_agent_browsertest.cc b/chrome/renderer/autofill/password_generation_agent_browsertest.cc
index b39c06e..5e24681 100644
--- a/chrome/renderer/autofill/password_generation_agent_browsertest.cc
+++ b/chrome/renderer/autofill/password_generation_agent_browsertest.cc
@@ -5,11 +5,11 @@
#include <string.h>
#include "base/memory/scoped_ptr.h"
-#include "base/memory/scoped_vector.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/test/base/chrome_render_view_test.h"
#include "components/autofill/content/common/autofill_messages.h"
-#include "components/autofill/content/renderer/password_generation_agent.h"
+#include "components/autofill/content/renderer/autofill_agent.h"
+#include "components/autofill/content/renderer/test_password_generation_agent.h"
#include "components/autofill/core/common/form_data.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebString.h"
@@ -24,79 +24,21 @@ using blink::WebString;
namespace autofill {
-class TestPasswordGenerationAgent : public PasswordGenerationAgent {
- public:
- explicit TestPasswordGenerationAgent(content::RenderView* view)
- : PasswordGenerationAgent(view) {}
- virtual ~TestPasswordGenerationAgent() {}
-
- // Make this public
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
- return PasswordGenerationAgent::OnMessageReceived(message);
- }
-
- const std::vector<IPC::Message*>& messages() {
- return messages_.get();
- }
-
- void ClearMessages() {
- messages_.clear();
- }
-
- protected:
- virtual bool ShouldAnalyzeDocument(const blink::WebDocument& document) const
- OVERRIDE {
- return true;
- }
-
- virtual bool Send(IPC::Message* message) OVERRIDE {
- messages_.push_back(message);
- return true;
- }
-
- private:
- ScopedVector<IPC::Message> messages_;
-
- DISALLOW_COPY_AND_ASSIGN(TestPasswordGenerationAgent);
-};
-
class PasswordGenerationAgentTest : public ChromeRenderViewTest {
public:
PasswordGenerationAgentTest() {}
- virtual void SetUp() {
- // We don't actually create a PasswordGenerationAgent during
- // ChromeRenderViewTest::SetUp because it's behind a flag. Since we want
- // to use a test manager anyway, we just create our own.
- ChromeRenderViewTest::SetUp();
- generation_manager_.reset(new TestPasswordGenerationAgent(view_));
- }
-
virtual void TearDown() {
LoadHTML("");
- generation_manager_.reset();
ChromeRenderViewTest::TearDown();
}
- void SimulateClickOnDecoration(blink::WebInputElement* input_element) {
- generation_manager_->ClearMessages();
- blink::WebElement decoration =
- input_element->decorationElementFor(generation_manager_.get());
- decoration.simulateClick();
- }
-
- bool DecorationIsVisible(blink::WebInputElement* input_element) {
- blink::WebElement decoration =
- input_element->decorationElementFor(generation_manager_.get());
- return decoration.hasNonEmptyBoundingBox();
- }
-
void SetNotBlacklistedMessage(const char* form_str) {
autofill::PasswordForm form;
form.origin =
GURL(base::StringPrintf("data:text/html;charset=utf-8,%s", form_str));
AutofillMsg_FormNotBlacklisted msg(0, form);
- generation_manager_->OnMessageReceived(msg);
+ password_generation_->OnMessageReceived(msg);
}
void SetAccountCreationFormsDetectedMessage(const char* form_str) {
@@ -106,29 +48,29 @@ class PasswordGenerationAgentTest : public ChromeRenderViewTest {
std::vector<autofill::FormData> forms;
forms.push_back(form);
AutofillMsg_AccountCreationFormsDetected msg(0, forms);
- generation_manager_->OnMessageReceived(msg);
+ password_generation_->OnMessageReceived(msg);
}
- void ExpectPasswordGenerationIconShown(const char* element_id, bool shown) {
+ void ExpectPasswordGenerationAvailable(const char* element_id,
+ bool available) {
WebDocument document = GetMainFrame()->document();
WebElement element =
document.getElementById(WebString::fromUTF8(element_id));
ASSERT_FALSE(element.isNull());
WebInputElement target_element = element.to<WebInputElement>();
- if (shown) {
- EXPECT_TRUE(DecorationIsVisible(&target_element));
- SimulateClickOnDecoration(&target_element);
- EXPECT_EQ(1u, generation_manager_->messages().size());
+ ExecuteJavaScript(
+ base::StringPrintf("document.getElementById('%s').focus();",
+ element_id).c_str());
+ if (available) {
+ ASSERT_EQ(1u, password_generation_->messages().size());
EXPECT_EQ(AutofillHostMsg_ShowPasswordGenerationPopup::ID,
- generation_manager_->messages()[0]->type());
+ password_generation_->messages()[0]->type());
} else {
- EXPECT_FALSE(DecorationIsVisible(&target_element));
+ EXPECT_EQ(0u, password_generation_->messages().size());
}
+ password_generation_->clear_messages();
}
- protected:
- scoped_ptr<TestPasswordGenerationAgent> generation_manager_;
-
private:
DISALLOW_COPY_AND_ASSIGN(PasswordGenerationAgentTest);
};
@@ -169,11 +111,11 @@ const char kInvalidActionAccountCreationFormHTML[] =
TEST_F(PasswordGenerationAgentTest, DetectionTest) {
// Don't shown the icon for non account creation forms.
LoadHTML(kSigninFormHTML);
- ExpectPasswordGenerationIconShown("password", false);
+ ExpectPasswordGenerationAvailable("password", false);
// We don't show the decoration yet because the feature isn't enabled.
LoadHTML(kAccountCreationFormHTML);
- ExpectPasswordGenerationIconShown("first_password", false);
+ ExpectPasswordGenerationAvailable("first_password", false);
// Pretend like We have received message indicating site is not blacklisted,
// and we have received message indicating the form is classified as
@@ -181,20 +123,20 @@ TEST_F(PasswordGenerationAgentTest, DetectionTest) {
LoadHTML(kAccountCreationFormHTML);
SetNotBlacklistedMessage(kAccountCreationFormHTML);
SetAccountCreationFormsDetectedMessage(kAccountCreationFormHTML);
- ExpectPasswordGenerationIconShown("first_password", true);
+ ExpectPasswordGenerationAvailable("first_password", true);
// This doesn't trigger because hidden password fields are ignored.
LoadHTML(kHiddenPasswordAccountCreationFormHTML);
SetNotBlacklistedMessage(kHiddenPasswordAccountCreationFormHTML);
SetAccountCreationFormsDetectedMessage(
kHiddenPasswordAccountCreationFormHTML);
- ExpectPasswordGenerationIconShown("first_password", false);
+ ExpectPasswordGenerationAvailable("first_password", false);
// This doesn't trigger because the form action is invalid.
LoadHTML(kInvalidActionAccountCreationFormHTML);
SetNotBlacklistedMessage(kInvalidActionAccountCreationFormHTML);
SetAccountCreationFormsDetectedMessage(kInvalidActionAccountCreationFormHTML);
- ExpectPasswordGenerationIconShown("first_password", false);
+ ExpectPasswordGenerationAvailable("first_password", false);
}
TEST_F(PasswordGenerationAgentTest, FillTest) {
@@ -216,7 +158,7 @@ TEST_F(PasswordGenerationAgentTest, FillTest) {
base::string16 password = base::ASCIIToUTF16("random_password");
AutofillMsg_GeneratedPasswordAccepted msg(0, password);
- generation_manager_->OnMessageReceived(msg);
+ password_generation_->OnMessageReceived(msg);
// Password fields are filled out and set as being autofilled.
EXPECT_EQ(password, first_password_element.value());
@@ -232,26 +174,62 @@ TEST_F(PasswordGenerationAgentTest, FillTest) {
EXPECT_EQ(element, document.focusedNode());
}
+TEST_F(PasswordGenerationAgentTest, EditingTest) {
+ LoadHTML(kAccountCreationFormHTML);
+ SetNotBlacklistedMessage(kAccountCreationFormHTML);
+ SetAccountCreationFormsDetectedMessage(kAccountCreationFormHTML);
+
+ WebDocument document = GetMainFrame()->document();
+ WebElement element =
+ document.getElementById(WebString::fromUTF8("first_password"));
+ ASSERT_FALSE(element.isNull());
+ WebInputElement first_password_element = element.to<WebInputElement>();
+ element = document.getElementById(WebString::fromUTF8("second_password"));
+ ASSERT_FALSE(element.isNull());
+ WebInputElement second_password_element = element.to<WebInputElement>();
+
+ base::string16 password = base::ASCIIToUTF16("random_password");
+ AutofillMsg_GeneratedPasswordAccepted msg(0, password);
+ password_generation_->OnMessageReceived(msg);
+
+ // Passwords start out the same.
+ EXPECT_EQ(password, first_password_element.value());
+ EXPECT_EQ(password, second_password_element.value());
+
+ // After editing the first field they are still the same.
+ base::string16 edited_password = base::ASCIIToUTF16("edited_password");
+ first_password_element.setValue(edited_password);
+ // Cast to WebAutofillClient where textFieldDidChange() is public.
+ static_cast<blink::WebAutofillClient*>(autofill_agent_)->textFieldDidChange(
+ first_password_element);
+ // textFieldDidChange posts a task, so we need to wait until it's been
+ // processed.
+ base::MessageLoop::current()->RunUntilIdle();
+
+ EXPECT_EQ(edited_password, first_password_element.value());
+ EXPECT_EQ(edited_password, second_password_element.value());
+}
+
TEST_F(PasswordGenerationAgentTest, BlacklistedTest) {
// Did not receive not blacklisted message. Don't show password generation
// icon.
LoadHTML(kAccountCreationFormHTML);
SetAccountCreationFormsDetectedMessage(kAccountCreationFormHTML);
- ExpectPasswordGenerationIconShown("first_password", false);
+ ExpectPasswordGenerationAvailable("first_password", false);
// Receive one not blacklisted message for non account creation form. Don't
// show password generation icon.
LoadHTML(kAccountCreationFormHTML);
SetNotBlacklistedMessage(kSigninFormHTML);
SetAccountCreationFormsDetectedMessage(kAccountCreationFormHTML);
- ExpectPasswordGenerationIconShown("first_password", false);
+ ExpectPasswordGenerationAvailable("first_password", false);
// Receive one not blackliste message for account creation form. Show password
// generation icon.
LoadHTML(kAccountCreationFormHTML);
SetNotBlacklistedMessage(kAccountCreationFormHTML);
SetAccountCreationFormsDetectedMessage(kAccountCreationFormHTML);
- ExpectPasswordGenerationIconShown("first_password", true);
+ ExpectPasswordGenerationAvailable("first_password", true);
// Receive two not blacklisted messages, one is for account creation form and
// the other is not. Show password generation icon.
@@ -259,7 +237,7 @@ TEST_F(PasswordGenerationAgentTest, BlacklistedTest) {
SetNotBlacklistedMessage(kAccountCreationFormHTML);
SetNotBlacklistedMessage(kSigninFormHTML);
SetAccountCreationFormsDetectedMessage(kAccountCreationFormHTML);
- ExpectPasswordGenerationIconShown("first_password", true);
+ ExpectPasswordGenerationAvailable("first_password", true);
}
TEST_F(PasswordGenerationAgentTest, AccountCreationFormsDetectedTest) {
@@ -267,14 +245,14 @@ TEST_F(PasswordGenerationAgentTest, AccountCreationFormsDetectedTest) {
// password generation icon.
LoadHTML(kAccountCreationFormHTML);
SetNotBlacklistedMessage(kAccountCreationFormHTML);
- ExpectPasswordGenerationIconShown("first_password", false);
+ ExpectPasswordGenerationAvailable("first_password", false);
// Receive the account creation forms detected message. Show password
// generation icon.
LoadHTML(kAccountCreationFormHTML);
SetNotBlacklistedMessage(kAccountCreationFormHTML);
SetAccountCreationFormsDetectedMessage(kAccountCreationFormHTML);
- ExpectPasswordGenerationIconShown("first_password", true);
+ ExpectPasswordGenerationAvailable("first_password", true);
}
} // namespace autofill
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index 9ea0b8f..870b7a3 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -68,7 +68,6 @@
#include "components/autofill/content/renderer/autofill_agent.h"
#include "components/autofill/content/renderer/password_autofill_agent.h"
#include "components/autofill/content/renderer/password_generation_agent.h"
-#include "components/autofill/core/common/password_generation_util.h"
#include "components/nacl/renderer/ppb_nacl_private_impl.h"
#include "components/plugins/renderer/mobile_youtube_plugin.h"
#include "components/visitedlink/renderer/visitedlink_slave.h"
@@ -406,13 +405,15 @@ void ChromeContentRendererClient::RenderViewCreated(
safe_browsing::MalwareDOMDetails::Create(render_view);
#endif
+ PasswordGenerationAgent* password_generation_agent =
+ new PasswordGenerationAgent(render_view);
PasswordAutofillAgent* password_autofill_agent =
new PasswordAutofillAgent(render_view);
- new AutofillAgent(render_view, password_autofill_agent);
+ new AutofillAgent(render_view,
+ password_autofill_agent,
+ password_generation_agent);
CommandLine* command_line = CommandLine::ForCurrentProcess();
- if (autofill::password_generation::IsPasswordGenerationEnabled())
- new PasswordGenerationAgent(render_view);
if (command_line->HasSwitch(switches::kInstantProcess))
new SearchBox(render_view);
diff --git a/chrome/test/base/chrome_render_view_test.cc b/chrome/test/base/chrome_render_view_test.cc
index 47e06f9..e92236f 100644
--- a/chrome/test/base/chrome_render_view_test.cc
+++ b/chrome/test/base/chrome_render_view_test.cc
@@ -14,6 +14,7 @@
#include "components/autofill/content/renderer/autofill_agent.h"
#include "components/autofill/content/renderer/password_autofill_agent.h"
#include "components/autofill/content/renderer/test_password_autofill_agent.h"
+#include "components/autofill/content/renderer/test_password_generation_agent.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/common/renderer_preferences.h"
#include "content/public/renderer/render_view.h"
@@ -40,6 +41,7 @@ using blink::WebString;
using blink::WebURLRequest;
using autofill::AutofillAgent;
using autofill::PasswordAutofillAgent;
+using autofill::PasswordGenerationAgent;
ChromeRenderViewTest::ChromeRenderViewTest() : extension_dispatcher_(NULL) {
}
@@ -60,11 +62,13 @@ void ChromeRenderViewTest::SetUp() {
content::RenderViewTest::SetUp();
- // RenderView doesn't expose its PasswordAutofillAgent or AutofillAgent
- // objects, because it has no need to store them directly (they're stored as
- // RenderViewObserver*). So just create another set.
+ // RenderView doesn't expose its Agent objects, because it has no need to
+ // store them directly (they're stored as RenderViewObserver*). So just
+ // create another set.
password_autofill_ = new autofill::TestPasswordAutofillAgent(view_);
- autofill_agent_ = new AutofillAgent(view_, password_autofill_);
+ password_generation_ = new autofill::TestPasswordGenerationAgent(view_);
+ autofill_agent_ =
+ new AutofillAgent(view_, password_autofill_, password_generation_);
}
void ChromeRenderViewTest::TearDown() {
diff --git a/chrome/test/base/chrome_render_view_test.h b/chrome/test/base/chrome_render_view_test.h
index 7e1e6c3..aff4c5d 100644
--- a/chrome/test/base/chrome_render_view_test.h
+++ b/chrome/test/base/chrome_render_view_test.h
@@ -14,6 +14,7 @@
namespace autofill {
class AutofillAgent;
class TestPasswordAutofillAgent;
+class TestPasswordGenerationAgent;
}
namespace extensions {
@@ -34,6 +35,7 @@ class ChromeRenderViewTest : public content::RenderViewTest {
extensions::Dispatcher* extension_dispatcher_;
autofill::TestPasswordAutofillAgent* password_autofill_;
+ autofill::TestPasswordGenerationAgent* password_generation_;
autofill::AutofillAgent* autofill_agent_;
// Naked pointer as ownership is with content::RenderViewTest::render_thread_.