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/infobars/infobar_service.h"
17 #include "chrome/browser/password_manager/chrome_password_manager_client.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/passwords/manage_passwords_ui_controller.h"
25 #include "chrome/browser/ui/tabs/tab_strip_model.h"
26 #include "chrome/common/chrome_paths.h"
27 #include "chrome/common/chrome_switches.h"
28 #include "chrome/common/chrome_version_info.h"
29 #include "chrome/test/base/in_process_browser_test.h"
30 #include "chrome/test/base/test_switches.h"
31 #include "chrome/test/base/ui_test_utils.h"
32 #include "components/autofill/core/browser/autofill_test_utils.h"
33 #include "components/autofill/core/browser/test_autofill_client.h"
34 #include "components/infobars/core/confirm_infobar_delegate.h"
35 #include "components/infobars/core/infobar.h"
36 #include "components/infobars/core/infobar_manager.h"
37 #include "components/password_manager/content/browser/content_password_manager_driver.h"
38 #include "components/password_manager/content/browser/content_password_manager_driver_factory.h"
39 #include "components/password_manager/core/browser/test_password_store.h"
40 #include "components/password_manager/core/common/password_manager_switches.h"
41 #include "content/public/browser/navigation_controller.h"
42 #include "content/public/browser/notification_service.h"
43 #include "content/public/browser/render_frame_host.h"
44 #include "content/public/browser/render_view_host.h"
45 #include "content/public/browser/web_contents.h"
46 #include "content/public/browser/web_contents_observer.h"
47 #include "content/public/common/content_switches.h"
48 #include "content/public/test/browser_test_utils.h"
49 #include "content/public/test/test_utils.h"
50 #include "net/base/filename_util.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"
62 // NavigationObserver ---------------------------------------------------------
66 // Observer that waits for navigation to complete and for the password infobar
68 class NavigationObserver
: public content::WebContentsObserver
{
70 explicit NavigationObserver(content::WebContents
* web_contents
)
71 : content::WebContentsObserver(web_contents
),
72 quit_on_entry_commited_(false),
73 message_loop_runner_(new content::MessageLoopRunner
) {}
75 ~NavigationObserver() override
{}
77 // Normally Wait() will not return until a main frame navigation occurs.
78 // If a path is set, Wait() will return after this path has been seen,
79 // regardless of the frame that navigated. Useful for multi-frame pages.
80 void SetPathToWaitFor(const std::string
& path
) {
81 wait_for_path_
= path
;
84 // Normally Wait() will not return until a main frame navigation occurs.
85 // If quit_on_entry_commited is true Wait() will return on EntryCommited.
86 void SetQuitOnEntryCommitted(bool quit_on_entry_commited
) {
87 quit_on_entry_commited_
= quit_on_entry_commited
;
90 // content::WebContentsObserver:
91 void DidFinishLoad(content::RenderFrameHost
* render_frame_host
,
92 const GURL
& validated_url
) override
{
93 if (!wait_for_path_
.empty()) {
94 if (validated_url
.path() == wait_for_path_
)
95 message_loop_runner_
->Quit();
96 } else if (!render_frame_host
->GetParent()) {
97 message_loop_runner_
->Quit();
100 void NavigationEntryCommitted(
101 const content::LoadCommittedDetails
& load_details
) override
{
102 if (quit_on_entry_commited_
)
103 message_loop_runner_
->Quit();
105 void Wait() { message_loop_runner_
->Run(); }
108 std::string wait_for_path_
;
109 bool quit_on_entry_commited_
;
110 scoped_refptr
<content::MessageLoopRunner
> message_loop_runner_
;
112 DISALLOW_COPY_AND_ASSIGN(NavigationObserver
);
115 // Observes the save password prompt (bubble or infobar) for a specified
116 // WebContents, keeps track of whether or not it is currently shown, and allows
117 // accepting saving passwords through it.
118 class PromptObserver
{
120 virtual ~PromptObserver() {}
122 // Checks if the prompt is being currently shown.
123 virtual bool IsShowingPrompt() const = 0;
125 // Expecting that the prompt is shown, saves the password. Checks that the
126 // prompt is no longer visible afterwards.
127 void Accept() const {
128 EXPECT_TRUE(IsShowingPrompt());
132 // Chooses the right implementation of PromptObserver and creates an instance
134 static scoped_ptr
<PromptObserver
> Create(content::WebContents
* web_contents
);
139 // Accepts the password. The implementation can assume that the prompt is
140 // currently shown, but is required to verify that the prompt is eventually
142 virtual void AcceptImpl() const = 0;
145 DISALLOW_COPY_AND_ASSIGN(PromptObserver
);
148 class InfoBarObserver
: public PromptObserver
,
149 public infobars::InfoBarManager::Observer
{
151 explicit InfoBarObserver(content::WebContents
* web_contents
)
152 : infobar_is_being_shown_(false),
153 infobar_service_(InfoBarService::FromWebContents(web_contents
)) {
154 infobar_service_
->AddObserver(this);
157 ~InfoBarObserver() override
{
158 if (infobar_service_
)
159 infobar_service_
->RemoveObserver(this);
164 bool IsShowingPrompt() const override
{ return infobar_is_being_shown_
; }
166 void AcceptImpl() const override
{
167 EXPECT_EQ(1u, infobar_service_
->infobar_count());
168 if (!infobar_service_
->infobar_count())
169 return; // Let the test finish to gather possibly more diagnostics.
171 // ConfirmInfoBarDelegate::Accept returning true means the infobar is
172 // immediately closed. Checking the return value is preferred to testing
173 // IsShowingPrompt() here, for it avoids the delay until the closing
174 // notification is received.
175 EXPECT_TRUE(infobar_service_
->infobar_at(0)
177 ->AsConfirmInfoBarDelegate()
181 // infobars::InfoBarManager::Observer:
182 void OnInfoBarAdded(infobars::InfoBar
* infobar
) override
{
183 infobar_is_being_shown_
= true;
186 void OnInfoBarRemoved(infobars::InfoBar
* infobar
, bool animate
) override
{
187 infobar_is_being_shown_
= false;
190 void OnManagerShuttingDown(infobars::InfoBarManager
* manager
) override
{
191 ASSERT_EQ(infobar_service_
, manager
);
192 infobar_service_
->RemoveObserver(this);
193 infobar_service_
= nullptr;
196 bool infobar_is_being_shown_
;
197 InfoBarService
* infobar_service_
;
199 DISALLOW_COPY_AND_ASSIGN(InfoBarObserver
);
202 class BubbleObserver
: public PromptObserver
{
204 explicit BubbleObserver(content::WebContents
* web_contents
)
206 ManagePasswordsUIController::FromWebContents(web_contents
)) {}
208 ~BubbleObserver() override
{}
212 bool IsShowingPrompt() const override
{
213 return ui_controller_
->PasswordPendingUserDecision();
216 void AcceptImpl() const override
{
217 ui_controller_
->SavePassword();
218 EXPECT_FALSE(IsShowingPrompt());
221 ManagePasswordsUIController
* const ui_controller_
;
223 DISALLOW_COPY_AND_ASSIGN(BubbleObserver
);
226 class ObservingAutofillClient
: public autofill::TestAutofillClient
{
228 ObservingAutofillClient()
229 : message_loop_runner_(new content::MessageLoopRunner
){}
230 ~ObservingAutofillClient() override
{}
233 message_loop_runner_
->Run();
236 void ShowAutofillPopup(
237 const gfx::RectF
& element_bounds
,
238 base::i18n::TextDirection text_direction
,
239 const std::vector
<autofill::Suggestion
>& suggestions
,
240 base::WeakPtr
<autofill::AutofillPopupDelegate
> delegate
) override
{
241 message_loop_runner_
->Quit();
245 scoped_refptr
<content::MessageLoopRunner
> message_loop_runner_
;
247 DISALLOW_COPY_AND_ASSIGN(ObservingAutofillClient
);
250 GURL
GetFileURL(const char* filename
) {
252 PathService::Get(chrome::DIR_TEST_DATA
, &path
);
253 path
= path
.AppendASCII("password").AppendASCII(filename
);
254 CHECK(base::PathExists(path
));
255 return net::FilePathToFileURL(path
);
259 scoped_ptr
<PromptObserver
> PromptObserver::Create(
260 content::WebContents
* web_contents
) {
261 if (ChromePasswordManagerClient::IsTheHotNewBubbleUIEnabled()) {
262 return scoped_ptr
<PromptObserver
>(new BubbleObserver(web_contents
));
264 return scoped_ptr
<PromptObserver
>(new InfoBarObserver(web_contents
));
268 // Handles |request| to "/basic_auth". If "Authorization" header is present,
269 // responds with a non-empty HTTP 200 page (regardless of its value). Otherwise
270 // serves a Basic Auth challenge.
271 scoped_ptr
<net::test_server::HttpResponse
> HandleTestAuthRequest(
272 const net::test_server::HttpRequest
& request
) {
273 if (!StartsWithASCII(request
.relative_url
, "/basic_auth", true))
274 return scoped_ptr
<net::test_server::HttpResponse
>();
276 if (ContainsKey(request
.headers
, "Authorization")) {
277 scoped_ptr
<net::test_server::BasicHttpResponse
> http_response(
278 new net::test_server::BasicHttpResponse
);
279 http_response
->set_code(net::HTTP_OK
);
280 http_response
->set_content("Success!");
281 return http_response
.Pass();
283 scoped_ptr
<net::test_server::BasicHttpResponse
> http_response(
284 new net::test_server::BasicHttpResponse
);
285 http_response
->set_code(net::HTTP_UNAUTHORIZED
);
286 http_response
->AddCustomHeader("WWW-Authenticate",
287 "Basic realm=\"test realm\"");
288 return http_response
.Pass();
295 // PasswordManagerBrowserTest -------------------------------------------------
297 class PasswordManagerBrowserTest
: public InProcessBrowserTest
{
299 PasswordManagerBrowserTest() {}
300 ~PasswordManagerBrowserTest() override
{}
302 // InProcessBrowserTest:
303 void SetUpOnMainThread() override
{
304 // Use TestPasswordStore to remove a possible race. Normally the
305 // PasswordStore does its database manipulation on the DB thread, which
306 // creates a possible race during navigation. Specifically the
307 // PasswordManager will ignore any forms in a page if the load from the
308 // PasswordStore has not completed.
309 PasswordStoreFactory::GetInstance()->SetTestingFactory(
310 browser()->profile(), TestPasswordStoreService::Build
);
311 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
312 ASSERT_FALSE(base::CommandLine::ForCurrentProcess()->HasSwitch(
313 password_manager::switches::kEnableAutomaticPasswordSaving
));
316 void TearDownOnMainThread() override
{
317 ASSERT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
321 content::WebContents
* WebContents() {
322 return browser()->tab_strip_model()->GetActiveWebContents();
325 content::RenderViewHost
* RenderViewHost() {
326 return WebContents()->GetRenderViewHost();
329 // Wrapper around ui_test_utils::NavigateToURL that waits until
330 // DidFinishLoad() fires. Normally this function returns after
331 // DidStopLoading(), which caused flakiness as the NavigationObserver
332 // would sometimes see the DidFinishLoad event from a previous navigation and
333 // return immediately.
334 void NavigateToFile(const std::string
& path
) {
335 NavigationObserver
observer(WebContents());
336 GURL url
= embedded_test_server()->GetURL(path
);
337 ui_test_utils::NavigateToURL(browser(), url
);
341 // Waits until the "value" attribute of the HTML element with |element_id| is
342 // equal to |expected_value|. If the current value is not as expected, this
343 // waits until the "change" event is fired for the element. This also
344 // guarantees that once the real value matches the expected, the JavaScript
345 // event loop is spun to allow all other possible events to take place.
346 void WaitForElementValue(const std::string
& element_id
,
347 const std::string
& expected_value
);
348 // Checks that the current "value" attribute of the HTML element with
349 // |element_id| is equal to |expected_value|.
350 void CheckElementValue(const std::string
& element_id
,
351 const std::string
& expected_value
);
353 // TODO(dvadym): Remove this once history.pushState() handling is not behind
355 // Calling this will activate handling of pushState()-initiated form submits.
356 // This feature is currently behind a renderer flag. Just setting the flag in
357 // the browser will not change it for the already running renderer at tab 0.
358 // Therefore this method first sets the flag and then opens a new tab at
359 // position 0. This new tab gets the flag copied from the browser process.
360 void ActivateHistoryPushState();
363 DISALLOW_COPY_AND_ASSIGN(PasswordManagerBrowserTest
);
366 void PasswordManagerBrowserTest::WaitForElementValue(
367 const std::string
& element_id
,
368 const std::string
& expected_value
) {
369 enum ReturnCodes
{ // Possible results of the JavaScript code.
371 RETURN_CODE_NO_ELEMENT
,
372 RETURN_CODE_WRONG_VALUE
,
375 const std::string value_check_function
= base::StringPrintf(
376 "function valueCheck() {"
377 " var element = document.getElementById('%s');"
378 " return element && element.value == '%s';"
381 expected_value
.c_str());
382 const std::string script
=
383 value_check_function
+
385 "if (valueCheck()) {"
386 " /* Spin the event loop with setTimeout. */"
387 " setTimeout(window.domAutomationController.send(%d), 0);"
389 " var element = document.getElementById('%s');"
391 " window.domAutomationController.send(%d);"
392 " element.onchange = function() {"
393 " if (valueCheck()) {"
394 " /* Spin the event loop with setTimeout. */"
395 " setTimeout(window.domAutomationController.send(%d), 0);"
397 " window.domAutomationController.send(%d);"
403 RETURN_CODE_NO_ELEMENT
,
405 RETURN_CODE_WRONG_VALUE
);
406 int return_value
= RETURN_CODE_INVALID
;
407 ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
408 RenderViewHost(), script
, &return_value
));
409 EXPECT_EQ(RETURN_CODE_OK
, return_value
)
410 << "element_id = " << element_id
411 << ", expected_value = " << expected_value
;
414 void PasswordManagerBrowserTest::CheckElementValue(
415 const std::string
& element_id
,
416 const std::string
& expected_value
) {
417 const std::string value_check_script
= base::StringPrintf(
418 "var element = document.getElementById('%s');"
419 "window.domAutomationController.send(element && element.value == '%s');",
421 expected_value
.c_str());
422 bool return_value
= false;
423 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
424 RenderViewHost(), value_check_script
, &return_value
));
425 EXPECT_TRUE(return_value
) << "element_id = " << element_id
426 << ", expected_value = " << expected_value
;
429 void PasswordManagerBrowserTest::ActivateHistoryPushState() {
430 base::CommandLine::ForCurrentProcess()->AppendSwitch(
431 autofill::switches::kEnablePasswordSaveOnInPageNavigation
);
432 AddTabAtIndex(0, GURL(url::kAboutBlankURL
), ui::PAGE_TRANSITION_TYPED
);
435 // Actual tests ---------------------------------------------------------------
436 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
437 PromptForNormalSubmit
) {
438 NavigateToFile("/password/password_form.html");
440 // Fill a form and submit through a <input type="submit"> button. Nothing
442 NavigationObserver
observer(WebContents());
443 scoped_ptr
<PromptObserver
> prompt_observer(
444 PromptObserver::Create(WebContents()));
445 std::string fill_and_submit
=
446 "document.getElementById('username_field').value = 'temp';"
447 "document.getElementById('password_field').value = 'random';"
448 "document.getElementById('input_submit_button').click()";
449 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
451 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
454 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
455 PromptForSubmitWithInPageNavigation
) {
456 NavigateToFile("/password/password_navigate_before_submit.html");
458 // Fill a form and submit through a <input type="submit"> button. Nothing
459 // special. The form does an in-page navigation before submitting.
460 NavigationObserver
observer(WebContents());
461 scoped_ptr
<PromptObserver
> prompt_observer(
462 PromptObserver::Create(WebContents()));
463 std::string fill_and_submit
=
464 "document.getElementById('username_field').value = 'temp';"
465 "document.getElementById('password_field').value = 'random';"
466 "document.getElementById('input_submit_button').click()";
467 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
469 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
472 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
473 LoginSuccessWithUnrelatedForm
) {
474 // Log in, see a form on the landing page. That form is not related to the
475 // login form (=has a different action), so we should offer saving the
477 NavigateToFile("/password/password_form.html");
479 NavigationObserver
observer(WebContents());
480 scoped_ptr
<PromptObserver
> prompt_observer(
481 PromptObserver::Create(WebContents()));
482 std::string fill_and_submit
=
483 "document.getElementById('username_unrelated').value = 'temp';"
484 "document.getElementById('password_unrelated').value = 'random';"
485 "document.getElementById('submit_unrelated').click()";
486 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
488 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
491 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
, LoginFailed
) {
492 // Log in, see a form on the landing page. That form is not related to the
493 // login form (=has a different action), so we should offer saving the
495 NavigateToFile("/password/password_form.html");
497 NavigationObserver
observer(WebContents());
498 scoped_ptr
<PromptObserver
> prompt_observer(
499 PromptObserver::Create(WebContents()));
500 std::string fill_and_submit
=
501 "document.getElementById('username_failed').value = 'temp';"
502 "document.getElementById('password_failed').value = 'random';"
503 "document.getElementById('submit_failed').click()";
504 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
506 EXPECT_FALSE(prompt_observer
->IsShowingPrompt());
509 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
, Redirects
) {
510 NavigateToFile("/password/password_form.html");
512 // Fill a form and submit through a <input type="submit"> button. The form
513 // points to a redirection page.
514 NavigationObserver
observer(WebContents());
515 scoped_ptr
<PromptObserver
> prompt_observer(
516 PromptObserver::Create(WebContents()));
517 std::string fill_and_submit
=
518 "document.getElementById('username_redirect').value = 'temp';"
519 "document.getElementById('password_redirect').value = 'random';"
520 "document.getElementById('submit_redirect').click()";
521 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
523 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
525 // The redirection page now redirects via Javascript. We check that the
527 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(),
528 "window.location.href = 'done.html';"));
530 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
533 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
534 PromptForSubmitUsingJavaScript
) {
535 NavigateToFile("/password/password_form.html");
537 // Fill a form and submit using <button> that calls submit() on the form.
538 // This should work regardless of the type of element, as long as submit() is
540 NavigationObserver
observer(WebContents());
541 scoped_ptr
<PromptObserver
> prompt_observer(
542 PromptObserver::Create(WebContents()));
543 std::string fill_and_submit
=
544 "document.getElementById('username_field').value = 'temp';"
545 "document.getElementById('password_field').value = 'random';"
546 "document.getElementById('submit_button').click()";
547 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
549 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
552 // Flaky: crbug.com/301547, observed on win and mac. Probably happens on all
554 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
555 DISABLED_PromptForDynamicForm
) {
556 NavigateToFile("/password/dynamic_password_form.html");
558 // Fill the dynamic password form and submit.
559 NavigationObserver
observer(WebContents());
560 scoped_ptr
<PromptObserver
> prompt_observer(
561 PromptObserver::Create(WebContents()));
562 std::string fill_and_submit
=
563 "document.getElementById('create_form_button').click();"
564 "window.setTimeout(function() {"
565 " document.dynamic_form.username.value = 'tempro';"
566 " document.dynamic_form.password.value = 'random';"
567 " document.dynamic_form.submit();"
569 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
571 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
574 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
, NoPromptForNavigation
) {
575 NavigateToFile("/password/password_form.html");
577 // Don't fill the password form, just navigate away. Shouldn't prompt.
578 NavigationObserver
observer(WebContents());
579 scoped_ptr
<PromptObserver
> prompt_observer(
580 PromptObserver::Create(WebContents()));
581 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(),
582 "window.location.href = 'done.html';"));
584 EXPECT_FALSE(prompt_observer
->IsShowingPrompt());
587 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
588 NoPromptForSubFrameNavigation
) {
589 NavigateToFile("/password/multi_frames.html");
591 // If you are filling out a password form in one frame and a different frame
592 // navigates, this should not trigger the infobar.
593 NavigationObserver
observer(WebContents());
594 scoped_ptr
<PromptObserver
> prompt_observer(
595 PromptObserver::Create(WebContents()));
596 observer
.SetPathToWaitFor("/password/done.html");
598 "var first_frame = document.getElementById('first_frame');"
599 "var frame_doc = first_frame.contentDocument;"
600 "frame_doc.getElementById('username_field').value = 'temp';"
601 "frame_doc.getElementById('password_field').value = 'random';";
602 std::string navigate_frame
=
603 "var second_iframe = document.getElementById('second_frame');"
604 "second_iframe.contentWindow.location.href = 'done.html';";
606 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill
));
607 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), navigate_frame
));
609 EXPECT_FALSE(prompt_observer
->IsShowingPrompt());
612 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
613 PromptAfterSubmitWithSubFrameNavigation
) {
614 NavigateToFile("/password/multi_frames.html");
616 // Make sure that we prompt to save password even if a sub-frame navigation
618 NavigationObserver
observer(WebContents());
619 scoped_ptr
<PromptObserver
> prompt_observer(
620 PromptObserver::Create(WebContents()));
621 observer
.SetPathToWaitFor("/password/done.html");
622 std::string navigate_frame
=
623 "var second_iframe = document.getElementById('second_frame');"
624 "second_iframe.contentWindow.location.href = 'other.html';";
625 std::string fill_and_submit
=
626 "var first_frame = document.getElementById('first_frame');"
627 "var frame_doc = first_frame.contentDocument;"
628 "frame_doc.getElementById('username_field').value = 'temp';"
629 "frame_doc.getElementById('password_field').value = 'random';"
630 "frame_doc.getElementById('input_submit_button').click();";
632 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), navigate_frame
));
633 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
635 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
638 IN_PROC_BROWSER_TEST_F(
639 PasswordManagerBrowserTest
,
640 NoPromptForFailedLoginFromMainFrameWithMultiFramesInPage
) {
641 NavigateToFile("/password/multi_frames.html");
643 // Make sure that we don't prompt to save the password for a failed login
644 // from the main frame with multiple frames in the same page.
645 NavigationObserver
observer(WebContents());
646 scoped_ptr
<PromptObserver
> prompt_observer(
647 PromptObserver::Create(WebContents()));
648 std::string fill_and_submit
=
649 "document.getElementById('username_failed').value = 'temp';"
650 "document.getElementById('password_failed').value = 'random';"
651 "document.getElementById('submit_failed').click();";
653 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
655 EXPECT_FALSE(prompt_observer
->IsShowingPrompt());
658 IN_PROC_BROWSER_TEST_F(
659 PasswordManagerBrowserTest
,
660 NoPromptForFailedLoginFromSubFrameWithMultiFramesInPage
) {
661 NavigateToFile("/password/multi_frames.html");
663 // Make sure that we don't prompt to save the password for a failed login
664 // from a sub-frame with multiple frames in the same page.
665 NavigationObserver
observer(WebContents());
666 scoped_ptr
<PromptObserver
> prompt_observer(
667 PromptObserver::Create(WebContents()));
668 std::string fill_and_submit
=
669 "var first_frame = document.getElementById('first_frame');"
670 "var frame_doc = first_frame.contentDocument;"
671 "frame_doc.getElementById('username_failed').value = 'temp';"
672 "frame_doc.getElementById('password_failed').value = 'random';"
673 "frame_doc.getElementById('submit_failed').click();";
675 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
676 observer
.SetPathToWaitFor("/password/failed.html");
678 EXPECT_FALSE(prompt_observer
->IsShowingPrompt());
681 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
, PromptForXHRSubmit
) {
682 #if defined(OS_WIN) && defined(USE_ASH)
683 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
684 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
685 switches::kAshBrowserTests
))
688 NavigateToFile("/password/password_xhr_submit.html");
690 // Verify that we show the save password prompt if a form returns false
691 // in its onsubmit handler but instead logs in/navigates via XHR.
692 // Note that calling 'submit()' on a form with javascript doesn't call
693 // the onsubmit handler, so we click the submit button instead.
694 NavigationObserver
observer(WebContents());
695 scoped_ptr
<PromptObserver
> prompt_observer(
696 PromptObserver::Create(WebContents()));
697 std::string fill_and_submit
=
698 "document.getElementById('username_field').value = 'temp';"
699 "document.getElementById('password_field').value = 'random';"
700 "document.getElementById('submit_button').click()";
701 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
703 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
706 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
707 PromptForXHRWithoutOnSubmit
) {
708 NavigateToFile("/password/password_xhr_submit.html");
710 // Verify that if XHR navigation occurs and the form is properly filled out,
711 // we try and save the password even though onsubmit hasn't been called.
712 NavigationObserver
observer(WebContents());
713 scoped_ptr
<PromptObserver
> prompt_observer(
714 PromptObserver::Create(WebContents()));
715 std::string fill_and_navigate
=
716 "document.getElementById('username_field').value = 'temp';"
717 "document.getElementById('password_field').value = 'random';"
719 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_navigate
));
721 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
724 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
725 PromptForXHRWithNewPasswordsWithoutOnSubmit
) {
726 NavigateToFile("/password/password_xhr_submit.html");
728 // Verify that if XHR navigation occurs and the form is properly filled out,
729 // we try and save the password even though onsubmit hasn't been called.
730 // Specifically verify that the password form saving new passwords is treated
731 // the same as a login form.
732 NavigationObserver
observer(WebContents());
733 scoped_ptr
<PromptObserver
> prompt_observer(
734 PromptObserver::Create(WebContents()));
735 std::string fill_and_navigate
=
736 "document.getElementById('signup_username_field').value = 'temp';"
737 "document.getElementById('signup_password_field').value = 'random';"
738 "document.getElementById('confirmation_password_field').value = 'random';"
740 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_navigate
));
742 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
745 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
746 PromptForXHRSubmitWithoutNavigation
) {
747 NavigateToFile("/password/password_xhr_submit.html");
749 // Need to pay attention for a message that XHR has finished since there
750 // is no navigation to wait for.
751 content::DOMMessageQueue message_queue
;
753 // Verify that if XHR without navigation occurs and the form has been filled
754 // out we try and save the password. Note that in general the submission
755 // doesn't need to be via form.submit(), but for testing purposes it's
756 // necessary since we otherwise ignore changes made to the value of these
758 scoped_ptr
<PromptObserver
> prompt_observer(
759 PromptObserver::Create(WebContents()));
760 std::string fill_and_submit
=
762 "document.getElementById('username_field').value = 'temp';"
763 "document.getElementById('password_field').value = 'random';"
764 "document.getElementById('submit_button').click();";
765 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
767 while (message_queue
.WaitForMessage(&message
)) {
768 if (message
== "\"XHR_FINISHED\"")
772 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
775 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
776 PromptForXHRSubmitWithoutNavigation_SignupForm
) {
777 NavigateToFile("/password/password_xhr_submit.html");
779 // Need to pay attention for a message that XHR has finished since there
780 // is no navigation to wait for.
781 content::DOMMessageQueue message_queue
;
783 // Verify that if XHR without navigation occurs and the form has been filled
784 // out we try and save the password. Note that in general the submission
785 // doesn't need to be via form.submit(), but for testing purposes it's
786 // necessary since we otherwise ignore changes made to the value of these
788 scoped_ptr
<PromptObserver
> prompt_observer(
789 PromptObserver::Create(WebContents()));
790 std::string fill_and_submit
=
792 "document.getElementById('signup_username_field').value = 'temp';"
793 "document.getElementById('signup_password_field').value = 'random';"
794 "document.getElementById('confirmation_password_field').value = 'random';"
795 "document.getElementById('signup_submit_button').click();";
796 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
798 while (message_queue
.WaitForMessage(&message
)) {
799 if (message
== "\"XHR_FINISHED\"")
803 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
806 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
807 NoPromptForXHRSubmitWithoutNavigationWithUnfilledForm
) {
808 NavigateToFile("/password/password_xhr_submit.html");
810 // Need to pay attention for a message that XHR has finished since there
811 // is no navigation to wait for.
812 content::DOMMessageQueue message_queue
;
814 // Verify that if XHR without navigation occurs and the form has NOT been
815 // filled out we don't prompt.
816 scoped_ptr
<PromptObserver
> prompt_observer(
817 PromptObserver::Create(WebContents()));
818 std::string fill_and_submit
=
820 "document.getElementById('username_field').value = 'temp';"
821 "document.getElementById('submit_button').click();";
822 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
824 while (message_queue
.WaitForMessage(&message
)) {
825 if (message
== "\"XHR_FINISHED\"")
829 EXPECT_FALSE(prompt_observer
->IsShowingPrompt());
832 IN_PROC_BROWSER_TEST_F(
833 PasswordManagerBrowserTest
,
834 NoPromptForXHRSubmitWithoutNavigationWithUnfilledForm_SignupForm
) {
835 NavigateToFile("/password/password_xhr_submit.html");
837 // Need to pay attention for a message that XHR has finished since there
838 // is no navigation to wait for.
839 content::DOMMessageQueue message_queue
;
841 // Verify that if XHR without navigation occurs and the form has NOT been
842 // filled out we don't prompt.
843 scoped_ptr
<PromptObserver
> prompt_observer(
844 PromptObserver::Create(WebContents()));
845 std::string fill_and_submit
=
847 "document.getElementById('signup_username_field').value = 'temp';"
848 "document.getElementById('signup_submit_button').click();";
849 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
851 while (message_queue
.WaitForMessage(&message
)) {
852 if (message
== "\"XHR_FINISHED\"")
856 EXPECT_FALSE(prompt_observer
->IsShowingPrompt());
859 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
, NoPromptIfLinkClicked
) {
860 NavigateToFile("/password/password_form.html");
862 // Verify that if the user takes a direct action to leave the page, we don't
863 // prompt to save the password even if the form is already filled out.
864 NavigationObserver
observer(WebContents());
865 scoped_ptr
<PromptObserver
> prompt_observer(
866 PromptObserver::Create(WebContents()));
867 std::string fill_and_click_link
=
868 "document.getElementById('username_field').value = 'temp';"
869 "document.getElementById('password_field').value = 'random';"
870 "document.getElementById('link').click();";
871 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_click_link
));
873 EXPECT_FALSE(prompt_observer
->IsShowingPrompt());
876 // TODO(jam): http://crbug.com/350550
878 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
879 VerifyPasswordGenerationUpload
) {
880 // Prevent Autofill requests from actually going over the wire.
881 net::TestURLFetcherFactory factory
;
882 // Disable Autofill requesting access to AddressBook data. This causes
883 // the test to hang on Mac.
884 autofill::test::DisableSystemServices(browser()->profile()->GetPrefs());
886 // Visit a signup form.
887 NavigateToFile("/password/signup_form.html");
889 // Enter a password and save it.
890 NavigationObserver
first_observer(WebContents());
891 scoped_ptr
<PromptObserver
> prompt_observer(
892 PromptObserver::Create(WebContents()));
893 std::string fill_and_submit
=
894 "document.getElementById('other_info').value = 'stuff';"
895 "document.getElementById('username_field').value = 'my_username';"
896 "document.getElementById('password_field').value = 'password';"
897 "document.getElementById('input_submit_button').click()";
898 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
900 first_observer
.Wait();
901 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
902 prompt_observer
->Accept();
904 // Now navigate to a login form that has similar HTML markup.
905 NavigateToFile("/password/password_form.html");
907 // Simulate a user click to force an autofill of the form's DOM value, not
908 // just the suggested value.
909 content::SimulateMouseClick(
910 WebContents(), 0, blink::WebMouseEvent::ButtonLeft
);
912 // The form should be filled with the previously submitted username.
913 std::string get_username
=
914 "window.domAutomationController.send("
915 "document.getElementById('username_field').value);";
916 std::string actual_username
;
917 ASSERT_TRUE(content::ExecuteScriptAndExtractString(RenderViewHost(),
920 ASSERT_EQ("my_username", actual_username
);
922 // Submit the form and verify that there is no infobar (as the password
923 // has already been saved).
924 NavigationObserver
second_observer(WebContents());
925 scoped_ptr
<PromptObserver
> second_prompt_observer(
926 PromptObserver::Create(WebContents()));
927 std::string submit_form
=
928 "document.getElementById('input_submit_button').click()";
929 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit_form
));
930 second_observer
.Wait();
931 EXPECT_FALSE(second_prompt_observer
->IsShowingPrompt());
933 // Verify that we sent two pings to Autofill. One vote for of PASSWORD for
934 // the current form, and one vote for ACCOUNT_CREATION_PASSWORD on the
935 // original form since it has more than 2 text input fields and was used for
936 // the first time on a different form.
937 base::HistogramBase
* upload_histogram
=
938 base::StatisticsRecorder::FindHistogram(
939 "PasswordGeneration.UploadStarted");
940 ASSERT_TRUE(upload_histogram
);
941 scoped_ptr
<base::HistogramSamples
> snapshot
=
942 upload_histogram
->SnapshotSamples();
943 EXPECT_EQ(0, snapshot
->GetCount(0 /* failure */));
944 EXPECT_EQ(2, snapshot
->GetCount(1 /* success */));
948 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
, PromptForSubmitFromIframe
) {
949 NavigateToFile("/password/password_submit_from_iframe.html");
951 // Submit a form in an iframe, then cause the whole page to navigate without a
952 // user gesture. We expect the save password prompt to be shown here, because
953 // some pages use such iframes for login forms.
954 NavigationObserver
observer(WebContents());
955 scoped_ptr
<PromptObserver
> prompt_observer(
956 PromptObserver::Create(WebContents()));
957 std::string fill_and_submit
=
958 "var iframe = document.getElementById('test_iframe');"
959 "var iframe_doc = iframe.contentDocument;"
960 "iframe_doc.getElementById('username_field').value = 'temp';"
961 "iframe_doc.getElementById('password_field').value = 'random';"
962 "iframe_doc.getElementById('submit_button').click()";
964 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
966 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
969 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
970 PromptForInputElementWithoutName
) {
971 // Check that the prompt is shown for forms where input elements lack the
972 // "name" attribute but the "id" is present.
973 NavigateToFile("/password/password_form.html");
975 NavigationObserver
observer(WebContents());
976 scoped_ptr
<PromptObserver
> prompt_observer(
977 PromptObserver::Create(WebContents()));
978 std::string fill_and_submit
=
979 "document.getElementById('username_field_no_name').value = 'temp';"
980 "document.getElementById('password_field_no_name').value = 'random';"
981 "document.getElementById('input_submit_button_no_name').click()";
982 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
984 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
987 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
988 PromptForInputElementWithoutId
) {
989 // Check that the prompt is shown for forms where input elements lack the
990 // "id" attribute but the "name" attribute is present.
991 NavigateToFile("/password/password_form.html");
993 NavigationObserver
observer(WebContents());
994 scoped_ptr
<PromptObserver
> prompt_observer(
995 PromptObserver::Create(WebContents()));
996 std::string fill_and_submit
=
997 "document.getElementsByName('username_field_no_id')[0].value = 'temp';"
998 "document.getElementsByName('password_field_no_id')[0].value = 'random';"
999 "document.getElementsByName('input_submit_button_no_id')[0].click()";
1000 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
1002 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
1005 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
1006 NoPromptForInputElementWithoutIdAndName
) {
1007 // Check that no prompt is shown for forms where the input fields lack both
1008 // the "id" and the "name" attributes.
1009 NavigateToFile("/password/password_form.html");
1011 NavigationObserver
observer(WebContents());
1012 scoped_ptr
<PromptObserver
> prompt_observer(
1013 PromptObserver::Create(WebContents()));
1014 std::string fill_and_submit
=
1015 "var form = document.getElementById('testform_elements_no_id_no_name');"
1016 "var username = form.children[0];"
1017 "username.value = 'temp';"
1018 "var password = form.children[1];"
1019 "password.value = 'random';"
1020 "form.children[2].click()"; // form.children[2] is the submit button.
1021 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
1023 EXPECT_FALSE(prompt_observer
->IsShowingPrompt());
1026 // Test for checking that no prompt is shown for URLs with file: scheme.
1027 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
1028 NoPromptForFileSchemeURLs
) {
1029 GURL url
= GetFileURL("password_form.html");
1030 ui_test_utils::NavigateToURL(browser(), url
);
1032 NavigationObserver
observer(WebContents());
1033 scoped_ptr
<PromptObserver
> prompt_observer(
1034 PromptObserver::Create(WebContents()));
1035 std::string fill_and_submit
=
1036 "document.getElementById('username_field').value = 'temp';"
1037 "document.getElementById('password_field').value = 'random';"
1038 "document.getElementById('input_submit_button').click();";
1039 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
1041 EXPECT_FALSE(prompt_observer
->IsShowingPrompt());
1044 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
1045 NoPromptForLandingPageWithHTTPErrorStatusCode
) {
1046 // Check that no prompt is shown for forms where the landing page has
1048 NavigateToFile("/password/password_form.html");
1050 NavigationObserver
observer(WebContents());
1051 scoped_ptr
<PromptObserver
> prompt_observer(
1052 PromptObserver::Create(WebContents()));
1053 std::string fill_and_submit
=
1054 "document.getElementById('username_field_http_error').value = 'temp';"
1055 "document.getElementById('password_field_http_error').value = 'random';"
1056 "document.getElementById('input_submit_button_http_error').click()";
1057 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
1059 EXPECT_FALSE(prompt_observer
->IsShowingPrompt());
1062 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
, DeleteFrameBeforeSubmit
) {
1063 NavigateToFile("/password/multi_frames.html");
1065 NavigationObserver
observer(WebContents());
1066 // Make sure we save some password info from an iframe and then destroy it.
1067 std::string save_and_remove
=
1068 "var first_frame = document.getElementById('first_frame');"
1069 "var frame_doc = first_frame.contentDocument;"
1070 "frame_doc.getElementById('username_field').value = 'temp';"
1071 "frame_doc.getElementById('password_field').value = 'random';"
1072 "frame_doc.getElementById('input_submit_button').click();"
1073 "first_frame.parentNode.removeChild(first_frame);";
1074 // Submit from the main frame, but without navigating through the onsubmit
1076 std::string navigate_frame
=
1077 "document.getElementById('username_field').value = 'temp';"
1078 "document.getElementById('password_field').value = 'random';"
1079 "document.getElementById('input_submit_button').click();"
1080 "window.location.href = 'done.html';";
1082 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), save_and_remove
));
1083 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), navigate_frame
));
1085 // The only thing we check here is that there is no use-after-free reported.
1088 // Disabled on Windows due to flakiness: http://crbug.com/346297
1090 #define MAYBE_PasswordValueAccessible DISABLED_PasswordValueAccessible
1092 #define MAYBE_PasswordValueAccessible PasswordValueAccessible
1094 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
1095 MAYBE_PasswordValueAccessible
) {
1096 NavigateToFile("/password/form_and_link.html");
1098 // Click on a link to open a new tab, then switch back to the first one.
1099 EXPECT_EQ(1, browser()->tab_strip_model()->count());
1101 "document.getElementById('testlink').click();";
1102 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), click
));
1103 EXPECT_EQ(2, browser()->tab_strip_model()->count());
1104 browser()->tab_strip_model()->ActivateTabAt(0, false);
1106 // Fill in the credentials, and make sure they are saved.
1107 NavigationObserver
form_submit_observer(WebContents());
1108 scoped_ptr
<PromptObserver
> prompt_observer(
1109 PromptObserver::Create(WebContents()));
1110 std::string fill_and_submit
=
1111 "document.getElementById('username_field').value = 'temp';"
1112 "document.getElementById('password_field').value = 'random';"
1113 "document.getElementById('input_submit_button').click();";
1114 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
1115 form_submit_observer
.Wait();
1116 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
1117 prompt_observer
->Accept();
1119 // Reload the original page to have the saved credentials autofilled.
1120 NavigationObserver
reload_observer(WebContents());
1121 NavigateToFile("/password/form_and_link.html");
1122 reload_observer
.Wait();
1124 // Wait until the username is filled, to make sure autofill kicked in.
1125 WaitForElementValue("username_field", "temp");
1126 // Now check that the password is not accessible yet.
1127 CheckElementValue("password_field", "");
1128 // Let the user interact with the page.
1129 content::SimulateMouseClickAt(
1130 WebContents(), 0, blink::WebMouseEvent::ButtonLeft
, gfx::Point(1, 1));
1131 // Wait until that interaction causes the password value to be revealed.
1132 WaitForElementValue("password_field", "random");
1133 // And check that after the side-effects of the interaction took place, the
1134 // username value stays the same.
1135 CheckElementValue("username_field", "temp");
1138 // The following test is limited to Aura, because
1139 // RenderWidgetHostViewGuest::ProcessAckedTouchEvent is, and
1140 // ProcessAckedTouchEvent is what triggers the translation of touch events to
1142 // Disabled: http://crbug.com/346297
1143 #if defined(USE_AURA)
1144 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
1145 DISABLED_PasswordValueAccessibleOnSubmit
) {
1146 NavigateToFile("/password/form_and_link.html");
1148 // Fill in the credentials, and make sure they are saved.
1149 NavigationObserver
form_submit_observer(WebContents());
1150 scoped_ptr
<PromptObserver
> prompt_observer(
1151 PromptObserver::Create(WebContents()));
1152 std::string fill_and_submit
=
1153 "document.getElementById('username_field').value = 'temp';"
1154 "document.getElementById('password_field').value = 'random_secret';"
1155 "document.getElementById('input_submit_button').click();";
1156 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
1157 form_submit_observer
.Wait();
1158 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
1159 prompt_observer
->Accept();
1161 // Reload the original page to have the saved credentials autofilled.
1162 NavigationObserver
reload_observer(WebContents());
1163 NavigateToFile("/password/form_and_link.html");
1164 reload_observer
.Wait();
1166 NavigationObserver
submit_observer(WebContents());
1167 // Submit the form via a tap on the submit button. The button is placed at 0,
1168 // 100, and has height 300 and width 700.
1169 content::SimulateTapAt(WebContents(), gfx::Point(350, 250));
1170 submit_observer
.Wait();
1171 std::string query
= WebContents()->GetURL().query();
1172 EXPECT_NE(std::string::npos
, query
.find("random_secret")) << query
;
1176 // Test fix for crbug.com/338650.
1177 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
1178 DontPromptForPasswordFormWithDefaultValue
) {
1179 NavigateToFile("/password/password_form_with_default_value.html");
1181 // Don't prompt if we navigate away even if there is a password value since
1182 // it's not coming from the user.
1183 NavigationObserver
observer(WebContents());
1184 scoped_ptr
<PromptObserver
> prompt_observer(
1185 PromptObserver::Create(WebContents()));
1186 NavigateToFile("/password/done.html");
1188 EXPECT_FALSE(prompt_observer
->IsShowingPrompt());
1191 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
1192 DontPromptForPasswordFormWithReadonlyPasswordField
) {
1193 NavigateToFile("/password/password_form_with_password_readonly.html");
1195 // Fill a form and submit through a <input type="submit"> button. Nothing
1197 NavigationObserver
observer(WebContents());
1198 scoped_ptr
<PromptObserver
> prompt_observer(
1199 PromptObserver::Create(WebContents()));
1200 std::string fill_and_submit
=
1201 "document.getElementById('username_field').value = 'temp';"
1202 "document.getElementById('password_field').value = 'random';"
1203 "document.getElementById('input_submit_button').click()";
1204 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
1206 EXPECT_FALSE(prompt_observer
->IsShowingPrompt());
1209 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
1210 PromptWhenEnableAutomaticPasswordSavingSwitchIsNotSet
) {
1211 NavigateToFile("/password/password_form.html");
1213 // Fill a form and submit through a <input type="submit"> button.
1214 NavigationObserver
observer(WebContents());
1215 scoped_ptr
<PromptObserver
> prompt_observer(
1216 PromptObserver::Create(WebContents()));
1217 std::string fill_and_submit
=
1218 "document.getElementById('username_field').value = 'temp';"
1219 "document.getElementById('password_field').value = 'random';"
1220 "document.getElementById('input_submit_button').click()";
1221 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
1223 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
1226 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
1227 DontPromptWhenEnableAutomaticPasswordSavingSwitchIsSet
) {
1228 password_manager::TestPasswordStore
* password_store
=
1229 static_cast<password_manager::TestPasswordStore
*>(
1230 PasswordStoreFactory::GetForProfile(
1231 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS
).get());
1233 EXPECT_TRUE(password_store
->IsEmpty());
1235 NavigateToFile("/password/password_form.html");
1237 // Add the enable-automatic-password-saving switch.
1238 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1239 password_manager::switches::kEnableAutomaticPasswordSaving
);
1241 // Fill a form and submit through a <input type="submit"> button.
1242 NavigationObserver
observer(WebContents());
1243 scoped_ptr
<PromptObserver
> prompt_observer(
1244 PromptObserver::Create(WebContents()));
1245 // Make sure that the only passwords saved are the auto-saved ones.
1246 std::string fill_and_submit
=
1247 "document.getElementById('username_field').value = 'temp';"
1248 "document.getElementById('password_field').value = 'random';"
1249 "document.getElementById('input_submit_button').click()";
1250 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
1252 if (chrome::VersionInfo::GetChannel() ==
1253 chrome::VersionInfo::CHANNEL_UNKNOWN
) {
1254 // Passwords getting auto-saved, no prompt.
1255 EXPECT_FALSE(prompt_observer
->IsShowingPrompt());
1256 EXPECT_FALSE(password_store
->IsEmpty());
1258 // Prompt shown, and no passwords saved automatically.
1259 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
1260 EXPECT_TRUE(password_store
->IsEmpty());
1264 // Test fix for crbug.com/368690.
1265 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
, NoPromptWhenReloading
) {
1266 NavigateToFile("/password/password_form.html");
1269 "document.getElementById('username_redirect').value = 'temp';"
1270 "document.getElementById('password_redirect').value = 'random';";
1271 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill
));
1273 NavigationObserver
observer(WebContents());
1274 scoped_ptr
<PromptObserver
> prompt_observer(
1275 PromptObserver::Create(WebContents()));
1276 GURL url
= embedded_test_server()->GetURL("/password/password_form.html");
1277 chrome::NavigateParams
params(browser(), url
,
1278 ui::PAGE_TRANSITION_RELOAD
);
1279 ui_test_utils::NavigateToURL(¶ms
);
1281 EXPECT_FALSE(prompt_observer
->IsShowingPrompt());
1284 // Test that if a form gets dynamically added between the form parsing and
1285 // rendering, and while the main frame still loads, it still is registered, and
1286 // thus saving passwords from it works.
1287 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
1288 FormsAddedBetweenParsingAndRendering
) {
1289 NavigateToFile("/password/between_parsing_and_rendering.html");
1291 NavigationObserver
observer(WebContents());
1292 scoped_ptr
<PromptObserver
> prompt_observer(
1293 PromptObserver::Create(WebContents()));
1294 std::string submit
=
1295 "document.getElementById('username').value = 'temp';"
1296 "document.getElementById('password').value = 'random';"
1297 "document.getElementById('submit-button').click();";
1298 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit
));
1301 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
1304 // Test that if there was no previous page load then the PasswordManagerDriver
1305 // does not think that there were SSL errors on the current page. The test opens
1306 // a new tab with a URL for which the embedded test server issues a basic auth
1308 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
, NoLastLoadGoodLastLoad
) {
1309 // Teach the embedded server to handle requests by issuing the basic auth
1311 embedded_test_server()->RegisterRequestHandler(
1312 base::Bind(&HandleTestAuthRequest
));
1314 LoginPromptBrowserTestObserver login_observer
;
1315 // We need to register to all sources, because the navigation observer we are
1316 // interested in is for a new tab to be opened, and thus does not exist yet.
1317 login_observer
.Register(content::NotificationService::AllSources());
1319 password_manager::TestPasswordStore
* password_store
=
1320 static_cast<password_manager::TestPasswordStore
*>(
1321 PasswordStoreFactory::GetForProfile(
1322 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS
).get());
1323 EXPECT_TRUE(password_store
->IsEmpty());
1325 // Navigate to a page requiring HTTP auth. Wait for the tab to get the correct
1326 // WebContents, but don't wait for navigation, which only finishes after
1328 ui_test_utils::NavigateToURLWithDisposition(
1330 embedded_test_server()->GetURL("/basic_auth"),
1332 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB
);
1334 content::NavigationController
* nav_controller
=
1335 &WebContents()->GetController();
1336 NavigationObserver
nav_observer(WebContents());
1337 scoped_ptr
<PromptObserver
> prompt_observer(
1338 PromptObserver::Create(WebContents()));
1339 WindowedAuthNeededObserver
auth_needed_observer(nav_controller
);
1340 auth_needed_observer
.Wait();
1342 WindowedAuthSuppliedObserver
auth_supplied_observer(nav_controller
);
1343 // Offer valid credentials on the auth challenge.
1344 ASSERT_EQ(1u, login_observer
.handlers().size());
1345 LoginHandler
* handler
= *login_observer
.handlers().begin();
1346 ASSERT_TRUE(handler
);
1347 // Any username/password will work.
1348 handler
->SetAuth(base::UTF8ToUTF16("user"), base::UTF8ToUTF16("pwd"));
1349 auth_supplied_observer
.Wait();
1351 // The password manager should be working correctly.
1352 nav_observer
.Wait();
1353 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
1354 prompt_observer
->Accept();
1356 // Spin the message loop to make sure the password store had a chance to save
1358 base::RunLoop run_loop
;
1359 run_loop
.RunUntilIdle();
1360 EXPECT_FALSE(password_store
->IsEmpty());
1363 // In some situations, multiple PasswordFormManager instances from
1364 // PasswordManager::pending_login_managers_ would match (via DoesManage) a form
1365 // to be provisionally saved. One of them might be a complete match, the other
1366 // all-but-action match. Normally, the former should be preferred, but if the
1367 // former has not finished matching, and the latter has, the latter should be
1368 // used (otherwise we'd give up even though we could have saved the password).
1369 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
1370 PreferPasswordFormManagerWhichFinishedMatching
) {
1371 NavigateToFile("/password/create_form_copy_on_submit.html");
1373 NavigationObserver
observer(WebContents());
1374 scoped_ptr
<PromptObserver
> prompt_observer(
1375 PromptObserver::Create(WebContents()));
1376 std::string submit
=
1377 "document.getElementById('username').value = 'overwrite_me';"
1378 "document.getElementById('password').value = 'random';"
1379 "document.getElementById('non-form-button').click();";
1380 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit
));
1383 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
1386 // Test that if login fails and content server pushes a different login form
1387 // with action URL having different schemes. Heuristic shall be able
1388 // identify such cases and *shall not* prompt to save incorrect password.
1389 IN_PROC_BROWSER_TEST_F(
1390 PasswordManagerBrowserTest
,
1391 NoPromptForLoginFailedAndServerPushSeperateLoginForm_HttpToHttps
) {
1393 "/password/separate_login_form_with_onload_submit_script.html";
1394 GURL
http_url(embedded_test_server()->GetURL(path
));
1395 ASSERT_TRUE(http_url
.SchemeIs(url::kHttpScheme
));
1397 NavigationObserver
observer(WebContents());
1398 scoped_ptr
<PromptObserver
> prompt_observer(
1399 PromptObserver::Create(WebContents()));
1400 ui_test_utils::NavigateToURL(browser(), http_url
);
1402 observer
.SetPathToWaitFor("/password/done_and_separate_login_form.html");
1405 EXPECT_FALSE(prompt_observer
->IsShowingPrompt());
1408 IN_PROC_BROWSER_TEST_F(
1409 PasswordManagerBrowserTest
,
1410 NoPromptForLoginFailedAndServerPushSeperateLoginForm_HttpsToHttp
) {
1411 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1412 switches::kAllowRunningInsecureContent
);
1413 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1414 switches::kIgnoreCertificateErrors
);
1415 const base::FilePath::CharType kDocRoot
[] =
1416 FILE_PATH_LITERAL("chrome/test/data");
1417 net::SpawnedTestServer
https_test_server(
1418 net::SpawnedTestServer::TYPE_HTTPS
,
1419 net::SpawnedTestServer::SSLOptions(
1420 net::SpawnedTestServer::SSLOptions::CERT_OK
),
1421 base::FilePath(kDocRoot
));
1422 ASSERT_TRUE(https_test_server
.Start());
1424 // This test case cannot inject the scripts via content::ExecuteScript() in
1425 // files served through HTTPS. Therefore the scripts are made part of the HTML
1426 // site and executed on load.
1428 "password/separate_login_form_with_onload_submit_script.html";
1429 GURL
https_url(https_test_server
.GetURL(path
));
1430 ASSERT_TRUE(https_url
.SchemeIs(url::kHttpsScheme
));
1432 NavigationObserver
observer(WebContents());
1433 scoped_ptr
<PromptObserver
> prompt_observer(
1434 PromptObserver::Create(WebContents()));
1435 ui_test_utils::NavigateToURL(browser(), https_url
);
1437 observer
.SetPathToWaitFor("/password/done_and_separate_login_form.html");
1440 EXPECT_FALSE(prompt_observer
->IsShowingPrompt());
1443 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
1444 PromptWhenPasswordFormWithoutUsernameFieldSubmitted
) {
1445 password_manager::TestPasswordStore
* password_store
=
1446 static_cast<password_manager::TestPasswordStore
*>(
1447 PasswordStoreFactory::GetForProfile(
1448 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS
).get());
1450 EXPECT_TRUE(password_store
->IsEmpty());
1452 NavigateToFile("/password/form_with_only_password_field.html");
1454 NavigationObserver
observer(WebContents());
1455 scoped_ptr
<PromptObserver
> prompt_observer(
1456 PromptObserver::Create(WebContents()));
1457 std::string submit
=
1458 "document.getElementById('password').value = 'password';"
1459 "document.getElementById('submit-button').click();";
1460 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit
));
1463 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
1464 prompt_observer
->Accept();
1466 // Spin the message loop to make sure the password store had a chance to save
1468 base::RunLoop run_loop
;
1469 run_loop
.RunUntilIdle();
1470 EXPECT_FALSE(password_store
->IsEmpty());
1473 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
1474 AutofillSuggetionsForPasswordFormWithoutUsernameField
) {
1475 password_manager::TestPasswordStore
* password_store
=
1476 static_cast<password_manager::TestPasswordStore
*>(
1477 PasswordStoreFactory::GetForProfile(
1478 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS
).get());
1480 EXPECT_TRUE(password_store
->IsEmpty());
1482 // Password form without username-field.
1483 NavigateToFile("/password/form_with_only_password_field.html");
1485 NavigationObserver
observer(WebContents());
1486 scoped_ptr
<PromptObserver
> prompt_observer(
1487 PromptObserver::Create(WebContents()));
1488 std::string submit
=
1489 "document.getElementById('password').value = 'mypassword';"
1490 "document.getElementById('submit-button').click();";
1491 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit
));
1494 prompt_observer
->Accept();
1496 // Spin the message loop to make sure the password store had a chance to save
1498 base::RunLoop run_loop
;
1499 run_loop
.RunUntilIdle();
1500 EXPECT_FALSE(password_store
->IsEmpty());
1502 // Now, navigate to same html password form and verify whether password is
1504 NavigateToFile("/password/form_with_only_password_field.html");
1506 // Let the user interact with the page, so that DOM gets modification events,
1507 // needed for autofilling fields.
1508 content::SimulateMouseClickAt(
1509 WebContents(), 0, blink::WebMouseEvent::ButtonLeft
, gfx::Point(1, 1));
1511 // Wait until that interaction causes the password value to be revealed.
1512 WaitForElementValue("password", "mypassword");
1515 // Test that if a form gets autofilled, then it gets autofilled on re-creation
1517 // TODO(vabr): This is flaky everywhere. http://crbug.com/442704
1518 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
1519 DISABLED_ReCreatedFormsGetFilled
) {
1520 NavigateToFile("/password/dynamic_password_form.html");
1522 // Fill in the credentials, and make sure they are saved.
1523 NavigationObserver
form_submit_observer(WebContents());
1524 scoped_ptr
<PromptObserver
> prompt_observer(
1525 PromptObserver::Create(WebContents()));
1526 std::string create_fill_and_submit
=
1527 "document.getElementById('create_form_button').click();"
1528 "window.setTimeout(function() {"
1529 " var form = document.getElementById('dynamic_form_id');"
1530 " form.username.value = 'temp';"
1531 " form.password.value = 'random';"
1534 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), create_fill_and_submit
));
1535 form_submit_observer
.Wait();
1536 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
1537 prompt_observer
->Accept();
1539 // Reload the original page to have the saved credentials autofilled.
1540 NavigationObserver
reload_observer(WebContents());
1541 NavigateToFile("/password/dynamic_password_form.html");
1542 reload_observer
.Wait();
1543 std::string create_form
=
1544 "document.getElementById('create_form_button').click();";
1545 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), create_form
));
1546 // Wait until the username is filled, to make sure autofill kicked in.
1547 WaitForElementValue("username_id", "temp");
1549 // Now the form gets deleted and created again. It should get autofilled
1551 std::string delete_form
=
1552 "var form = document.getElementById('dynamic_form_id');"
1553 "form.parentNode.removeChild(form);";
1554 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), delete_form
));
1555 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), create_form
));
1556 WaitForElementValue("username_id", "temp");
1559 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
, PromptForPushState
) {
1560 ActivateHistoryPushState();
1561 NavigateToFile("/password/password_push_state.html");
1563 // Verify that we show the save password prompt if 'history.pushState()'
1564 // is called after form submission is suppressed by, for example, calling
1565 // preventDefault in a form's submit event handler.
1566 // Note that calling 'submit()' on a form with javascript doesn't call
1567 // the onsubmit handler, so we click the submit button instead.
1568 NavigationObserver
observer(WebContents());
1569 observer
.SetQuitOnEntryCommitted(true);
1570 scoped_ptr
<PromptObserver
> prompt_observer(
1571 PromptObserver::Create(WebContents()));
1572 std::string fill_and_submit
=
1573 "document.getElementById('username_field').value = 'temp';"
1574 "document.getElementById('password_field').value = 'random';"
1575 "document.getElementById('submit_button').click()";
1576 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
1578 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
1581 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
1582 InFrameNavigationDoesNotClearPopupState
) {
1583 // Mock out the AutofillClient so we know how long to wait. Unfortunately
1584 // there isn't otherwise a good even to wait on to verify that the popup
1585 // would have been shown.
1586 password_manager::ContentPasswordManagerDriverFactory
* driver_factory
=
1587 password_manager::ContentPasswordManagerDriverFactory::FromWebContents(
1589 ObservingAutofillClient observing_autofill_client
;
1590 driver_factory
->TestingSetDriverForFrame(
1591 RenderViewHost()->GetMainFrame(),
1592 make_scoped_ptr(new password_manager::ContentPasswordManagerDriver(
1593 RenderViewHost()->GetMainFrame(),
1594 ChromePasswordManagerClient::FromWebContents(WebContents()),
1595 &observing_autofill_client
)));
1597 NavigateToFile("/password/password_form.html");
1599 NavigationObserver
form_submit_observer(WebContents());
1600 scoped_ptr
<PromptObserver
> prompt_observer(
1601 PromptObserver::Create(WebContents()));
1603 "document.getElementById('username_field').value = 'temp';"
1604 "document.getElementById('password_field').value = 'random123';"
1605 "document.getElementById('input_submit_button').click();";
1607 // Save credentials for the site.
1608 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill
));
1609 form_submit_observer
.Wait();
1610 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
1611 prompt_observer
->Accept();
1613 NavigateToFile("/password/password_form.html");
1614 ASSERT_TRUE(content::ExecuteScript(
1616 "var usernameRect = document.getElementById('username_field')"
1617 ".getBoundingClientRect();"));
1619 // Trigger in page navigation.
1620 std::string in_page_navigate
= "location.hash = '#blah';";
1621 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), in_page_navigate
));
1623 // Click on the username field to display the popup.
1625 ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
1627 "window.domAutomationController.send(usernameRect.top);",
1630 ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
1632 "window.domAutomationController.send(usernameRect.left);",
1635 content::SimulateMouseClickAt(
1636 WebContents(), 0, blink::WebMouseEvent::ButtonLeft
, gfx::Point(left
+ 1,
1638 // Make sure the popup would be shown.
1639 observing_autofill_client
.Wait();
1642 // Passwords from change password forms should only be offered for saving when
1643 // it is certain that the username is correct.
1644 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
, ChangePwdCorrect
) {
1645 NavigateToFile("/password/password_form.html");
1647 NavigationObserver
observer(WebContents());
1648 scoped_ptr
<PromptObserver
> prompt_observer(
1649 PromptObserver::Create(WebContents()));
1650 std::string fill_and_submit
=
1651 "document.getElementById('mark_chg_username_field').value = 'temp';"
1652 "document.getElementById('mark_chg_password_field').value = 'random';"
1653 "document.getElementById('mark_chg_new_password_1').value = 'random1';"
1654 "document.getElementById('mark_chg_new_password_2').value = 'random1';"
1655 "document.getElementById('mark_chg_submit_button').click()";
1656 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
1658 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
1661 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
, ChangePwdIncorrect
) {
1662 NavigateToFile("/password/password_form.html");
1664 NavigationObserver
observer(WebContents());
1665 scoped_ptr
<PromptObserver
> prompt_observer(
1666 PromptObserver::Create(WebContents()));
1667 std::string fill_and_submit
=
1668 "document.getElementById('chg_not_username_field').value = 'temp';"
1669 "document.getElementById('chg_password_field').value = 'random';"
1670 "document.getElementById('chg_new_password_1').value = 'random1';"
1671 "document.getElementById('chg_new_password_2').value = 'random1';"
1672 "document.getElementById('chg_submit_button').click()";
1673 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
1675 EXPECT_FALSE(prompt_observer
->IsShowingPrompt());
1678 // As the two ChangePwd* tests above, only with submitting through
1679 // history.pushState().
1680 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
, ChangePwdPushStateCorrect
) {
1681 ActivateHistoryPushState();
1682 NavigateToFile("/password/password_push_state.html");
1684 NavigationObserver
observer(WebContents());
1685 observer
.SetQuitOnEntryCommitted(true);
1686 scoped_ptr
<PromptObserver
> prompt_observer(
1687 PromptObserver::Create(WebContents()));
1688 std::string fill_and_submit
=
1689 "document.getElementById('mark_chg_username_field').value = 'temp';"
1690 "document.getElementById('mark_chg_password_field').value = 'random';"
1691 "document.getElementById('mark_chg_new_password_1').value = 'random1';"
1692 "document.getElementById('mark_chg_new_password_2').value = 'random1';"
1693 "document.getElementById('mark_chg_submit_button').click()";
1694 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
1696 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
1699 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
1700 ChangePwdPushStateIncorrect
) {
1701 ActivateHistoryPushState();
1702 NavigateToFile("/password/password_push_state.html");
1704 NavigationObserver
observer(WebContents());
1705 observer
.SetQuitOnEntryCommitted(true);
1706 scoped_ptr
<PromptObserver
> prompt_observer(
1707 PromptObserver::Create(WebContents()));
1708 std::string fill_and_submit
=
1709 "document.getElementById('chg_not_username_field').value = 'temp';"
1710 "document.getElementById('chg_password_field').value = 'random';"
1711 "document.getElementById('chg_new_password_1').value = 'random1';"
1712 "document.getElementById('chg_new_password_2').value = 'random1';"
1713 "document.getElementById('chg_submit_button').click()";
1714 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
1716 EXPECT_FALSE(prompt_observer
->IsShowingPrompt());
1719 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
, NoPromptOnBack
) {
1720 // Go to a successful landing page through submitting first, so that it is
1721 // reachable through going back, and the remembered page transition is form
1722 // submit. There is no need to submit non-empty strings.
1723 NavigateToFile("/password/password_form.html");
1725 NavigationObserver
dummy_submit_observer(WebContents());
1726 std::string just_submit
=
1727 "document.getElementById('input_submit_button').click()";
1728 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), just_submit
));
1729 dummy_submit_observer
.Wait();
1731 // Now go to a page with a form again, fill the form, and go back instead of
1733 NavigateToFile("/password/dummy_submit.html");
1735 NavigationObserver
observer(WebContents());
1736 scoped_ptr
<PromptObserver
> prompt_observer(
1737 PromptObserver::Create(WebContents()));
1738 // The (dummy) submit is necessary to provisionally save the typed password. A
1739 // user typing in the password field would not need to submit to provisionally
1740 // save it, but the script cannot trigger that just by assigning to the
1742 std::string fill_and_back
=
1743 "document.getElementById('password_field').value = 'random';"
1744 "document.getElementById('input_submit_button').click();"
1745 "window.history.back();";
1746 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_back
));
1748 EXPECT_FALSE(prompt_observer
->IsShowingPrompt());
1751 // Regression test for http://crbug.com/452306
1752 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
1753 ChangingTextToPasswordFieldOnSignupForm
) {
1754 NavigateToFile("/password/signup_form.html");
1756 // In this case, pretend that username_field is actually a password field
1757 // that starts as a text field to simulate placeholder.
1758 NavigationObserver
observer(WebContents());
1759 scoped_ptr
<PromptObserver
> prompt_observer(
1760 PromptObserver::Create(WebContents()));
1761 std::string change_and_submit
=
1762 "document.getElementById('other_info').value = 'username';"
1763 "document.getElementById('username_field').type = 'password';"
1764 "document.getElementById('username_field').value = 'mypass';"
1765 "document.getElementById('password_field').value = 'mypass';"
1766 "document.getElementById('testform').submit();";
1767 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), change_and_submit
));
1769 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
1772 // Regression test for http://crbug.com/451631
1773 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
1774 SavingOnManyPasswordFieldsTest
) {
1775 // Simulate Macy's registration page, which contains the normal 2 password
1776 // fields for confirming the new password plus 2 more fields for security
1777 // questions and credit card. Make sure that saving works correctly for such
1779 NavigateToFile("/password/many_password_signup_form.html");
1781 NavigationObserver
observer(WebContents());
1782 scoped_ptr
<PromptObserver
> prompt_observer(
1783 PromptObserver::Create(WebContents()));
1784 std::string fill_and_submit
=
1785 "document.getElementById('username_field').value = 'username';"
1786 "document.getElementById('password_field').value = 'mypass';"
1787 "document.getElementById('confirm_field').value = 'mypass';"
1788 "document.getElementById('security_answer').value = 'hometown';"
1789 "document.getElementById('SSN').value = '1234';"
1790 "document.getElementById('testform').submit();";
1791 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
1793 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
1796 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
1797 SaveWhenIFrameDestroyedOnFormSubmit
) {
1798 NavigateToFile("/password/frame_detached_on_submit.html");
1800 // Need to pay attention for a message that XHR has finished since there
1801 // is no navigation to wait for.
1802 content::DOMMessageQueue message_queue
;
1804 scoped_ptr
<PromptObserver
> prompt_observer(
1805 PromptObserver::Create(WebContents()));
1806 std::string fill_and_submit
=
1807 "var iframe = document.getElementById('login_iframe');"
1808 "var frame_doc = iframe.contentDocument;"
1809 "frame_doc.getElementById('username_field').value = 'temp';"
1810 "frame_doc.getElementById('password_field').value = 'random';"
1811 "frame_doc.getElementById('submit_button').click();";
1813 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit
));
1814 std::string message
;
1815 while (message_queue
.WaitForMessage(&message
)) {
1816 if (message
== "\"SUBMISSION_FINISHED\"")
1820 EXPECT_TRUE(prompt_observer
->IsShowingPrompt());
1823 // Tests that if a site embeds the login and signup forms into one <form>, the
1824 // login form still gets autofilled.
1825 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
,
1826 AutofillSuggetionsForLoginSignupForm
) {
1827 password_manager::TestPasswordStore
* password_store
=
1828 static_cast<password_manager::TestPasswordStore
*>(
1829 PasswordStoreFactory::GetForProfile(
1830 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS
).get());
1832 EXPECT_TRUE(password_store
->IsEmpty());
1834 NavigateToFile("/password/login_signup_form.html");
1836 NavigationObserver
observer(WebContents());
1837 scoped_ptr
<PromptObserver
> prompt_observer(
1838 PromptObserver::Create(WebContents()));
1839 std::string submit
=
1840 "document.getElementById('username').value = 'myusername';"
1841 "document.getElementById('password').value = 'mypassword';"
1842 "document.getElementById('submit').click();";
1843 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit
));
1846 prompt_observer
->Accept();
1848 // Spin the message loop to make sure the password store had a chance to save
1850 base::RunLoop run_loop
;
1851 run_loop
.RunUntilIdle();
1852 EXPECT_FALSE(password_store
->IsEmpty());
1854 // Now, navigate to the same html password form and verify whether password is
1856 NavigateToFile("/password/login_signup_form.html");
1858 // Let the user interact with the page, so that DOM gets modification events,
1859 // needed for autofilling fields.
1860 content::SimulateMouseClickAt(
1861 WebContents(), 0, blink::WebMouseEvent::ButtonLeft
, gfx::Point(1, 1));
1863 // Wait until that interaction causes the password value to be revealed.
1864 WaitForElementValue("password", "mypassword");
1867 // Check that we can fill in cases where <base href> is set and the action of
1868 // the form is not set. Regression test for https://crbug.com/360230.
1869 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest
, BaseTagWithNoActionTest
) {
1870 password_manager::TestPasswordStore
* password_store
=
1871 static_cast<password_manager::TestPasswordStore
*>(
1872 PasswordStoreFactory::GetForProfile(
1873 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS
).get());
1875 EXPECT_TRUE(password_store
->IsEmpty());
1877 NavigateToFile("/password/password_xhr_submit.html");
1879 NavigationObserver
observer(WebContents());
1880 scoped_ptr
<PromptObserver
> prompt_observer(
1881 PromptObserver::Create(WebContents()));
1882 std::string submit
=
1883 "document.getElementById('username_field').value = 'myusername';"
1884 "document.getElementById('password_field').value = 'mypassword';"
1885 "document.getElementById('submit_button').click();";
1886 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit
));
1889 prompt_observer
->Accept();
1891 // Spin the message loop to make sure the password store had a chance to save
1893 base::RunLoop run_loop
;
1894 run_loop
.RunUntilIdle();
1895 EXPECT_FALSE(password_store
->IsEmpty());
1897 NavigateToFile("/password/password_xhr_submit.html");
1899 // Let the user interact with the page, so that DOM gets modification events,
1900 // needed for autofilling fields.
1901 content::SimulateMouseClickAt(
1902 WebContents(), 0, blink::WebMouseEvent::ButtonLeft
, gfx::Point(1, 1));
1904 // Wait until that interaction causes the password value to be revealed.
1905 WaitForElementValue("password_field", "mypassword");