diff options
Diffstat (limited to 'chrome')
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_. |