Home | History | Annotate | Download | only in password_manager
      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