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.
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"
63 GURL
GetFileURL(const char* filename
) {
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();
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
{
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();
113 scoped_refptr
<content::MessageLoopRunner
> message_loop_runner_
;
115 DISALLOW_COPY_AND_ASSIGN(ObservingAutofillClient
);
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
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
));
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
));
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
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
));
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
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
));
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
));
209 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
211 // The redirection page now redirects via Javascript. We check that the
213 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(),
214 "window.location.href = 'done.html';"));
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
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
));
235 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
238 // Flaky: crbug.com/301547, observed on win and mac. Probably happens on all
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();"
255 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
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';"));
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");
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
));
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
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
));
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
));
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
349 #define MAYBE_NoPromptForFailedLoginFromSubFrameWithMultiFramesInPage \
350 NoPromptForFailedLoginFromSubFrameWithMultiFramesInPage
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");
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
))
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
));
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';"
413 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_navigate
));
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';"
434 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_navigate
));
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
452 scoped_ptr
<PromptObserver
> prompt_observer(
453 PromptObserver::Create(WebContents()));
454 std::string fill_and_submit
=
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
));
461 while (message_queue
.WaitForMessage(&message
)) {
462 if (message
== "\"XHR_FINISHED\"")
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
482 scoped_ptr
<PromptObserver
> prompt_observer(
483 PromptObserver::Create(WebContents()));
484 std::string fill_and_submit
=
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
));
492 while (message_queue
.WaitForMessage(&message
)) {
493 if (message
== "\"XHR_FINISHED\"")
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
=
514 "document.getElementById('username_field').value = 'temp';"
515 "document.getElementById('submit_button').click();";
516 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
518 while (message_queue
.WaitForMessage(&message
)) {
519 if (message
== "\"XHR_FINISHED\"")
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
=
541 "document.getElementById('signup_username_field').value = 'temp';"
542 "document.getElementById('signup_submit_button').click();";
543 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
545 while (message_queue
.WaitForMessage(&message
)) {
546 if (message
== "\"XHR_FINISHED\"")
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
))
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
));
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';"
591 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_navigate
));
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';"
612 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_navigate
));
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
630 scoped_ptr
<PromptObserver
> prompt_observer(
631 PromptObserver::Create(WebContents()));
632 std::string fill_and_submit
=
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
));
639 while (message_queue
.WaitForMessage(&message
)) {
640 if (message
== "\"FETCH_FINISHED\"")
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
660 scoped_ptr
<PromptObserver
> prompt_observer(
661 PromptObserver::Create(WebContents()));
662 std::string fill_and_submit
=
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
));
670 while (message_queue
.WaitForMessage(&message
)) {
671 if (message
== "\"FETCH_FINISHED\"")
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
=
693 "document.getElementById('username_field').value = 'temp';"
694 "document.getElementById('submit_button').click();";
695 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
697 while (message_queue
.WaitForMessage(&message
)) {
698 if (message
== "\"FETCH_FINISHED\"")
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
=
720 "document.getElementById('signup_username_field').value = 'temp';"
721 "document.getElementById('signup_submit_button').click();";
722 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
724 while (message_queue
.WaitForMessage(&message
)) {
725 if (message
== "\"FETCH_FINISHED\"")
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
));
746 EXPECT_FALSE(prompt_observer
->IsShowingPrompt());
749 // TODO(jam): http://crbug.com/350550
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(),
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 */));
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
));
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
));
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
));
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
));
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
));
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
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
));
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
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
));
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
965 #define MAYBE_PasswordValueAccessible DISABLED_PasswordValueAccessible
967 #define MAYBE_PasswordValueAccessible PasswordValueAccessible
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());
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
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
;
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");
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
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
));
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
));
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
));
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());
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");
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(¶ms
);
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
));
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
1182 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase
, NoLastLoadGoodLastLoad
) {
1183 // Teach the embedded server to handle requests by issuing the basic auth
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
1202 ui_test_utils::NavigateToURLWithDisposition(
1204 embedded_test_server()->GetURL("/basic_auth"),
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
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
1249 #define MAYBE_PreferPasswordFormManagerWhichFinishedMatching \
1250 PreferPasswordFormManagerWhichFinishedMatching
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
));
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
) {
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");
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.
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");
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
));
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
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
));
1377 prompt_observer
->Accept();
1379 // Spin the message loop to make sure the password store had a chance to save
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
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
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';"
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
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
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
));
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
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
));
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(
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()));
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(
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.
1533 ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
1535 "window.domAutomationController.send(usernameRect.top);",
1538 ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
1540 "window.domAutomationController.send(usernameRect.left);",
1543 content::SimulateMouseClickAt(
1544 WebContents(), 0, blink::WebMouseEvent::ButtonLeft
, gfx::Point(left
+ 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
));
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
));
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
));
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
));
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
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
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
));
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
));
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
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
));
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\"")
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
));
1753 prompt_observer
->Accept();
1755 // Spin the message loop to make sure the password store had a chance to save
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
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
));
1797 prompt_observer
->Accept();
1799 // Spin the message loop to make sure the password store had a chance to save
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(
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(
1861 "sendMessage('get_username');",
1863 ASSERT_EQ("", empty_username
);
1864 // Verify password is not autofilled
1865 std::string empty_password
;
1866 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
1868 "sendMessage('get_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(
1878 "var iframeRect = document.getElementById("
1879 "'iframe').getBoundingClientRect();"));
1881 ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
1883 "window.domAutomationController.send(iframeRect.top);",
1886 ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
1888 "window.domAutomationController.send(iframeRect.left);",
1891 content::SimulateMouseClickAt(
1892 WebContents(), 0, blink::WebMouseEvent::ButtonLeft
, gfx::Point(left
+ 1,
1894 // Verify username is not autofilled
1895 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
1897 "sendMessage('get_username');",
1899 ASSERT_EQ("", empty_username
);
1900 // Verify password is not autofilled
1901 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
1903 "sendMessage('get_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
));
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(
1943 "var iframeRect = document.getElementById("
1944 "'iframe').getBoundingClientRect();"));
1946 ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
1948 "window.domAutomationController.send(iframeRect.top);",
1951 ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
1953 "window.domAutomationController.send(iframeRect.left);",
1956 content::SimulateMouseClickAt(
1957 WebContents(), 0, blink::WebMouseEvent::ButtonLeft
, gfx::Point(left
+ 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
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
)) {
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
);
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
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