Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / password_manager / password_manager_browsertest.cc
blob0d0f9c39161cd7fc7ef841240ae7e48be1a7fbcb
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
3 // found in the LICENSE file.
5 #include <string>
7 #include "base/command_line.h"
8 #include "base/metrics/histogram_samples.h"
9 #include "base/metrics/statistics_recorder.h"
10 #include "base/path_service.h"
11 #include "base/run_loop.h"
12 #include "base/stl_util.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "chrome/browser/chrome_notification_types.h"
16 #include "chrome/browser/password_manager/chrome_password_manager_client.h"
17 #include "chrome/browser/password_manager/password_manager_test_base.h"
18 #include "chrome/browser/password_manager/password_store_factory.h"
19 #include "chrome/browser/password_manager/test_password_store_service.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/ui/browser.h"
22 #include "chrome/browser/ui/login/login_prompt.h"
23 #include "chrome/browser/ui/login/login_prompt_test_utils.h"
24 #include "chrome/browser/ui/tabs/tab_strip_model.h"
25 #include "chrome/common/chrome_paths.h"
26 #include "chrome/common/chrome_switches.h"
27 #include "chrome/common/chrome_version_info.h"
28 #include "chrome/test/base/test_switches.h"
29 #include "chrome/test/base/ui_test_utils.h"
30 #include "components/autofill/content/common/autofill_messages.h"
31 #include "components/autofill/core/browser/autofill_test_utils.h"
32 #include "components/autofill/core/browser/test_autofill_client.h"
33 #include "components/autofill/core/common/password_form.h"
34 #include "components/password_manager/content/browser/content_password_manager_driver.h"
35 #include "components/password_manager/content/browser/content_password_manager_driver_factory.h"
36 #include "components/password_manager/core/browser/test_password_store.h"
37 #include "components/password_manager/core/common/password_manager_switches.h"
38 #include "content/public/browser/navigation_controller.h"
39 #include "content/public/browser/notification_service.h"
40 #include "content/public/browser/render_frame_host.h"
41 #include "content/public/browser/render_process_host.h"
42 #include "content/public/browser/render_view_host.h"
43 #include "content/public/browser/web_contents.h"
44 #include "content/public/browser/web_contents_observer.h"
45 #include "content/public/common/content_switches.h"
46 #include "content/public/test/browser_test_utils.h"
47 #include "content/public/test/test_utils.h"
48 #include "ipc/ipc_security_test_util.h"
49 #include "net/base/filename_util.h"
50 #include "net/dns/mock_host_resolver.h"
51 #include "net/test/embedded_test_server/embedded_test_server.h"
52 #include "net/test/embedded_test_server/http_request.h"
53 #include "net/test/embedded_test_server/http_response.h"
54 #include "net/test/spawned_test_server/spawned_test_server.h"
55 #include "net/url_request/test_url_fetcher_factory.h"
56 #include "testing/gmock/include/gmock/gmock.h"
57 #include "third_party/WebKit/public/web/WebInputEvent.h"
58 #include "ui/events/keycodes/keyboard_codes.h"
59 #include "ui/gfx/geometry/point.h"
61 namespace {
63 GURL GetFileURL(const char* filename) {
64 base::FilePath path;
65 PathService::Get(chrome::DIR_TEST_DATA, &path);
66 path = path.AppendASCII("password").AppendASCII(filename);
67 CHECK(base::PathExists(path));
68 return net::FilePathToFileURL(path);
71 // Handles |request| to "/basic_auth". If "Authorization" header is present,
72 // responds with a non-empty HTTP 200 page (regardless of its value). Otherwise
73 // serves a Basic Auth challenge.
74 scoped_ptr<net::test_server::HttpResponse> HandleTestAuthRequest(
75 const net::test_server::HttpRequest& request) {
76 if (!base::StartsWith(request.relative_url, "/basic_auth",
77 base::CompareCase::SENSITIVE))
78 return scoped_ptr<net::test_server::HttpResponse>();
80 if (ContainsKey(request.headers, "Authorization")) {
81 scoped_ptr<net::test_server::BasicHttpResponse> http_response(
82 new net::test_server::BasicHttpResponse);
83 http_response->set_code(net::HTTP_OK);
84 http_response->set_content("Success!");
85 return http_response.Pass();
86 } else {
87 scoped_ptr<net::test_server::BasicHttpResponse> http_response(
88 new net::test_server::BasicHttpResponse);
89 http_response->set_code(net::HTTP_UNAUTHORIZED);
90 http_response->AddCustomHeader("WWW-Authenticate",
91 "Basic realm=\"test realm\"");
92 return http_response.Pass();
96 class ObservingAutofillClient : public autofill::TestAutofillClient {
97 public:
98 ObservingAutofillClient()
99 : message_loop_runner_(new content::MessageLoopRunner) {}
100 ~ObservingAutofillClient() override {}
102 void Wait() { message_loop_runner_->Run(); }
104 void ShowAutofillPopup(
105 const gfx::RectF& element_bounds,
106 base::i18n::TextDirection text_direction,
107 const std::vector<autofill::Suggestion>& suggestions,
108 base::WeakPtr<autofill::AutofillPopupDelegate> delegate) override {
109 message_loop_runner_->Quit();
112 private:
113 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
115 DISALLOW_COPY_AND_ASSIGN(ObservingAutofillClient);
118 } // namespace
120 namespace password_manager {
122 // Actual tests ---------------------------------------------------------------
123 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase, PromptForNormalSubmit) {
124 NavigateToFile("/password/password_form.html");
126 // Fill a form and submit through a <input type="submit"> button. Nothing
127 // special.
128 NavigationObserver observer(WebContents());
129 scoped_ptr<PromptObserver> prompt_observer(
130 PromptObserver::Create(WebContents()));
131 std::string fill_and_submit =
132 "document.getElementById('username_field').value = 'temp';"
133 "document.getElementById('password_field').value = 'random';"
134 "document.getElementById('input_submit_button').click()";
135 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
136 observer.Wait();
137 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
140 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
141 PromptForSubmitWithInPageNavigation) {
142 NavigateToFile("/password/password_navigate_before_submit.html");
144 // Fill a form and submit through a <input type="submit"> button. Nothing
145 // special. The form does an in-page navigation before submitting.
146 NavigationObserver observer(WebContents());
147 scoped_ptr<PromptObserver> prompt_observer(
148 PromptObserver::Create(WebContents()));
149 std::string fill_and_submit =
150 "document.getElementById('username_field').value = 'temp';"
151 "document.getElementById('password_field').value = 'random';"
152 "document.getElementById('input_submit_button').click()";
153 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
154 observer.Wait();
155 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
158 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
159 LoginSuccessWithUnrelatedForm) {
160 // Log in, see a form on the landing page. That form is not related to the
161 // login form (=has a different action), so we should offer saving the
162 // password.
163 NavigateToFile("/password/password_form.html");
165 NavigationObserver observer(WebContents());
166 scoped_ptr<PromptObserver> prompt_observer(
167 PromptObserver::Create(WebContents()));
168 std::string fill_and_submit =
169 "document.getElementById('username_unrelated').value = 'temp';"
170 "document.getElementById('password_unrelated').value = 'random';"
171 "document.getElementById('submit_unrelated').click()";
172 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
173 observer.Wait();
174 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
177 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase, LoginFailed) {
178 // Log in, see a form on the landing page. That form is not related to the
179 // login form (=has a different action), so we should offer saving the
180 // password.
181 NavigateToFile("/password/password_form.html");
183 NavigationObserver observer(WebContents());
184 scoped_ptr<PromptObserver> prompt_observer(
185 PromptObserver::Create(WebContents()));
186 std::string fill_and_submit =
187 "document.getElementById('username_failed').value = 'temp';"
188 "document.getElementById('password_failed').value = 'random';"
189 "document.getElementById('submit_failed').click()";
190 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
191 observer.Wait();
192 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
195 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase, Redirects) {
196 NavigateToFile("/password/password_form.html");
198 // Fill a form and submit through a <input type="submit"> button. The form
199 // points to a redirection page.
200 NavigationObserver observer(WebContents());
201 scoped_ptr<PromptObserver> prompt_observer(
202 PromptObserver::Create(WebContents()));
203 std::string fill_and_submit =
204 "document.getElementById('username_redirect').value = 'temp';"
205 "document.getElementById('password_redirect').value = 'random';"
206 "document.getElementById('submit_redirect').click()";
207 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
208 observer.Wait();
209 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
211 // The redirection page now redirects via Javascript. We check that the
212 // infobar stays.
213 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(),
214 "window.location.href = 'done.html';"));
215 observer.Wait();
216 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
219 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
220 PromptForSubmitUsingJavaScript) {
221 NavigateToFile("/password/password_form.html");
223 // Fill a form and submit using <button> that calls submit() on the form.
224 // This should work regardless of the type of element, as long as submit() is
225 // called.
226 NavigationObserver observer(WebContents());
227 scoped_ptr<PromptObserver> prompt_observer(
228 PromptObserver::Create(WebContents()));
229 std::string fill_and_submit =
230 "document.getElementById('username_field').value = 'temp';"
231 "document.getElementById('password_field').value = 'random';"
232 "document.getElementById('submit_button').click()";
233 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
234 observer.Wait();
235 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
238 // Flaky: crbug.com/301547, observed on win and mac. Probably happens on all
239 // platforms.
240 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
241 DISABLED_PromptForDynamicForm) {
242 NavigateToFile("/password/dynamic_password_form.html");
244 // Fill the dynamic password form and submit.
245 NavigationObserver observer(WebContents());
246 scoped_ptr<PromptObserver> prompt_observer(
247 PromptObserver::Create(WebContents()));
248 std::string fill_and_submit =
249 "document.getElementById('create_form_button').click();"
250 "window.setTimeout(function() {"
251 " document.dynamic_form.username.value = 'tempro';"
252 " document.dynamic_form.password.value = 'random';"
253 " document.dynamic_form.submit();"
254 "}, 0)";
255 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
256 observer.Wait();
257 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
260 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase, NoPromptForNavigation) {
261 NavigateToFile("/password/password_form.html");
263 // Don't fill the password form, just navigate away. Shouldn't prompt.
264 NavigationObserver observer(WebContents());
265 scoped_ptr<PromptObserver> prompt_observer(
266 PromptObserver::Create(WebContents()));
267 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(),
268 "window.location.href = 'done.html';"));
269 observer.Wait();
270 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
273 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
274 NoPromptForSubFrameNavigation) {
275 NavigateToFile("/password/multi_frames.html");
277 // If you are filling out a password form in one frame and a different frame
278 // navigates, this should not trigger the infobar.
279 NavigationObserver observer(WebContents());
280 scoped_ptr<PromptObserver> prompt_observer(
281 PromptObserver::Create(WebContents()));
282 observer.SetPathToWaitFor("/password/done.html");
283 std::string fill =
284 "var first_frame = document.getElementById('first_frame');"
285 "var frame_doc = first_frame.contentDocument;"
286 "frame_doc.getElementById('username_field').value = 'temp';"
287 "frame_doc.getElementById('password_field').value = 'random';";
288 std::string navigate_frame =
289 "var second_iframe = document.getElementById('second_frame');"
290 "second_iframe.contentWindow.location.href = 'done.html';";
292 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill));
293 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), navigate_frame));
294 observer.Wait();
295 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
298 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
299 PromptAfterSubmitWithSubFrameNavigation) {
300 NavigateToFile("/password/multi_frames.html");
302 // Make sure that we prompt to save password even if a sub-frame navigation
303 // happens first.
304 NavigationObserver observer(WebContents());
305 scoped_ptr<PromptObserver> prompt_observer(
306 PromptObserver::Create(WebContents()));
307 observer.SetPathToWaitFor("/password/done.html");
308 std::string navigate_frame =
309 "var second_iframe = document.getElementById('second_frame');"
310 "second_iframe.contentWindow.location.href = 'other.html';";
311 std::string fill_and_submit =
312 "var first_frame = document.getElementById('first_frame');"
313 "var frame_doc = first_frame.contentDocument;"
314 "frame_doc.getElementById('username_field').value = 'temp';"
315 "frame_doc.getElementById('password_field').value = 'random';"
316 "frame_doc.getElementById('input_submit_button').click();";
318 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), navigate_frame));
319 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
320 observer.Wait();
321 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
324 IN_PROC_BROWSER_TEST_F(
325 PasswordManagerBrowserTestBase,
326 NoPromptForFailedLoginFromMainFrameWithMultiFramesInPage) {
327 NavigateToFile("/password/multi_frames.html");
329 // Make sure that we don't prompt to save the password for a failed login
330 // from the main frame with multiple frames in the same page.
331 NavigationObserver observer(WebContents());
332 scoped_ptr<PromptObserver> prompt_observer(
333 PromptObserver::Create(WebContents()));
334 std::string fill_and_submit =
335 "document.getElementById('username_failed').value = 'temp';"
336 "document.getElementById('password_failed').value = 'random';"
337 "document.getElementById('submit_failed').click();";
339 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
340 observer.Wait();
341 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
344 // Disabled on Mac due to flakiness: crbug.com/493263
345 #if defined(OS_MACOSX)
346 #define MAYBE_NoPromptForFailedLoginFromSubFrameWithMultiFramesInPage \
347 DISABLED_NoPromptForFailedLoginFromSubFrameWithMultiFramesInPage
348 #else
349 #define MAYBE_NoPromptForFailedLoginFromSubFrameWithMultiFramesInPage \
350 NoPromptForFailedLoginFromSubFrameWithMultiFramesInPage
351 #endif
352 IN_PROC_BROWSER_TEST_F(
353 PasswordManagerBrowserTestBase,
354 MAYBE_NoPromptForFailedLoginFromSubFrameWithMultiFramesInPage) {
355 NavigateToFile("/password/multi_frames.html");
357 // Make sure that we don't prompt to save the password for a failed login
358 // from a sub-frame with multiple frames in the same page.
359 NavigationObserver observer(WebContents());
360 scoped_ptr<PromptObserver> prompt_observer(
361 PromptObserver::Create(WebContents()));
362 std::string fill_and_submit =
363 "var first_frame = document.getElementById('first_frame');"
364 "var frame_doc = first_frame.contentDocument;"
365 "frame_doc.getElementById('username_failed').value = 'temp';"
366 "frame_doc.getElementById('password_failed').value = 'random';"
367 "frame_doc.getElementById('submit_failed').click();";
369 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
370 observer.SetPathToWaitFor("/password/failed.html");
371 observer.Wait();
372 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
375 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase, PromptForXHRSubmit) {
376 #if defined(OS_WIN) && defined(USE_ASH)
377 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
378 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
379 ::switches::kAshBrowserTests))
380 return;
381 #endif
382 NavigateToFile("/password/password_xhr_submit.html");
384 // Verify that we show the save password prompt if a form returns false
385 // in its onsubmit handler but instead logs in/navigates via XHR.
386 // Note that calling 'submit()' on a form with javascript doesn't call
387 // the onsubmit handler, so we click the submit button instead.
388 NavigationObserver observer(WebContents());
389 scoped_ptr<PromptObserver> prompt_observer(
390 PromptObserver::Create(WebContents()));
391 std::string fill_and_submit =
392 "document.getElementById('username_field').value = 'temp';"
393 "document.getElementById('password_field').value = 'random';"
394 "document.getElementById('submit_button').click()";
395 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
396 observer.Wait();
397 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
400 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
401 PromptForXHRWithoutOnSubmit) {
402 NavigateToFile("/password/password_xhr_submit.html");
404 // Verify that if XHR navigation occurs and the form is properly filled out,
405 // we try and save the password even though onsubmit hasn't been called.
406 NavigationObserver observer(WebContents());
407 scoped_ptr<PromptObserver> prompt_observer(
408 PromptObserver::Create(WebContents()));
409 std::string fill_and_navigate =
410 "document.getElementById('username_field').value = 'temp';"
411 "document.getElementById('password_field').value = 'random';"
412 "send_xhr()";
413 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_navigate));
414 observer.Wait();
415 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
418 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
419 PromptForXHRWithNewPasswordsWithoutOnSubmit) {
420 NavigateToFile("/password/password_xhr_submit.html");
422 // Verify that if XHR navigation occurs and the form is properly filled out,
423 // we try and save the password even though onsubmit hasn't been called.
424 // Specifically verify that the password form saving new passwords is treated
425 // the same as a login form.
426 NavigationObserver observer(WebContents());
427 scoped_ptr<PromptObserver> prompt_observer(
428 PromptObserver::Create(WebContents()));
429 std::string fill_and_navigate =
430 "document.getElementById('signup_username_field').value = 'temp';"
431 "document.getElementById('signup_password_field').value = 'random';"
432 "document.getElementById('confirmation_password_field').value = 'random';"
433 "send_xhr()";
434 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_navigate));
435 observer.Wait();
436 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
439 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
440 PromptForXHRSubmitWithoutNavigation) {
441 NavigateToFile("/password/password_xhr_submit.html");
443 // Need to pay attention for a message that XHR has finished since there
444 // is no navigation to wait for.
445 content::DOMMessageQueue message_queue;
447 // Verify that if XHR without navigation occurs and the form has been filled
448 // out we try and save the password. Note that in general the submission
449 // doesn't need to be via form.submit(), but for testing purposes it's
450 // necessary since we otherwise ignore changes made to the value of these
451 // fields by script.
452 scoped_ptr<PromptObserver> prompt_observer(
453 PromptObserver::Create(WebContents()));
454 std::string fill_and_submit =
455 "navigate = false;"
456 "document.getElementById('username_field').value = 'temp';"
457 "document.getElementById('password_field').value = 'random';"
458 "document.getElementById('submit_button').click();";
459 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
460 std::string message;
461 while (message_queue.WaitForMessage(&message)) {
462 if (message == "\"XHR_FINISHED\"")
463 break;
466 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
469 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
470 PromptForXHRSubmitWithoutNavigation_SignupForm) {
471 NavigateToFile("/password/password_xhr_submit.html");
473 // Need to pay attention for a message that XHR has finished since there
474 // is no navigation to wait for.
475 content::DOMMessageQueue message_queue;
477 // Verify that if XHR without navigation occurs and the form has been filled
478 // out we try and save the password. Note that in general the submission
479 // doesn't need to be via form.submit(), but for testing purposes it's
480 // necessary since we otherwise ignore changes made to the value of these
481 // fields by script.
482 scoped_ptr<PromptObserver> prompt_observer(
483 PromptObserver::Create(WebContents()));
484 std::string fill_and_submit =
485 "navigate = false;"
486 "document.getElementById('signup_username_field').value = 'temp';"
487 "document.getElementById('signup_password_field').value = 'random';"
488 "document.getElementById('confirmation_password_field').value = 'random';"
489 "document.getElementById('signup_submit_button').click();";
490 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
491 std::string message;
492 while (message_queue.WaitForMessage(&message)) {
493 if (message == "\"XHR_FINISHED\"")
494 break;
497 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
500 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
501 NoPromptForXHRSubmitWithoutNavigationWithUnfilledForm) {
502 NavigateToFile("/password/password_xhr_submit.html");
504 // Need to pay attention for a message that XHR has finished since there
505 // is no navigation to wait for.
506 content::DOMMessageQueue message_queue;
508 // Verify that if XHR without navigation occurs and the form has NOT been
509 // filled out we don't prompt.
510 scoped_ptr<PromptObserver> prompt_observer(
511 PromptObserver::Create(WebContents()));
512 std::string fill_and_submit =
513 "navigate = false;"
514 "document.getElementById('username_field').value = 'temp';"
515 "document.getElementById('submit_button').click();";
516 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
517 std::string message;
518 while (message_queue.WaitForMessage(&message)) {
519 if (message == "\"XHR_FINISHED\"")
520 break;
523 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
526 IN_PROC_BROWSER_TEST_F(
527 PasswordManagerBrowserTestBase,
528 NoPromptForXHRSubmitWithoutNavigationWithUnfilledForm_SignupForm) {
529 NavigateToFile("/password/password_xhr_submit.html");
531 // Need to pay attention for a message that XHR has finished since there
532 // is no navigation to wait for.
533 content::DOMMessageQueue message_queue;
535 // Verify that if XHR without navigation occurs and the form has NOT been
536 // filled out we don't prompt.
537 scoped_ptr<PromptObserver> prompt_observer(
538 PromptObserver::Create(WebContents()));
539 std::string fill_and_submit =
540 "navigate = false;"
541 "document.getElementById('signup_username_field').value = 'temp';"
542 "document.getElementById('signup_submit_button').click();";
543 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
544 std::string message;
545 while (message_queue.WaitForMessage(&message)) {
546 if (message == "\"XHR_FINISHED\"")
547 break;
550 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
553 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase, PromptForFetchSubmit) {
554 #if defined(OS_WIN) && defined(USE_ASH)
555 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
556 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
557 ::switches::kAshBrowserTests))
558 return;
559 #endif
560 NavigateToFile("/password/password_fetch_submit.html");
562 // Verify that we show the save password prompt if a form returns false
563 // in its onsubmit handler but instead logs in/navigates via Fetch.
564 // Note that calling 'submit()' on a form with javascript doesn't call
565 // the onsubmit handler, so we click the submit button instead.
566 NavigationObserver observer(WebContents());
567 scoped_ptr<PromptObserver> prompt_observer(
568 PromptObserver::Create(WebContents()));
569 std::string fill_and_submit =
570 "document.getElementById('username_field').value = 'temp';"
571 "document.getElementById('password_field').value = 'random';"
572 "document.getElementById('submit_button').click()";
573 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
574 observer.Wait();
575 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
578 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
579 PromptForFetchWithoutOnSubmit) {
580 NavigateToFile("/password/password_fetch_submit.html");
582 // Verify that if Fetch navigation occurs and the form is properly filled out,
583 // we try and save the password even though onsubmit hasn't been called.
584 NavigationObserver observer(WebContents());
585 scoped_ptr<PromptObserver> prompt_observer(
586 PromptObserver::Create(WebContents()));
587 std::string fill_and_navigate =
588 "document.getElementById('username_field').value = 'temp';"
589 "document.getElementById('password_field').value = 'random';"
590 "send_fetch()";
591 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_navigate));
592 observer.Wait();
593 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
596 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
597 PromptForFetchWithNewPasswordsWithoutOnSubmit) {
598 NavigateToFile("/password/password_fetch_submit.html");
600 // Verify that if Fetch navigation occurs and the form is properly filled out,
601 // we try and save the password even though onsubmit hasn't been called.
602 // Specifically verify that the password form saving new passwords is treated
603 // the same as a login form.
604 NavigationObserver observer(WebContents());
605 scoped_ptr<PromptObserver> prompt_observer(
606 PromptObserver::Create(WebContents()));
607 std::string fill_and_navigate =
608 "document.getElementById('signup_username_field').value = 'temp';"
609 "document.getElementById('signup_password_field').value = 'random';"
610 "document.getElementById('confirmation_password_field').value = 'random';"
611 "send_fetch()";
612 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_navigate));
613 observer.Wait();
614 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
617 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
618 PromptForFetchSubmitWithoutNavigation) {
619 NavigateToFile("/password/password_fetch_submit.html");
621 // Need to pay attention for a message that XHR has finished since there
622 // is no navigation to wait for.
623 content::DOMMessageQueue message_queue;
625 // Verify that if XHR without navigation occurs and the form has been filled
626 // out we try and save the password. Note that in general the submission
627 // doesn't need to be via form.submit(), but for testing purposes it's
628 // necessary since we otherwise ignore changes made to the value of these
629 // fields by script.
630 scoped_ptr<PromptObserver> prompt_observer(
631 PromptObserver::Create(WebContents()));
632 std::string fill_and_submit =
633 "navigate = false;"
634 "document.getElementById('username_field').value = 'temp';"
635 "document.getElementById('password_field').value = 'random';"
636 "document.getElementById('submit_button').click();";
637 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
638 std::string message;
639 while (message_queue.WaitForMessage(&message)) {
640 if (message == "\"FETCH_FINISHED\"")
641 break;
644 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
647 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
648 PromptForFetchSubmitWithoutNavigation_SignupForm) {
649 NavigateToFile("/password/password_fetch_submit.html");
651 // Need to pay attention for a message that Fetch has finished since there
652 // is no navigation to wait for.
653 content::DOMMessageQueue message_queue;
655 // Verify that if Fetch without navigation occurs and the form has been filled
656 // out we try and save the password. Note that in general the submission
657 // doesn't need to be via form.submit(), but for testing purposes it's
658 // necessary since we otherwise ignore changes made to the value of these
659 // fields by script.
660 scoped_ptr<PromptObserver> prompt_observer(
661 PromptObserver::Create(WebContents()));
662 std::string fill_and_submit =
663 "navigate = false;"
664 "document.getElementById('signup_username_field').value = 'temp';"
665 "document.getElementById('signup_password_field').value = 'random';"
666 "document.getElementById('confirmation_password_field').value = 'random';"
667 "document.getElementById('signup_submit_button').click();";
668 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
669 std::string message;
670 while (message_queue.WaitForMessage(&message)) {
671 if (message == "\"FETCH_FINISHED\"")
672 break;
675 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
678 IN_PROC_BROWSER_TEST_F(
679 PasswordManagerBrowserTestBase,
680 NoPromptForFetchSubmitWithoutNavigationWithUnfilledForm) {
681 NavigateToFile("/password/password_fetch_submit.html");
683 // Need to pay attention for a message that Fetch has finished since there
684 // is no navigation to wait for.
685 content::DOMMessageQueue message_queue;
687 // Verify that if Fetch without navigation occurs and the form has NOT been
688 // filled out we don't prompt.
689 scoped_ptr<PromptObserver> prompt_observer(
690 PromptObserver::Create(WebContents()));
691 std::string fill_and_submit =
692 "navigate = false;"
693 "document.getElementById('username_field').value = 'temp';"
694 "document.getElementById('submit_button').click();";
695 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
696 std::string message;
697 while (message_queue.WaitForMessage(&message)) {
698 if (message == "\"FETCH_FINISHED\"")
699 break;
702 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
705 IN_PROC_BROWSER_TEST_F(
706 PasswordManagerBrowserTestBase,
707 NoPromptForFetchSubmitWithoutNavigationWithUnfilledForm_SignupForm) {
708 NavigateToFile("/password/password_fetch_submit.html");
710 // Need to pay attention for a message that Fetch has finished since there
711 // is no navigation to wait for.
712 content::DOMMessageQueue message_queue;
714 // Verify that if Fetch without navigation occurs and the form has NOT been
715 // filled out we don't prompt.
716 scoped_ptr<PromptObserver> prompt_observer(
717 PromptObserver::Create(WebContents()));
718 std::string fill_and_submit =
719 "navigate = false;"
720 "document.getElementById('signup_username_field').value = 'temp';"
721 "document.getElementById('signup_submit_button').click();";
722 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
723 std::string message;
724 while (message_queue.WaitForMessage(&message)) {
725 if (message == "\"FETCH_FINISHED\"")
726 break;
729 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
732 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase, NoPromptIfLinkClicked) {
733 NavigateToFile("/password/password_form.html");
735 // Verify that if the user takes a direct action to leave the page, we don't
736 // prompt to save the password even if the form is already filled out.
737 NavigationObserver observer(WebContents());
738 scoped_ptr<PromptObserver> prompt_observer(
739 PromptObserver::Create(WebContents()));
740 std::string fill_and_click_link =
741 "document.getElementById('username_field').value = 'temp';"
742 "document.getElementById('password_field').value = 'random';"
743 "document.getElementById('link').click();";
744 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_click_link));
745 observer.Wait();
746 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
749 // TODO(jam): http://crbug.com/350550
750 #if !defined(OS_WIN)
751 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
752 VerifyPasswordGenerationUpload) {
753 // Prevent Autofill requests from actually going over the wire.
754 net::TestURLFetcherFactory factory;
755 // Disable Autofill requesting access to AddressBook data. This causes
756 // the test to hang on Mac.
757 autofill::test::DisableSystemServices(browser()->profile()->GetPrefs());
759 // Visit a signup form.
760 NavigateToFile("/password/signup_form.html");
762 // Enter a password and save it.
763 NavigationObserver first_observer(WebContents());
764 scoped_ptr<PromptObserver> prompt_observer(
765 PromptObserver::Create(WebContents()));
766 std::string fill_and_submit =
767 "document.getElementById('other_info').value = 'stuff';"
768 "document.getElementById('username_field').value = 'my_username';"
769 "document.getElementById('password_field').value = 'password';"
770 "document.getElementById('input_submit_button').click()";
771 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
773 first_observer.Wait();
774 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
775 prompt_observer->Accept();
777 // Now navigate to a login form that has similar HTML markup.
778 NavigateToFile("/password/password_form.html");
780 // Simulate a user click to force an autofill of the form's DOM value, not
781 // just the suggested value.
782 content::SimulateMouseClick(
783 WebContents(), 0, blink::WebMouseEvent::ButtonLeft);
785 // The form should be filled with the previously submitted username.
786 std::string get_username =
787 "window.domAutomationController.send("
788 "document.getElementById('username_field').value);";
789 std::string actual_username;
790 ASSERT_TRUE(content::ExecuteScriptAndExtractString(RenderViewHost(),
791 get_username,
792 &actual_username));
793 ASSERT_EQ("my_username", actual_username);
795 // Submit the form and verify that there is no infobar (as the password
796 // has already been saved).
797 NavigationObserver second_observer(WebContents());
798 scoped_ptr<PromptObserver> second_prompt_observer(
799 PromptObserver::Create(WebContents()));
800 std::string submit_form =
801 "document.getElementById('input_submit_button').click()";
802 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit_form));
803 second_observer.Wait();
804 EXPECT_FALSE(second_prompt_observer->IsShowingPrompt());
806 // Verify that we sent two pings to Autofill. One vote for of PASSWORD for
807 // the current form, and one vote for ACCOUNT_CREATION_PASSWORD on the
808 // original form since it has more than 2 text input fields and was used for
809 // the first time on a different form.
810 base::HistogramBase* upload_histogram =
811 base::StatisticsRecorder::FindHistogram(
812 "PasswordGeneration.UploadStarted");
813 ASSERT_TRUE(upload_histogram);
814 scoped_ptr<base::HistogramSamples> snapshot =
815 upload_histogram->SnapshotSamples();
816 EXPECT_EQ(0, snapshot->GetCount(0 /* failure */));
817 EXPECT_EQ(2, snapshot->GetCount(1 /* success */));
819 #endif
821 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
822 PromptForSubmitFromIframe) {
823 NavigateToFile("/password/password_submit_from_iframe.html");
825 // Submit a form in an iframe, then cause the whole page to navigate without a
826 // user gesture. We expect the save password prompt to be shown here, because
827 // some pages use such iframes for login forms.
828 NavigationObserver observer(WebContents());
829 scoped_ptr<PromptObserver> prompt_observer(
830 PromptObserver::Create(WebContents()));
831 std::string fill_and_submit =
832 "var iframe = document.getElementById('test_iframe');"
833 "var iframe_doc = iframe.contentDocument;"
834 "iframe_doc.getElementById('username_field').value = 'temp';"
835 "iframe_doc.getElementById('password_field').value = 'random';"
836 "iframe_doc.getElementById('submit_button').click()";
838 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
839 observer.Wait();
840 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
843 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
844 PromptForInputElementWithoutName) {
845 // Check that the prompt is shown for forms where input elements lack the
846 // "name" attribute but the "id" is present.
847 NavigateToFile("/password/password_form.html");
849 NavigationObserver observer(WebContents());
850 scoped_ptr<PromptObserver> prompt_observer(
851 PromptObserver::Create(WebContents()));
852 std::string fill_and_submit =
853 "document.getElementById('username_field_no_name').value = 'temp';"
854 "document.getElementById('password_field_no_name').value = 'random';"
855 "document.getElementById('input_submit_button_no_name').click()";
856 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
857 observer.Wait();
858 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
861 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
862 PromptForInputElementWithoutId) {
863 // Check that the prompt is shown for forms where input elements lack the
864 // "id" attribute but the "name" attribute is present.
865 NavigateToFile("/password/password_form.html");
867 NavigationObserver observer(WebContents());
868 scoped_ptr<PromptObserver> prompt_observer(
869 PromptObserver::Create(WebContents()));
870 std::string fill_and_submit =
871 "document.getElementsByName('username_field_no_id')[0].value = 'temp';"
872 "document.getElementsByName('password_field_no_id')[0].value = 'random';"
873 "document.getElementsByName('input_submit_button_no_id')[0].click()";
874 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
875 observer.Wait();
876 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
879 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
880 NoPromptForInputElementWithoutIdAndName) {
881 // Check that no prompt is shown for forms where the input fields lack both
882 // the "id" and the "name" attributes.
883 NavigateToFile("/password/password_form.html");
885 NavigationObserver observer(WebContents());
886 scoped_ptr<PromptObserver> prompt_observer(
887 PromptObserver::Create(WebContents()));
888 std::string fill_and_submit =
889 "var form = document.getElementById('testform_elements_no_id_no_name');"
890 "var username = form.children[0];"
891 "username.value = 'temp';"
892 "var password = form.children[1];"
893 "password.value = 'random';"
894 "form.children[2].click()"; // form.children[2] is the submit button.
895 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
896 observer.Wait();
897 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
900 // Test for checking that no prompt is shown for URLs with file: scheme.
901 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
902 NoPromptForFileSchemeURLs) {
903 GURL url = GetFileURL("password_form.html");
904 ui_test_utils::NavigateToURL(browser(), url);
906 NavigationObserver observer(WebContents());
907 scoped_ptr<PromptObserver> prompt_observer(
908 PromptObserver::Create(WebContents()));
909 std::string fill_and_submit =
910 "document.getElementById('username_field').value = 'temp';"
911 "document.getElementById('password_field').value = 'random';"
912 "document.getElementById('input_submit_button').click();";
913 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
914 observer.Wait();
915 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
918 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
919 NoPromptForLandingPageWithHTTPErrorStatusCode) {
920 // Check that no prompt is shown for forms where the landing page has
921 // HTTP status 404.
922 NavigateToFile("/password/password_form.html");
924 NavigationObserver observer(WebContents());
925 scoped_ptr<PromptObserver> prompt_observer(
926 PromptObserver::Create(WebContents()));
927 std::string fill_and_submit =
928 "document.getElementById('username_field_http_error').value = 'temp';"
929 "document.getElementById('password_field_http_error').value = 'random';"
930 "document.getElementById('input_submit_button_http_error').click()";
931 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
932 observer.Wait();
933 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
936 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
937 DeleteFrameBeforeSubmit) {
938 NavigateToFile("/password/multi_frames.html");
940 NavigationObserver observer(WebContents());
941 // Make sure we save some password info from an iframe and then destroy it.
942 std::string save_and_remove =
943 "var first_frame = document.getElementById('first_frame');"
944 "var frame_doc = first_frame.contentDocument;"
945 "frame_doc.getElementById('username_field').value = 'temp';"
946 "frame_doc.getElementById('password_field').value = 'random';"
947 "frame_doc.getElementById('input_submit_button').click();"
948 "first_frame.parentNode.removeChild(first_frame);";
949 // Submit from the main frame, but without navigating through the onsubmit
950 // handler.
951 std::string navigate_frame =
952 "document.getElementById('username_field').value = 'temp';"
953 "document.getElementById('password_field').value = 'random';"
954 "document.getElementById('input_submit_button').click();"
955 "window.location.href = 'done.html';";
957 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), save_and_remove));
958 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), navigate_frame));
959 observer.Wait();
960 // The only thing we check here is that there is no use-after-free reported.
963 // Disabled on Windows due to flakiness: http://crbug.com/346297
964 #if defined(OS_WIN)
965 #define MAYBE_PasswordValueAccessible DISABLED_PasswordValueAccessible
966 #else
967 #define MAYBE_PasswordValueAccessible PasswordValueAccessible
968 #endif
969 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
970 MAYBE_PasswordValueAccessible) {
971 NavigateToFile("/password/form_and_link.html");
973 // Click on a link to open a new tab, then switch back to the first one.
974 EXPECT_EQ(1, browser()->tab_strip_model()->count());
975 std::string click =
976 "document.getElementById('testlink').click();";
977 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), click));
978 EXPECT_EQ(2, browser()->tab_strip_model()->count());
979 browser()->tab_strip_model()->ActivateTabAt(0, false);
981 // Fill in the credentials, and make sure they are saved.
982 NavigationObserver form_submit_observer(WebContents());
983 scoped_ptr<PromptObserver> prompt_observer(
984 PromptObserver::Create(WebContents()));
985 std::string fill_and_submit =
986 "document.getElementById('username_field').value = 'temp';"
987 "document.getElementById('password_field').value = 'random';"
988 "document.getElementById('input_submit_button').click();";
989 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
990 form_submit_observer.Wait();
991 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
992 prompt_observer->Accept();
994 // Reload the original page to have the saved credentials autofilled.
995 NavigationObserver reload_observer(WebContents());
996 NavigateToFile("/password/form_and_link.html");
997 reload_observer.Wait();
999 // Wait until the username is filled, to make sure autofill kicked in.
1000 WaitForElementValue("username_field", "temp");
1001 // Now check that the password is not accessible yet.
1002 CheckElementValue("password_field", "");
1003 // Let the user interact with the page.
1004 content::SimulateMouseClickAt(
1005 WebContents(), 0, blink::WebMouseEvent::ButtonLeft, gfx::Point(1, 1));
1006 // Wait until that interaction causes the password value to be revealed.
1007 WaitForElementValue("password_field", "random");
1008 // And check that after the side-effects of the interaction took place, the
1009 // username value stays the same.
1010 CheckElementValue("username_field", "temp");
1013 // The following test is limited to Aura, because
1014 // RenderWidgetHostViewGuest::ProcessAckedTouchEvent is, and
1015 // ProcessAckedTouchEvent is what triggers the translation of touch events to
1016 // gesture events.
1017 // Disabled: http://crbug.com/346297
1018 #if defined(USE_AURA)
1019 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
1020 DISABLED_PasswordValueAccessibleOnSubmit) {
1021 NavigateToFile("/password/form_and_link.html");
1023 // Fill in the credentials, and make sure they are saved.
1024 NavigationObserver form_submit_observer(WebContents());
1025 scoped_ptr<PromptObserver> prompt_observer(
1026 PromptObserver::Create(WebContents()));
1027 std::string fill_and_submit =
1028 "document.getElementById('username_field').value = 'temp';"
1029 "document.getElementById('password_field').value = 'random_secret';"
1030 "document.getElementById('input_submit_button').click();";
1031 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1032 form_submit_observer.Wait();
1033 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1034 prompt_observer->Accept();
1036 // Reload the original page to have the saved credentials autofilled.
1037 NavigationObserver reload_observer(WebContents());
1038 NavigateToFile("/password/form_and_link.html");
1039 reload_observer.Wait();
1041 NavigationObserver submit_observer(WebContents());
1042 // Submit the form via a tap on the submit button. The button is placed at 0,
1043 // 100, and has height 300 and width 700.
1044 content::SimulateTapAt(WebContents(), gfx::Point(350, 250));
1045 submit_observer.Wait();
1046 std::string query = WebContents()->GetURL().query();
1047 EXPECT_NE(std::string::npos, query.find("random_secret")) << query;
1049 #endif
1051 // Test fix for crbug.com/338650.
1052 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
1053 DontPromptForPasswordFormWithDefaultValue) {
1054 NavigateToFile("/password/password_form_with_default_value.html");
1056 // Don't prompt if we navigate away even if there is a password value since
1057 // it's not coming from the user.
1058 NavigationObserver observer(WebContents());
1059 scoped_ptr<PromptObserver> prompt_observer(
1060 PromptObserver::Create(WebContents()));
1061 NavigateToFile("/password/done.html");
1062 observer.Wait();
1063 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
1066 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
1067 DontPromptForPasswordFormWithReadonlyPasswordField) {
1068 NavigateToFile("/password/password_form_with_password_readonly.html");
1070 // Fill a form and submit through a <input type="submit"> button. Nothing
1071 // special.
1072 NavigationObserver observer(WebContents());
1073 scoped_ptr<PromptObserver> prompt_observer(
1074 PromptObserver::Create(WebContents()));
1075 std::string fill_and_submit =
1076 "document.getElementById('username_field').value = 'temp';"
1077 "document.getElementById('password_field').value = 'random';"
1078 "document.getElementById('input_submit_button').click()";
1079 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1080 observer.Wait();
1081 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
1084 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
1085 PromptWhenEnableAutomaticPasswordSavingSwitchIsNotSet) {
1086 NavigateToFile("/password/password_form.html");
1088 // Fill a form and submit through a <input type="submit"> button.
1089 NavigationObserver observer(WebContents());
1090 scoped_ptr<PromptObserver> prompt_observer(
1091 PromptObserver::Create(WebContents()));
1092 std::string fill_and_submit =
1093 "document.getElementById('username_field').value = 'temp';"
1094 "document.getElementById('password_field').value = 'random';"
1095 "document.getElementById('input_submit_button').click()";
1096 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1097 observer.Wait();
1098 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1101 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
1102 DontPromptWhenEnableAutomaticPasswordSavingSwitchIsSet) {
1103 password_manager::TestPasswordStore* password_store =
1104 static_cast<password_manager::TestPasswordStore*>(
1105 PasswordStoreFactory::GetForProfile(
1106 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS).get());
1108 EXPECT_TRUE(password_store->IsEmpty());
1110 NavigateToFile("/password/password_form.html");
1112 // Add the enable-automatic-password-saving switch.
1113 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1114 password_manager::switches::kEnableAutomaticPasswordSaving);
1116 // Fill a form and submit through a <input type="submit"> button.
1117 NavigationObserver observer(WebContents());
1118 scoped_ptr<PromptObserver> prompt_observer(
1119 PromptObserver::Create(WebContents()));
1120 // Make sure that the only passwords saved are the auto-saved ones.
1121 std::string fill_and_submit =
1122 "document.getElementById('username_field').value = 'temp';"
1123 "document.getElementById('password_field').value = 'random';"
1124 "document.getElementById('input_submit_button').click()";
1125 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1126 observer.Wait();
1127 if (chrome::VersionInfo::GetChannel() ==
1128 chrome::VersionInfo::CHANNEL_UNKNOWN) {
1129 // Passwords getting auto-saved, no prompt.
1130 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
1131 EXPECT_FALSE(password_store->IsEmpty());
1132 } else {
1133 // Prompt shown, and no passwords saved automatically.
1134 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1135 EXPECT_TRUE(password_store->IsEmpty());
1139 // Test fix for crbug.com/368690.
1140 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase, NoPromptWhenReloading) {
1141 NavigateToFile("/password/password_form.html");
1143 std::string fill =
1144 "document.getElementById('username_redirect').value = 'temp';"
1145 "document.getElementById('password_redirect').value = 'random';";
1146 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill));
1148 NavigationObserver observer(WebContents());
1149 scoped_ptr<PromptObserver> prompt_observer(
1150 PromptObserver::Create(WebContents()));
1151 GURL url = embedded_test_server()->GetURL("/password/password_form.html");
1152 chrome::NavigateParams params(browser(), url, ::ui::PAGE_TRANSITION_RELOAD);
1153 ui_test_utils::NavigateToURL(&params);
1154 observer.Wait();
1155 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
1158 // Test that if a form gets dynamically added between the form parsing and
1159 // rendering, and while the main frame still loads, it still is registered, and
1160 // thus saving passwords from it works.
1161 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
1162 FormsAddedBetweenParsingAndRendering) {
1163 NavigateToFile("/password/between_parsing_and_rendering.html");
1165 NavigationObserver observer(WebContents());
1166 scoped_ptr<PromptObserver> prompt_observer(
1167 PromptObserver::Create(WebContents()));
1168 std::string submit =
1169 "document.getElementById('username').value = 'temp';"
1170 "document.getElementById('password').value = 'random';"
1171 "document.getElementById('submit-button').click();";
1172 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit));
1173 observer.Wait();
1175 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1178 // Test that if there was no previous page load then the PasswordManagerDriver
1179 // does not think that there were SSL errors on the current page. The test opens
1180 // a new tab with a URL for which the embedded test server issues a basic auth
1181 // challenge.
1182 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase, NoLastLoadGoodLastLoad) {
1183 // Teach the embedded server to handle requests by issuing the basic auth
1184 // challenge.
1185 embedded_test_server()->RegisterRequestHandler(
1186 base::Bind(&HandleTestAuthRequest));
1188 LoginPromptBrowserTestObserver login_observer;
1189 // We need to register to all sources, because the navigation observer we are
1190 // interested in is for a new tab to be opened, and thus does not exist yet.
1191 login_observer.Register(content::NotificationService::AllSources());
1193 password_manager::TestPasswordStore* password_store =
1194 static_cast<password_manager::TestPasswordStore*>(
1195 PasswordStoreFactory::GetForProfile(
1196 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS).get());
1197 EXPECT_TRUE(password_store->IsEmpty());
1199 // Navigate to a page requiring HTTP auth. Wait for the tab to get the correct
1200 // WebContents, but don't wait for navigation, which only finishes after
1201 // authentication.
1202 ui_test_utils::NavigateToURLWithDisposition(
1203 browser(),
1204 embedded_test_server()->GetURL("/basic_auth"),
1205 NEW_FOREGROUND_TAB,
1206 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
1208 content::NavigationController* nav_controller =
1209 &WebContents()->GetController();
1210 NavigationObserver nav_observer(WebContents());
1211 scoped_ptr<PromptObserver> prompt_observer(
1212 PromptObserver::Create(WebContents()));
1213 WindowedAuthNeededObserver auth_needed_observer(nav_controller);
1214 auth_needed_observer.Wait();
1216 WindowedAuthSuppliedObserver auth_supplied_observer(nav_controller);
1217 // Offer valid credentials on the auth challenge.
1218 ASSERT_EQ(1u, login_observer.handlers().size());
1219 LoginHandler* handler = *login_observer.handlers().begin();
1220 ASSERT_TRUE(handler);
1221 // Any username/password will work.
1222 handler->SetAuth(base::UTF8ToUTF16("user"), base::UTF8ToUTF16("pwd"));
1223 auth_supplied_observer.Wait();
1225 // The password manager should be working correctly.
1226 nav_observer.Wait();
1227 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1228 prompt_observer->Accept();
1230 // Spin the message loop to make sure the password store had a chance to save
1231 // the password.
1232 base::RunLoop run_loop;
1233 run_loop.RunUntilIdle();
1234 EXPECT_FALSE(password_store->IsEmpty());
1237 // In some situations, multiple PasswordFormManager instances from
1238 // PasswordManager::pending_login_managers_ would match (via DoesManage) a form
1239 // to be provisionally saved. One of them might be a complete match, the other
1240 // all-but-action match. Normally, the former should be preferred, but if the
1241 // former has not finished matching, and the latter has, the latter should be
1242 // used (otherwise we'd give up even though we could have saved the password).
1244 // Disabled on Mac and Linux due to flakiness: http://crbug.com/477812
1245 #if defined(OS_MACOSX) || defined(OS_LINUX)
1246 #define MAYBE_PreferPasswordFormManagerWhichFinishedMatching \
1247 DISABLED_PreferPasswordFormManagerWhichFinishedMatching
1248 #else
1249 #define MAYBE_PreferPasswordFormManagerWhichFinishedMatching \
1250 PreferPasswordFormManagerWhichFinishedMatching
1251 #endif
1252 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
1253 MAYBE_PreferPasswordFormManagerWhichFinishedMatching) {
1254 NavigateToFile("/password/create_form_copy_on_submit.html");
1256 NavigationObserver observer(WebContents());
1257 scoped_ptr<PromptObserver> prompt_observer(
1258 PromptObserver::Create(WebContents()));
1259 std::string submit =
1260 "document.getElementById('username').value = 'overwrite_me';"
1261 "document.getElementById('password').value = 'random';"
1262 "document.getElementById('non-form-button').click();";
1263 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit));
1264 observer.Wait();
1266 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1269 // Test that if login fails and content server pushes a different login form
1270 // with action URL having different schemes. Heuristic shall be able
1271 // identify such cases and *shall not* prompt to save incorrect password.
1272 IN_PROC_BROWSER_TEST_F(
1273 PasswordManagerBrowserTestBase,
1274 NoPromptForLoginFailedAndServerPushSeperateLoginForm_HttpToHttps) {
1275 std::string path =
1276 "/password/separate_login_form_with_onload_submit_script.html";
1277 GURL http_url(embedded_test_server()->GetURL(path));
1278 ASSERT_TRUE(http_url.SchemeIs(url::kHttpScheme));
1280 NavigationObserver observer(WebContents());
1281 scoped_ptr<PromptObserver> prompt_observer(
1282 PromptObserver::Create(WebContents()));
1283 ui_test_utils::NavigateToURL(browser(), http_url);
1285 observer.SetPathToWaitFor("/password/done_and_separate_login_form.html");
1286 observer.Wait();
1288 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
1291 IN_PROC_BROWSER_TEST_F(
1292 PasswordManagerBrowserTestBase,
1293 NoPromptForLoginFailedAndServerPushSeperateLoginForm_HttpsToHttp) {
1294 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1295 ::switches::kAllowRunningInsecureContent);
1296 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1297 ::switches::kIgnoreCertificateErrors);
1298 const base::FilePath::CharType kDocRoot[] =
1299 FILE_PATH_LITERAL("chrome/test/data");
1300 net::SpawnedTestServer https_test_server(
1301 net::SpawnedTestServer::TYPE_HTTPS,
1302 net::SpawnedTestServer::SSLOptions(
1303 net::SpawnedTestServer::SSLOptions::CERT_OK),
1304 base::FilePath(kDocRoot));
1305 ASSERT_TRUE(https_test_server.Start());
1307 // This test case cannot inject the scripts via content::ExecuteScript() in
1308 // files served through HTTPS. Therefore the scripts are made part of the HTML
1309 // site and executed on load.
1310 std::string path =
1311 "password/separate_login_form_with_onload_submit_script.html";
1312 GURL https_url(https_test_server.GetURL(path));
1313 ASSERT_TRUE(https_url.SchemeIs(url::kHttpsScheme));
1315 NavigationObserver observer(WebContents());
1316 scoped_ptr<PromptObserver> prompt_observer(
1317 PromptObserver::Create(WebContents()));
1318 ui_test_utils::NavigateToURL(browser(), https_url);
1320 observer.SetPathToWaitFor("/password/done_and_separate_login_form.html");
1321 observer.Wait();
1323 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
1326 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
1327 PromptWhenPasswordFormWithoutUsernameFieldSubmitted) {
1328 password_manager::TestPasswordStore* password_store =
1329 static_cast<password_manager::TestPasswordStore*>(
1330 PasswordStoreFactory::GetForProfile(
1331 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS).get());
1333 EXPECT_TRUE(password_store->IsEmpty());
1335 NavigateToFile("/password/form_with_only_password_field.html");
1337 NavigationObserver observer(WebContents());
1338 scoped_ptr<PromptObserver> prompt_observer(
1339 PromptObserver::Create(WebContents()));
1340 std::string submit =
1341 "document.getElementById('password').value = 'password';"
1342 "document.getElementById('submit-button').click();";
1343 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit));
1344 observer.Wait();
1346 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1347 prompt_observer->Accept();
1349 // Spin the message loop to make sure the password store had a chance to save
1350 // the password.
1351 base::RunLoop run_loop;
1352 run_loop.RunUntilIdle();
1353 EXPECT_FALSE(password_store->IsEmpty());
1356 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
1357 AutofillSuggetionsForPasswordFormWithoutUsernameField) {
1358 password_manager::TestPasswordStore* password_store =
1359 static_cast<password_manager::TestPasswordStore*>(
1360 PasswordStoreFactory::GetForProfile(
1361 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS).get());
1363 EXPECT_TRUE(password_store->IsEmpty());
1365 // Password form without username-field.
1366 NavigateToFile("/password/form_with_only_password_field.html");
1368 NavigationObserver observer(WebContents());
1369 scoped_ptr<PromptObserver> prompt_observer(
1370 PromptObserver::Create(WebContents()));
1371 std::string submit =
1372 "document.getElementById('password').value = 'mypassword';"
1373 "document.getElementById('submit-button').click();";
1374 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit));
1375 observer.Wait();
1377 prompt_observer->Accept();
1379 // Spin the message loop to make sure the password store had a chance to save
1380 // the password.
1381 base::RunLoop run_loop;
1382 run_loop.RunUntilIdle();
1383 EXPECT_FALSE(password_store->IsEmpty());
1385 // Now, navigate to same html password form and verify whether password is
1386 // autofilled.
1387 NavigateToFile("/password/form_with_only_password_field.html");
1389 // Let the user interact with the page, so that DOM gets modification events,
1390 // needed for autofilling fields.
1391 content::SimulateMouseClickAt(
1392 WebContents(), 0, blink::WebMouseEvent::ButtonLeft, gfx::Point(1, 1));
1394 // Wait until that interaction causes the password value to be revealed.
1395 WaitForElementValue("password", "mypassword");
1398 // Test that if a form gets autofilled, then it gets autofilled on re-creation
1399 // as well.
1400 // TODO(vabr): This is flaky everywhere. http://crbug.com/442704
1401 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
1402 DISABLED_ReCreatedFormsGetFilled) {
1403 NavigateToFile("/password/dynamic_password_form.html");
1405 // Fill in the credentials, and make sure they are saved.
1406 NavigationObserver form_submit_observer(WebContents());
1407 scoped_ptr<PromptObserver> prompt_observer(
1408 PromptObserver::Create(WebContents()));
1409 std::string create_fill_and_submit =
1410 "document.getElementById('create_form_button').click();"
1411 "window.setTimeout(function() {"
1412 " var form = document.getElementById('dynamic_form_id');"
1413 " form.username.value = 'temp';"
1414 " form.password.value = 'random';"
1415 " form.submit();"
1416 "}, 0)";
1417 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), create_fill_and_submit));
1418 form_submit_observer.Wait();
1419 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1420 prompt_observer->Accept();
1422 // Reload the original page to have the saved credentials autofilled.
1423 NavigationObserver reload_observer(WebContents());
1424 NavigateToFile("/password/dynamic_password_form.html");
1425 reload_observer.Wait();
1426 std::string create_form =
1427 "document.getElementById('create_form_button').click();";
1428 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), create_form));
1429 // Wait until the username is filled, to make sure autofill kicked in.
1430 WaitForElementValue("username_id", "temp");
1432 // Now the form gets deleted and created again. It should get autofilled
1433 // again.
1434 std::string delete_form =
1435 "var form = document.getElementById('dynamic_form_id');"
1436 "form.parentNode.removeChild(form);";
1437 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), delete_form));
1438 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), create_form));
1439 WaitForElementValue("username_id", "temp");
1442 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
1443 PromptForPushStateWhenFormDisappears) {
1444 NavigateToFile("/password/password_push_state.html");
1446 // Verify that we show the save password prompt if 'history.pushState()'
1447 // is called after form submission is suppressed by, for example, calling
1448 // preventDefault() in a form's submit event handler.
1449 // Note that calling 'submit()' on a form with javascript doesn't call
1450 // the onsubmit handler, so we click the submit button instead.
1451 // Also note that the prompt will only show up if the form disappers
1452 // after submission
1453 NavigationObserver observer(WebContents());
1454 observer.set_quit_on_entry_committed(true);
1455 scoped_ptr<PromptObserver> prompt_observer(
1456 PromptObserver::Create(WebContents()));
1457 std::string fill_and_submit =
1458 "document.getElementById('username_field').value = 'temp';"
1459 "document.getElementById('password_field').value = 'random';"
1460 "document.getElementById('submit_button').click()";
1461 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1462 observer.Wait();
1463 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1466 // Similar to the case above, but this time the form persists after
1467 // 'history.pushState()'. And save password prompt should not show up
1468 // in this case.
1469 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
1470 NoPromptForPushStateWhenFormPersists) {
1471 NavigateToFile("/password/password_push_state.html");
1473 // Set |should_delete_testform| to false to keep submitted form visible after
1474 // history.pushsTate();
1475 NavigationObserver observer(WebContents());
1476 observer.set_quit_on_entry_committed(true);
1477 scoped_ptr<PromptObserver> prompt_observer(
1478 PromptObserver::Create(WebContents()));
1479 std::string fill_and_submit =
1480 "should_delete_testform = false;"
1481 "document.getElementById('username_field').value = 'temp';"
1482 "document.getElementById('password_field').value = 'random';"
1483 "document.getElementById('submit_button').click()";
1484 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1485 observer.Wait();
1486 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
1489 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
1490 InFrameNavigationDoesNotClearPopupState) {
1491 // Mock out the AutofillClient so we know how long to wait. Unfortunately
1492 // there isn't otherwise a good even to wait on to verify that the popup
1493 // would have been shown.
1494 password_manager::ContentPasswordManagerDriverFactory* driver_factory =
1495 password_manager::ContentPasswordManagerDriverFactory::FromWebContents(
1496 WebContents());
1497 ObservingAutofillClient observing_autofill_client;
1498 driver_factory->TestingSetDriverForFrame(
1499 RenderViewHost()->GetMainFrame(),
1500 make_scoped_ptr(new password_manager::ContentPasswordManagerDriver(
1501 RenderViewHost()->GetMainFrame(),
1502 ChromePasswordManagerClient::FromWebContents(WebContents()),
1503 &observing_autofill_client)));
1505 NavigateToFile("/password/password_form.html");
1507 NavigationObserver form_submit_observer(WebContents());
1508 scoped_ptr<PromptObserver> prompt_observer(
1509 PromptObserver::Create(WebContents()));
1510 std::string fill =
1511 "document.getElementById('username_field').value = 'temp';"
1512 "document.getElementById('password_field').value = 'random123';"
1513 "document.getElementById('input_submit_button').click();";
1515 // Save credentials for the site.
1516 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill));
1517 form_submit_observer.Wait();
1518 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1519 prompt_observer->Accept();
1521 NavigateToFile("/password/password_form.html");
1522 ASSERT_TRUE(content::ExecuteScript(
1523 RenderViewHost(),
1524 "var usernameRect = document.getElementById('username_field')"
1525 ".getBoundingClientRect();"));
1527 // Trigger in page navigation.
1528 std::string in_page_navigate = "location.hash = '#blah';";
1529 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), in_page_navigate));
1531 // Click on the username field to display the popup.
1532 int top;
1533 ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
1534 RenderViewHost(),
1535 "window.domAutomationController.send(usernameRect.top);",
1536 &top));
1537 int left;
1538 ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
1539 RenderViewHost(),
1540 "window.domAutomationController.send(usernameRect.left);",
1541 &left));
1543 content::SimulateMouseClickAt(
1544 WebContents(), 0, blink::WebMouseEvent::ButtonLeft, gfx::Point(left + 1,
1545 top + 1));
1546 // Make sure the popup would be shown.
1547 observing_autofill_client.Wait();
1550 // Passwords from change password forms should only be offered for saving when
1551 // it is certain that the username is correct.
1552 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase, ChangePwdCorrect) {
1553 NavigateToFile("/password/password_form.html");
1555 NavigationObserver observer(WebContents());
1556 scoped_ptr<PromptObserver> prompt_observer(
1557 PromptObserver::Create(WebContents()));
1558 std::string fill_and_submit =
1559 "document.getElementById('mark_chg_username_field').value = 'temp';"
1560 "document.getElementById('mark_chg_password_field').value = 'random';"
1561 "document.getElementById('mark_chg_new_password_1').value = 'random1';"
1562 "document.getElementById('mark_chg_new_password_2').value = 'random1';"
1563 "document.getElementById('mark_chg_submit_button').click()";
1564 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1565 observer.Wait();
1566 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1569 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase, ChangePwdIncorrect) {
1570 NavigateToFile("/password/password_form.html");
1572 NavigationObserver observer(WebContents());
1573 scoped_ptr<PromptObserver> prompt_observer(
1574 PromptObserver::Create(WebContents()));
1575 std::string fill_and_submit =
1576 "document.getElementById('chg_not_username_field').value = 'temp';"
1577 "document.getElementById('chg_password_field').value = 'random';"
1578 "document.getElementById('chg_new_password_1').value = 'random1';"
1579 "document.getElementById('chg_new_password_2').value = 'random1';"
1580 "document.getElementById('chg_submit_button').click()";
1581 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1582 observer.Wait();
1583 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
1586 // As the two ChangePwd* tests above, only with submitting through
1587 // history.pushState().
1588 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
1589 ChangePwdPushStateCorrect) {
1590 NavigateToFile("/password/password_push_state.html");
1592 NavigationObserver observer(WebContents());
1593 observer.set_quit_on_entry_committed(true);
1594 scoped_ptr<PromptObserver> prompt_observer(
1595 PromptObserver::Create(WebContents()));
1596 std::string fill_and_submit =
1597 "document.getElementById('mark_chg_username_field').value = 'temp';"
1598 "document.getElementById('mark_chg_password_field').value = 'random';"
1599 "document.getElementById('mark_chg_new_password_1').value = 'random1';"
1600 "document.getElementById('mark_chg_new_password_2').value = 'random1';"
1601 "document.getElementById('mark_chg_submit_button').click()";
1602 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1603 observer.Wait();
1604 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1607 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
1608 ChangePwdPushStateIncorrect) {
1609 NavigateToFile("/password/password_push_state.html");
1611 NavigationObserver observer(WebContents());
1612 observer.set_quit_on_entry_committed(true);
1613 scoped_ptr<PromptObserver> prompt_observer(
1614 PromptObserver::Create(WebContents()));
1615 std::string fill_and_submit =
1616 "document.getElementById('chg_not_username_field').value = 'temp';"
1617 "document.getElementById('chg_password_field').value = 'random';"
1618 "document.getElementById('chg_new_password_1').value = 'random1';"
1619 "document.getElementById('chg_new_password_2').value = 'random1';"
1620 "document.getElementById('chg_submit_button').click()";
1621 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1622 observer.Wait();
1623 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
1626 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase, NoPromptOnBack) {
1627 // Go to a successful landing page through submitting first, so that it is
1628 // reachable through going back, and the remembered page transition is form
1629 // submit. There is no need to submit non-empty strings.
1630 NavigateToFile("/password/password_form.html");
1632 NavigationObserver dummy_submit_observer(WebContents());
1633 std::string just_submit =
1634 "document.getElementById('input_submit_button').click()";
1635 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), just_submit));
1636 dummy_submit_observer.Wait();
1638 // Now go to a page with a form again, fill the form, and go back instead of
1639 // submitting it.
1640 NavigateToFile("/password/dummy_submit.html");
1642 NavigationObserver observer(WebContents());
1643 scoped_ptr<PromptObserver> prompt_observer(
1644 PromptObserver::Create(WebContents()));
1645 // The (dummy) submit is necessary to provisionally save the typed password. A
1646 // user typing in the password field would not need to submit to provisionally
1647 // save it, but the script cannot trigger that just by assigning to the
1648 // field's value.
1649 std::string fill_and_back =
1650 "document.getElementById('password_field').value = 'random';"
1651 "document.getElementById('input_submit_button').click();"
1652 "window.history.back();";
1653 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_back));
1654 observer.Wait();
1655 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
1658 // Regression test for http://crbug.com/452306
1659 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
1660 ChangingTextToPasswordFieldOnSignupForm) {
1661 NavigateToFile("/password/signup_form.html");
1663 // In this case, pretend that username_field is actually a password field
1664 // that starts as a text field to simulate placeholder.
1665 NavigationObserver observer(WebContents());
1666 scoped_ptr<PromptObserver> prompt_observer(
1667 PromptObserver::Create(WebContents()));
1668 std::string change_and_submit =
1669 "document.getElementById('other_info').value = 'username';"
1670 "document.getElementById('username_field').type = 'password';"
1671 "document.getElementById('username_field').value = 'mypass';"
1672 "document.getElementById('password_field').value = 'mypass';"
1673 "document.getElementById('testform').submit();";
1674 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), change_and_submit));
1675 observer.Wait();
1676 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1679 // Regression test for http://crbug.com/451631
1680 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
1681 SavingOnManyPasswordFieldsTest) {
1682 // Simulate Macy's registration page, which contains the normal 2 password
1683 // fields for confirming the new password plus 2 more fields for security
1684 // questions and credit card. Make sure that saving works correctly for such
1685 // sites.
1686 NavigateToFile("/password/many_password_signup_form.html");
1688 NavigationObserver observer(WebContents());
1689 scoped_ptr<PromptObserver> prompt_observer(
1690 PromptObserver::Create(WebContents()));
1691 std::string fill_and_submit =
1692 "document.getElementById('username_field').value = 'username';"
1693 "document.getElementById('password_field').value = 'mypass';"
1694 "document.getElementById('confirm_field').value = 'mypass';"
1695 "document.getElementById('security_answer').value = 'hometown';"
1696 "document.getElementById('SSN').value = '1234';"
1697 "document.getElementById('testform').submit();";
1698 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1699 observer.Wait();
1700 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1703 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
1704 SaveWhenIFrameDestroyedOnFormSubmit) {
1705 NavigateToFile("/password/frame_detached_on_submit.html");
1707 // Need to pay attention for a message that XHR has finished since there
1708 // is no navigation to wait for.
1709 content::DOMMessageQueue message_queue;
1711 scoped_ptr<PromptObserver> prompt_observer(
1712 PromptObserver::Create(WebContents()));
1713 std::string fill_and_submit =
1714 "var iframe = document.getElementById('login_iframe');"
1715 "var frame_doc = iframe.contentDocument;"
1716 "frame_doc.getElementById('username_field').value = 'temp';"
1717 "frame_doc.getElementById('password_field').value = 'random';"
1718 "frame_doc.getElementById('submit_button').click();";
1720 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1721 std::string message;
1722 while (message_queue.WaitForMessage(&message)) {
1723 if (message == "\"SUBMISSION_FINISHED\"")
1724 break;
1727 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1730 // Tests that if a site embeds the login and signup forms into one <form>, the
1731 // login form still gets autofilled.
1732 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
1733 AutofillSuggetionsForLoginSignupForm) {
1734 password_manager::TestPasswordStore* password_store =
1735 static_cast<password_manager::TestPasswordStore*>(
1736 PasswordStoreFactory::GetForProfile(
1737 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS).get());
1739 EXPECT_TRUE(password_store->IsEmpty());
1741 NavigateToFile("/password/login_signup_form.html");
1743 NavigationObserver observer(WebContents());
1744 scoped_ptr<PromptObserver> prompt_observer(
1745 PromptObserver::Create(WebContents()));
1746 std::string submit =
1747 "document.getElementById('username').value = 'myusername';"
1748 "document.getElementById('password').value = 'mypassword';"
1749 "document.getElementById('submit').click();";
1750 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit));
1751 observer.Wait();
1753 prompt_observer->Accept();
1755 // Spin the message loop to make sure the password store had a chance to save
1756 // the password.
1757 base::RunLoop run_loop;
1758 run_loop.RunUntilIdle();
1759 EXPECT_FALSE(password_store->IsEmpty());
1761 // Now, navigate to the same html password form and verify whether password is
1762 // autofilled.
1763 NavigateToFile("/password/login_signup_form.html");
1765 // Let the user interact with the page, so that DOM gets modification events,
1766 // needed for autofilling fields.
1767 content::SimulateMouseClickAt(
1768 WebContents(), 0, blink::WebMouseEvent::ButtonLeft, gfx::Point(1, 1));
1770 // Wait until that interaction causes the password value to be revealed.
1771 WaitForElementValue("password", "mypassword");
1774 // Check that we can fill in cases where <base href> is set and the action of
1775 // the form is not set. Regression test for https://crbug.com/360230.
1776 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
1777 BaseTagWithNoActionTest) {
1778 password_manager::TestPasswordStore* password_store =
1779 static_cast<password_manager::TestPasswordStore*>(
1780 PasswordStoreFactory::GetForProfile(
1781 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS).get());
1783 EXPECT_TRUE(password_store->IsEmpty());
1785 NavigateToFile("/password/password_xhr_submit.html");
1787 NavigationObserver observer(WebContents());
1788 scoped_ptr<PromptObserver> prompt_observer(
1789 PromptObserver::Create(WebContents()));
1790 std::string submit =
1791 "document.getElementById('username_field').value = 'myusername';"
1792 "document.getElementById('password_field').value = 'mypassword';"
1793 "document.getElementById('submit_button').click();";
1794 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit));
1795 observer.Wait();
1797 prompt_observer->Accept();
1799 // Spin the message loop to make sure the password store had a chance to save
1800 // the password.
1801 base::RunLoop run_loop;
1802 run_loop.RunUntilIdle();
1803 EXPECT_FALSE(password_store->IsEmpty());
1805 NavigateToFile("/password/password_xhr_submit.html");
1807 // Let the user interact with the page, so that DOM gets modification events,
1808 // needed for autofilling fields.
1809 content::SimulateMouseClickAt(
1810 WebContents(), 0, blink::WebMouseEvent::ButtonLeft, gfx::Point(1, 1));
1812 // Wait until that interaction causes the password value to be revealed.
1813 WaitForElementValue("password_field", "mypassword");
1816 // Check that a password form in an iframe of different origin will not be
1817 // filled in until a user interact with the form.
1818 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
1819 CrossSiteIframeNotFillTest) {
1820 // Setup the mock host resolver
1821 host_resolver()->AddRule("*", "127.0.0.1");
1823 // Here we need to dynamically create the iframe because the port
1824 // embedded_test_server ran on was dynamically allocated, so the iframe's src
1825 // attribute can only be determined at run time.
1826 NavigateToFile("/password/password_form_in_crosssite_iframe.html");
1827 NavigationObserver ifrm_observer(WebContents());
1828 ifrm_observer.SetPathToWaitFor("/password/crossite_iframe_content.html");
1829 std::string create_iframe = base::StringPrintf(
1830 "create_iframe("
1831 "'http://randomsite.net:%d/password/crossite_iframe_content.html');",
1832 embedded_test_server()->port());
1833 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), create_iframe));
1834 ifrm_observer.Wait();
1836 // Store a password for autofill later
1837 NavigationObserver init_observer(WebContents());
1838 init_observer.SetPathToWaitFor("/password/done.html");
1839 scoped_ptr<PromptObserver> prompt_observer(
1840 PromptObserver::Create(WebContents()));
1841 std::string init_form = "sendMessage('fill_and_submit');";
1842 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), init_form));
1843 init_observer.Wait();
1844 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1845 prompt_observer->Accept();
1847 // Visit the form again
1848 NavigationObserver reload_observer(WebContents());
1849 NavigateToFile("/password/password_form_in_crosssite_iframe.html");
1850 reload_observer.Wait();
1852 NavigationObserver ifrm_observer_2(WebContents());
1853 ifrm_observer_2.SetPathToWaitFor("/password/crossite_iframe_content.html");
1854 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), create_iframe));
1855 ifrm_observer_2.Wait();
1857 // Verify username is not autofilled
1858 std::string empty_username;
1859 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
1860 RenderViewHost(),
1861 "sendMessage('get_username');",
1862 &empty_username));
1863 ASSERT_EQ("", empty_username);
1864 // Verify password is not autofilled
1865 std::string empty_password;
1866 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
1867 RenderViewHost(),
1868 "sendMessage('get_password');",
1869 &empty_password));
1870 ASSERT_EQ("", empty_password);
1872 // Simulate the user interaction in the iframe and verify autofill is not
1873 // triggered. Note this check is only best-effort because we don't know how
1874 // long to wait before we are certain that no autofill will be triggered.
1875 // Theoretically unexpected autofill can happen after this check.
1876 ASSERT_TRUE(content::ExecuteScript(
1877 RenderViewHost(),
1878 "var iframeRect = document.getElementById("
1879 "'iframe').getBoundingClientRect();"));
1880 int top;
1881 ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
1882 RenderViewHost(),
1883 "window.domAutomationController.send(iframeRect.top);",
1884 &top));
1885 int left;
1886 ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
1887 RenderViewHost(),
1888 "window.domAutomationController.send(iframeRect.left);",
1889 &left));
1891 content::SimulateMouseClickAt(
1892 WebContents(), 0, blink::WebMouseEvent::ButtonLeft, gfx::Point(left + 1,
1893 top + 1));
1894 // Verify username is not autofilled
1895 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
1896 RenderViewHost(),
1897 "sendMessage('get_username');",
1898 &empty_username));
1899 ASSERT_EQ("", empty_username);
1900 // Verify password is not autofilled
1901 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
1902 RenderViewHost(),
1903 "sendMessage('get_password');",
1904 &empty_password));
1905 ASSERT_EQ("", empty_password);
1908 // Check that a password form in an iframe of same origin will not be
1909 // filled in until user interact with the iframe.
1910 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
1911 SameOriginIframeAutoFillTest) {
1912 // Visit the sign-up form to store a password for autofill later
1913 NavigateToFile("/password/password_form_in_same_origin_iframe.html");
1914 NavigationObserver observer(WebContents());
1915 observer.SetPathToWaitFor("/password/done.html");
1916 scoped_ptr<PromptObserver> prompt_observer(
1917 PromptObserver::Create(WebContents()));
1919 std::string submit =
1920 "var ifrmDoc = document.getElementById('iframe').contentDocument;"
1921 "ifrmDoc.getElementById('username_field').value = 'temp';"
1922 "ifrmDoc.getElementById('password_field').value = 'pa55w0rd';"
1923 "ifrmDoc.getElementById('input_submit_button').click();";
1924 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit));
1925 observer.Wait();
1926 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1927 prompt_observer->Accept();
1929 // Visit the form again
1930 NavigationObserver reload_observer(WebContents());
1931 NavigateToFile("/password/password_form_in_same_origin_iframe.html");
1932 reload_observer.Wait();
1934 // Verify username is autofilled
1935 CheckElementValue("iframe", "username_field", "temp");
1937 // Verify password is not autofilled
1938 CheckElementValue("iframe", "password_field", "");
1940 // Simulate the user interaction in the iframe which should trigger autofill.
1941 ASSERT_TRUE(content::ExecuteScript(
1942 RenderViewHost(),
1943 "var iframeRect = document.getElementById("
1944 "'iframe').getBoundingClientRect();"));
1945 int top;
1946 ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
1947 RenderViewHost(),
1948 "window.domAutomationController.send(iframeRect.top);",
1949 &top));
1950 int left;
1951 ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
1952 RenderViewHost(),
1953 "window.domAutomationController.send(iframeRect.left);",
1954 &left));
1956 content::SimulateMouseClickAt(
1957 WebContents(), 0, blink::WebMouseEvent::ButtonLeft, gfx::Point(left + 1,
1958 top + 1));
1959 // Verify password has been autofilled
1960 WaitForElementValue("iframe", "password_field", "pa55w0rd");
1962 // Verify username has been autofilled
1963 CheckElementValue("iframe", "username_field", "temp");
1967 // The password manager driver will kill processes when they try to access
1968 // passwords of sites other than the site the process is dedicated to, under
1969 // site isolation.
1970 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
1971 CrossSitePasswordEnforcement) {
1972 // The code under test is only active under site isolation.
1973 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
1974 ::switches::kSitePerProcess)) {
1975 return;
1978 // Setup the mock host resolver
1979 host_resolver()->AddRule("*", "127.0.0.1");
1981 // Navigate the main frame.
1982 GURL main_frame_url = embedded_test_server()->GetURL(
1983 "/password/password_form_in_crosssite_iframe.html");
1984 NavigationObserver observer(WebContents());
1985 ui_test_utils::NavigateToURL(browser(), main_frame_url);
1986 observer.Wait();
1988 // Create an iframe and navigate cross-site.
1989 NavigationObserver iframe_observer(WebContents());
1990 iframe_observer.SetPathToWaitFor("/password/crossite_iframe_content.html");
1991 GURL iframe_url = embedded_test_server()->GetURL(
1992 "foo.com", "/password/crossite_iframe_content.html");
1993 std::string create_iframe =
1994 base::StringPrintf("create_iframe('%s');", iframe_url.spec().c_str());
1995 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), create_iframe));
1996 iframe_observer.Wait();
1998 // The iframe should get its own process.
1999 content::RenderFrameHost* main_frame = WebContents()->GetMainFrame();
2000 content::RenderFrameHost* iframe = iframe_observer.render_frame_host();
2001 content::SiteInstance* main_site_instance = main_frame->GetSiteInstance();
2002 content::SiteInstance* iframe_site_instance = iframe->GetSiteInstance();
2003 EXPECT_NE(main_site_instance, iframe_site_instance);
2004 EXPECT_NE(main_frame->GetProcess(), iframe->GetProcess());
2006 // Try to get cross-site passwords from the subframe's process and wait for it
2007 // to be killed.
2008 std::vector<autofill::PasswordForm> password_forms;
2009 password_forms.push_back(autofill::PasswordForm());
2010 password_forms.back().origin = main_frame_url;
2011 AutofillHostMsg_PasswordFormsParsed illegal_forms_parsed(
2012 iframe->GetRoutingID(), password_forms);
2014 content::RenderProcessHostWatcher iframe_killed(
2015 iframe->GetProcess(),
2016 content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
2018 IPC::IpcSecurityTestUtil::PwnMessageReceived(
2019 iframe->GetProcess()->GetChannel(), illegal_forms_parsed);
2021 iframe_killed.Wait();
2024 } // namespace password_manager