OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <string> | 5 #include <string> |
6 | 6 |
7 #include "chrome/browser/chrome_notification_types.h" | 7 #include "chrome/browser/chrome_notification_types.h" |
8 #include "chrome/browser/infobars/confirm_infobar_delegate.h" | 8 #include "chrome/browser/infobars/confirm_infobar_delegate.h" |
9 #include "chrome/browser/infobars/infobar_service.h" | 9 #include "chrome/browser/infobars/infobar_service.h" |
10 #include "chrome/browser/password_manager/password_store_factory.h" | 10 #include "chrome/browser/password_manager/password_store_factory.h" |
11 #include "chrome/browser/password_manager/test_password_store.h" | 11 #include "chrome/browser/password_manager/test_password_store.h" |
12 #include "chrome/browser/ui/browser.h" | 12 #include "chrome/browser/ui/browser.h" |
13 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 13 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
14 #include "chrome/test/base/in_process_browser_test.h" | 14 #include "chrome/test/base/in_process_browser_test.h" |
15 #include "chrome/test/base/ui_test_utils.h" | 15 #include "chrome/test/base/ui_test_utils.h" |
16 #include "content/public/browser/notification_observer.h" | 16 #include "content/public/browser/notification_observer.h" |
17 #include "content/public/browser/notification_registrar.h" | 17 #include "content/public/browser/notification_registrar.h" |
18 #include "content/public/browser/notification_service.h" | 18 #include "content/public/browser/notification_service.h" |
19 #include "content/public/browser/render_view_host.h" | 19 #include "content/public/browser/render_view_host.h" |
20 #include "content/public/browser/web_contents.h" | 20 #include "content/public/browser/web_contents.h" |
21 #include "content/public/browser/web_contents_observer.h" | 21 #include "content/public/browser/web_contents_observer.h" |
22 #include "content/public/test/browser_test_utils.h" | 22 #include "content/public/test/browser_test_utils.h" |
23 #include "content/public/test/test_utils.h" | 23 #include "content/public/test/test_utils.h" |
24 #include "testing/gmock/include/gmock/gmock.h" | 24 #include "testing/gmock/include/gmock/gmock.h" |
25 #include "ui/base/keycodes/keyboard_codes.h" | 25 #include "ui/base/keycodes/keyboard_codes.h" |
26 | 26 |
| 27 |
| 28 // NavigationObserver --------------------------------------------------------- |
| 29 |
27 namespace { | 30 namespace { |
28 | 31 |
29 class NavigationObserver : public content::NotificationObserver, | 32 class NavigationObserver : public content::NotificationObserver, |
30 public content::WebContentsObserver { | 33 public content::WebContentsObserver { |
31 public: | 34 public: |
32 explicit NavigationObserver(content::WebContents* web_contents) | 35 explicit NavigationObserver(content::WebContents* web_contents); |
33 : content::WebContentsObserver(web_contents), | 36 virtual ~NavigationObserver(); |
34 message_loop_runner_(new content::MessageLoopRunner), | |
35 info_bar_shown_(false), | |
36 infobar_service_(InfoBarService::FromWebContents(web_contents)) { | |
37 registrar_.Add(this, | |
38 chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED, | |
39 content::Source<InfoBarService>(infobar_service_)); | |
40 } | |
41 | |
42 virtual ~NavigationObserver() {} | |
43 | |
44 void Wait() { | |
45 message_loop_runner_->Run(); | |
46 } | |
47 | |
48 bool InfoBarWasShown() { | |
49 return info_bar_shown_; | |
50 } | |
51 | 37 |
52 // content::NotificationObserver: | 38 // content::NotificationObserver: |
53 virtual void Observe(int type, | 39 virtual void Observe(int type, |
54 const content::NotificationSource& source, | 40 const content::NotificationSource& source, |
55 const content::NotificationDetails& details) OVERRIDE { | 41 const content::NotificationDetails& details) OVERRIDE; |
56 // Accept in the infobar. | |
57 InfoBarDelegate* infobar = infobar_service_->infobar_at(0); | |
58 ConfirmInfoBarDelegate* confirm_infobar = | |
59 infobar->AsConfirmInfoBarDelegate(); | |
60 confirm_infobar->Accept(); | |
61 info_bar_shown_ = true; | |
62 } | |
63 | 42 |
64 // content::WebContentsObserver | 43 // content::WebContentsObserver |
65 virtual void DidFinishLoad( | 44 virtual void DidFinishLoad( |
66 int64 frame_id, | 45 int64 frame_id, |
67 const GURL& validated_url, | 46 const GURL& validated_url, |
68 bool is_main_frame, | 47 bool is_main_frame, |
69 content::RenderViewHost* render_view_host) OVERRIDE { | 48 content::RenderViewHost* render_view_host) OVERRIDE; |
70 message_loop_runner_->Quit(); | 49 |
71 } | 50 bool infobar_shown() { return info_bar_shown_; } |
| 51 |
| 52 void Wait(); |
72 | 53 |
73 private: | 54 private: |
74 scoped_refptr<content::MessageLoopRunner> message_loop_runner_; | 55 scoped_refptr<content::MessageLoopRunner> message_loop_runner_; |
75 bool info_bar_shown_; | 56 bool info_bar_shown_; |
76 content::NotificationRegistrar registrar_; | 57 content::NotificationRegistrar registrar_; |
77 InfoBarService* infobar_service_; | 58 InfoBarService* infobar_service_; |
78 }; | 59 }; |
79 | 60 |
| 61 NavigationObserver::NavigationObserver(content::WebContents* web_contents) |
| 62 : content::WebContentsObserver(web_contents), |
| 63 message_loop_runner_(new content::MessageLoopRunner), |
| 64 info_bar_shown_(false), |
| 65 infobar_service_(InfoBarService::FromWebContents(web_contents)) { |
| 66 registrar_.Add(this, |
| 67 chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED, |
| 68 content::Source<InfoBarService>(infobar_service_)); |
| 69 } |
| 70 |
| 71 NavigationObserver::~NavigationObserver() { |
| 72 } |
| 73 |
| 74 void NavigationObserver::Observe(int type, |
| 75 const content::NotificationSource& source, |
| 76 const content::NotificationDetails& details) { |
| 77 // Accept in the infobar. |
| 78 InfoBarDelegate* infobar = infobar_service_->infobar_at(0); |
| 79 ConfirmInfoBarDelegate* confirm_infobar = |
| 80 infobar->AsConfirmInfoBarDelegate(); |
| 81 confirm_infobar->Accept(); |
| 82 info_bar_shown_ = true; |
| 83 } |
| 84 |
| 85 void NavigationObserver::DidFinishLoad( |
| 86 int64 frame_id, |
| 87 const GURL& validated_url, |
| 88 bool is_main_frame, |
| 89 content::RenderViewHost* render_view_host) { |
| 90 message_loop_runner_->Quit(); |
| 91 } |
| 92 |
| 93 void NavigationObserver::Wait() { |
| 94 message_loop_runner_->Run(); |
| 95 } |
| 96 |
80 } // namespace | 97 } // namespace |
81 | 98 |
| 99 |
| 100 // PasswordManagerBrowserTest ------------------------------------------------- |
| 101 |
82 class PasswordManagerBrowserTest : public InProcessBrowserTest { | 102 class PasswordManagerBrowserTest : public InProcessBrowserTest { |
83 public: | 103 public: |
84 virtual void SetUpOnMainThread() OVERRIDE { | 104 virtual void SetUpOnMainThread() OVERRIDE; |
85 // Use TestPasswordStore to remove a possible race. Normally the | |
86 // PasswordStore does it's database manipulation on the DB thread, which | |
87 // creates a possible race during navigation. Specifically the | |
88 // PasswordManager will ignore any forms in a page if the load from the | |
89 // PasswordStore has not completed. | |
90 PasswordStoreFactory::GetInstance()->SetTestingFactory( | |
91 browser()->profile(), &TestPasswordStore::Create); | |
92 } | |
93 | 105 |
94 protected: | 106 protected: |
95 content::WebContents* WebContents() { | 107 content::WebContents* WebContents(); |
96 return browser()->tab_strip_model()->GetActiveWebContents(); | 108 content::RenderViewHost* RenderViewHost(); |
97 } | 109 }; |
98 | 110 |
99 content::RenderViewHost* RenderViewHost() { | 111 void PasswordManagerBrowserTest::SetUpOnMainThread() { |
100 return WebContents()->GetRenderViewHost(); | 112 // Use TestPasswordStore to remove a possible race. Normally the PasswordStore |
101 } | 113 // does its database manipulation on the DB thread, which creates a possible |
102 }; | 114 // race during navigation. Specifically the PasswordManager will ignore any |
| 115 // forms in a page if the load from the PasswordStore has not completed. |
| 116 PasswordStoreFactory::GetInstance()->SetTestingFactory( |
| 117 browser()->profile(), &TestPasswordStore::Create); |
| 118 } |
| 119 |
| 120 content::WebContents* PasswordManagerBrowserTest::WebContents() { |
| 121 return browser()->tab_strip_model()->GetActiveWebContents(); |
| 122 } |
| 123 |
| 124 content::RenderViewHost* PasswordManagerBrowserTest::RenderViewHost() { |
| 125 return WebContents()->GetRenderViewHost(); |
| 126 } |
| 127 |
| 128 |
| 129 // Actual tests --------------------------------------------------------------- |
103 | 130 |
104 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, PromptForXHRSubmit) { | 131 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, PromptForXHRSubmit) { |
105 ASSERT_TRUE(test_server()->Start()); | 132 ASSERT_TRUE(test_server()->Start()); |
106 | 133 |
107 GURL url = test_server()->GetURL("files/password/password_xhr_submit.html"); | 134 GURL url = test_server()->GetURL("files/password/password_xhr_submit.html"); |
108 ui_test_utils::NavigateToURL(browser(), url); | 135 ui_test_utils::NavigateToURL(browser(), url); |
109 | 136 |
110 // Verify that we show the save password prompt if a form returns false | 137 // Verify that we show the save password prompt if a form returns false |
111 // in its onsubmit handler but instead logs in/navigates via XHR. | 138 // in its onsubmit handler but instead logs in/navigates via XHR. |
112 // Note that calling 'submit()' on a form with javascript doesn't call | 139 // Note that calling 'submit()' on a form with javascript doesn't call |
113 // the onsubmit handler, so we click the submit button instead. | 140 // the onsubmit handler, so we click the submit button instead. |
114 NavigationObserver observer(WebContents()); | 141 NavigationObserver observer(WebContents()); |
115 std::string fill_and_submit = | 142 std::string fill_and_submit = |
116 "document.getElementById('username_field').value = 'temp';" | 143 "document.getElementById('username_field').value = 'temp';" |
117 "document.getElementById('password_field').value = 'random';" | 144 "document.getElementById('password_field').value = 'random';" |
118 "document.getElementById('submit_button').click()"; | 145 "document.getElementById('submit_button').click()"; |
119 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit)); | 146 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit)); |
120 observer.Wait(); | 147 observer.Wait(); |
121 EXPECT_TRUE(observer.InfoBarWasShown()); | 148 EXPECT_TRUE(observer.infobar_shown()); |
122 } | 149 } |
123 | 150 |
124 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, NoPromptForOtherXHR) { | 151 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, NoPromptForOtherXHR) { |
125 ASSERT_TRUE(test_server()->Start()); | 152 ASSERT_TRUE(test_server()->Start()); |
126 | 153 |
127 GURL url = test_server()->GetURL("files/password/password_xhr_submit.html"); | 154 GURL url = test_server()->GetURL("files/password/password_xhr_submit.html"); |
128 ui_test_utils::NavigateToURL(browser(), url); | 155 ui_test_utils::NavigateToURL(browser(), url); |
129 | 156 |
130 // Verify that if random XHR navigation occurs, we don't try and save the | 157 // Verify that if random XHR navigation occurs, we don't try and save the |
131 // password. | 158 // password. |
132 // | 159 // |
133 // We may want to change this functionality in the future to account for | 160 // We may want to change this functionality in the future to account for |
134 // cases where the element that users click on isn't a submit button. | 161 // cases where the element that users click on isn't a submit button. |
135 NavigationObserver observer(WebContents()); | 162 NavigationObserver observer(WebContents()); |
136 std::string fill_and_navigate = | 163 std::string fill_and_navigate = |
137 "document.getElementById('username_field').value = 'temp';" | 164 "document.getElementById('username_field').value = 'temp';" |
138 "document.getElementById('password_field').value = 'random';" | 165 "document.getElementById('password_field').value = 'random';" |
139 "send_xhr()"; | 166 "send_xhr()"; |
140 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_navigate)); | 167 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_navigate)); |
141 observer.Wait(); | 168 observer.Wait(); |
142 EXPECT_FALSE(observer.InfoBarWasShown()); | 169 EXPECT_FALSE(observer.infobar_shown()); |
143 } | 170 } |
OLD | NEW |