1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/command_line.h" 6 #include "chrome/browser/password_manager/chrome_password_manager_client.h" 7 #include "chrome/browser/profiles/profile.h" 8 #include "chrome/browser/ui/autofill/password_generation_popup_observer.h" 9 #include "chrome/browser/ui/browser.h" 10 #include "chrome/browser/ui/tabs/tab_strip_model.h" 11 #include "chrome/test/base/in_process_browser_test.h" 12 #include "chrome/test/base/ui_test_utils.h" 13 #include "components/autofill/core/browser/autofill_test_utils.h" 14 #include "components/autofill/core/common/autofill_switches.h" 15 #include "components/password_manager/core/browser/password_generation_manager.h" 16 #include "content/public/browser/render_view_host.h" 17 #include "content/public/browser/web_contents.h" 18 #include "content/public/test/browser_test_utils.h" 19 #include "net/test/embedded_test_server/embedded_test_server.h" 20 #include "testing/gtest/include/gtest/gtest.h" 21 #include "ui/events/keycodes/keyboard_codes.h" 22 23 namespace { 24 25 class TestPopupObserver : public autofill::PasswordGenerationPopupObserver { 26 public: 27 TestPopupObserver() 28 : popup_showing_(false), 29 password_visible_(false) {} 30 virtual ~TestPopupObserver() {} 31 32 virtual void OnPopupShown(bool password_visible) OVERRIDE { 33 popup_showing_ = true; 34 password_visible_ = password_visible; 35 } 36 37 virtual void OnPopupHidden() OVERRIDE { 38 popup_showing_ = false; 39 } 40 41 bool popup_showing() { return popup_showing_; } 42 bool password_visible() { return password_visible_; } 43 44 private: 45 bool popup_showing_; 46 bool password_visible_; 47 }; 48 49 } // namespace 50 51 class PasswordGenerationInteractiveTest : public InProcessBrowserTest { 52 public: 53 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 54 // Make sure the feature is enabled. 55 command_line->AppendSwitch(autofill::switches::kEnablePasswordGeneration); 56 57 // Don't require ping from autofill or blacklist checking. 58 command_line->AppendSwitch( 59 autofill::switches::kLocalHeuristicsOnlyForPasswordGeneration); 60 } 61 62 virtual void SetUpOnMainThread() OVERRIDE { 63 // Disable Autofill requesting access to AddressBook data. This will cause 64 // the tests to hang on Mac. 65 autofill::test::DisableSystemServices(browser()->profile()->GetPrefs()); 66 67 // Set observer for popup. 68 ChromePasswordManagerClient* client = 69 ChromePasswordManagerClient::FromWebContents(GetWebContents()); 70 client->SetTestObserver(&observer_); 71 72 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 73 GURL url = embedded_test_server()->GetURL("/password/signup_form.html"); 74 ui_test_utils::NavigateToURL(browser(), url); 75 } 76 77 virtual void TearDownOnMainThread() OVERRIDE { 78 // Clean up UI. 79 ChromePasswordManagerClient* client = 80 ChromePasswordManagerClient::FromWebContents(GetWebContents()); 81 client->HidePasswordGenerationPopup(); 82 } 83 84 content::WebContents* GetWebContents() { 85 return browser()->tab_strip_model()->GetActiveWebContents(); 86 } 87 88 content::RenderViewHost* GetRenderViewHost() { 89 return GetWebContents()->GetRenderViewHost(); 90 } 91 92 std::string GetFieldValue(const std::string& field_id) { 93 std::string value; 94 EXPECT_TRUE(content::ExecuteScriptAndExtractString( 95 GetRenderViewHost(), 96 "window.domAutomationController.send(" 97 " document.getElementById('" + field_id + "').value);", 98 &value)); 99 return value; 100 } 101 102 std::string GetFocusedElement() { 103 std::string focused_element; 104 EXPECT_TRUE(content::ExecuteScriptAndExtractString( 105 GetRenderViewHost(), 106 "window.domAutomationController.send(" 107 " document.activeElement.id)", 108 &focused_element)); 109 return focused_element; 110 } 111 112 void FocusPasswordField() { 113 ASSERT_TRUE(content::ExecuteScript( 114 GetRenderViewHost(), 115 "document.getElementById('password_field').focus()")); 116 } 117 118 void SendKeyToPopup(ui::KeyboardCode key) { 119 content::NativeWebKeyboardEvent event; 120 event.windowsKeyCode = key; 121 event.type = blink::WebKeyboardEvent::RawKeyDown; 122 GetRenderViewHost()->ForwardKeyboardEvent(event); 123 } 124 125 bool GenerationPopupShowing() { 126 return observer_.popup_showing() && observer_.password_visible(); 127 } 128 129 bool EditingPopupShowing() { 130 return observer_.popup_showing() && !observer_.password_visible(); 131 } 132 133 private: 134 TestPopupObserver observer_; 135 }; 136 137 #if defined(USE_AURA) 138 // Enabled on these platforms. 139 // Disabled due to flakiness, see http://crbug.com/407998 140 #define MAYBE_PopupShownAndPasswordSelected \ 141 DISABLED_PopupShownAndPasswordSelected 142 #define MAYBE_PopupShownAndDismissed DISABLED_PopupShownAndDismissed 143 #define MAYBE_PopupShownAndDismissedByScrolling \ 144 DISABLED_PopupShownAndDismissedByScrolling 145 #else 146 // Popup not enabled for these platforms yet. 147 #define MAYBE_PopupShownAndPasswordSelected \ 148 DISABLED_PopupShownAndPasswordSelected 149 #define MAYBE_PopupShownAndDismissed DISABLED_PopupShownAndDismissed 150 #define MAYBE_PopupShownAndDismissedByScrolling \ 151 DISABLED_PopupShownAndDismissedByScrolling 152 #endif 153 154 IN_PROC_BROWSER_TEST_F(PasswordGenerationInteractiveTest, 155 MAYBE_PopupShownAndPasswordSelected) { 156 FocusPasswordField(); 157 EXPECT_TRUE(GenerationPopupShowing()); 158 SendKeyToPopup(ui::VKEY_DOWN); 159 SendKeyToPopup(ui::VKEY_RETURN); 160 161 // Selecting the password should fill the field and move focus to the 162 // submit button. 163 EXPECT_FALSE(GetFieldValue("password_field").empty()); 164 EXPECT_FALSE(GenerationPopupShowing()); 165 EXPECT_FALSE(EditingPopupShowing()); 166 EXPECT_EQ("input_submit_button", GetFocusedElement()); 167 168 // Re-focusing the password field should show the editing popup. 169 FocusPasswordField(); 170 EXPECT_TRUE(EditingPopupShowing()); 171 } 172 173 IN_PROC_BROWSER_TEST_F(PasswordGenerationInteractiveTest, 174 MAYBE_PopupShownAndDismissed) { 175 FocusPasswordField(); 176 EXPECT_TRUE(GenerationPopupShowing()); 177 178 SendKeyToPopup(ui::VKEY_ESCAPE); 179 180 // Popup is dismissed. 181 EXPECT_FALSE(GenerationPopupShowing()); 182 } 183 184 IN_PROC_BROWSER_TEST_F(PasswordGenerationInteractiveTest, 185 MAYBE_PopupShownAndDismissedByScrolling) { 186 FocusPasswordField(); 187 EXPECT_TRUE(GenerationPopupShowing()); 188 189 ASSERT_TRUE(content::ExecuteScript(GetRenderViewHost(), 190 "window.scrollTo(100, 0);")); 191 192 EXPECT_FALSE(GenerationPopupShowing()); 193 } 194