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 "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/infobars/confirm_infobar_delegate.h"
12 #include "chrome/browser/infobars/infobar_service.h"
13 #include "chrome/browser/password_manager/password_store_factory.h"
14 #include "chrome/browser/password_manager/test_password_store_service.h"
15 #include "chrome/browser/ui/browser.h"
16 #include "chrome/browser/ui/tabs/tab_strip_model.h"
17 #include "chrome/common/chrome_version_info.h"
18 #include "chrome/test/base/in_process_browser_test.h"
19 #include "chrome/test/base/test_switches.h"
20 #include "chrome/test/base/ui_test_utils.h"
21 #include "components/autofill/core/browser/autofill_test_utils.h"
22 #include "components/infobars/core/infobar.h"
23 #include "components/infobars/core/infobar_manager.h"
24 #include "components/password_manager/core/browser/test_password_store.h"
25 #include "components/password_manager/core/common/password_manager_switches.h"
26 #include "content/public/browser/render_view_host.h"
27 #include "content/public/browser/web_contents.h"
28 #include "content/public/browser/web_contents_observer.h"
29 #include "content/public/test/browser_test_utils.h"
30 #include "content/public/test/test_utils.h"
31 #include "net/test/embedded_test_server/embedded_test_server.h"
32 #include "net/url_request/test_url_fetcher_factory.h"
33 #include "testing/gmock/include/gmock/gmock.h"
34 #include "third_party/WebKit/public/web/WebInputEvent.h"
35 #include "ui/events/keycodes/keyboard_codes.h"
38 // NavigationObserver ---------------------------------------------------------
42 // Observer that waits for navigation to complete and for the password infobar
44 class NavigationObserver : public content::WebContentsObserver,
45 public infobars::InfoBarManager::Observer {
47 explicit NavigationObserver(content::WebContents* web_contents)
48 : content::WebContentsObserver(web_contents),
49 message_loop_runner_(new content::MessageLoopRunner),
50 infobar_shown_(false),
51 infobar_removed_(false),
52 should_automatically_accept_infobar_(true),
53 infobar_service_(InfoBarService::FromWebContents(web_contents)) {
54 infobar_service_->AddObserver(this);
57 virtual ~NavigationObserver() {
59 infobar_service_->RemoveObserver(this);
62 // Normally Wait() will not return until a main frame navigation occurs.
63 // If a path is set, Wait() will return after this path has been seen,
64 // regardless of the frame that navigated. Useful for multi-frame pages.
65 void SetPathToWaitFor(const std::string& path) {
66 wait_for_path_ = path;
69 // content::WebContentsObserver:
70 virtual void DidFinishLoad(
72 const GURL& validated_url,
74 content::RenderViewHost* render_view_host) OVERRIDE {
75 if (!wait_for_path_.empty()) {
76 if (validated_url.path() == wait_for_path_)
77 message_loop_runner_->Quit();
78 } else if (is_main_frame) {
79 message_loop_runner_->Quit();
83 bool infobar_shown() const { return infobar_shown_; }
84 bool infobar_removed() const { return infobar_removed_; }
86 void disable_should_automatically_accept_infobar() {
87 should_automatically_accept_infobar_ = false;
91 message_loop_runner_->Run();
95 // infobars::InfoBarManager::Observer:
96 virtual void OnInfoBarAdded(infobars::InfoBar* infobar) OVERRIDE {
97 if (should_automatically_accept_infobar_) {
98 infobar_service_->infobar_at(0)->delegate()->
99 AsConfirmInfoBarDelegate()->Accept();
101 infobar_shown_ = true;
104 virtual void OnInfoBarRemoved(infobars::InfoBar* infobar,
105 bool animate) OVERRIDE {
106 infobar_removed_ = true;
109 virtual void OnManagerShuttingDown(
110 infobars::InfoBarManager* manager) OVERRIDE {
111 ASSERT_EQ(infobar_service_, manager);
112 infobar_service_->RemoveObserver(this);
113 infobar_service_ = NULL;
116 std::string wait_for_path_;
117 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
119 bool infobar_removed_;
120 // If |should_automatically_accept_infobar_| is true, then whenever the test
121 // sees an infobar added, it will click its accepting button. Default = true.
122 bool should_automatically_accept_infobar_;
123 InfoBarService* infobar_service_;
125 DISALLOW_COPY_AND_ASSIGN(NavigationObserver);
131 // PasswordManagerBrowserTest -------------------------------------------------
133 class PasswordManagerBrowserTest : public InProcessBrowserTest {
135 PasswordManagerBrowserTest() {}
136 virtual ~PasswordManagerBrowserTest() {}
138 // InProcessBrowserTest:
139 virtual void SetUpOnMainThread() OVERRIDE {
140 // Use TestPasswordStore to remove a possible race. Normally the
141 // PasswordStore does its database manipulation on the DB thread, which
142 // creates a possible race during navigation. Specifically the
143 // PasswordManager will ignore any forms in a page if the load from the
144 // PasswordStore has not completed.
145 PasswordStoreFactory::GetInstance()->SetTestingFactory(
146 browser()->profile(), TestPasswordStoreService::Build);
150 content::WebContents* WebContents() {
151 return browser()->tab_strip_model()->GetActiveWebContents();
154 content::RenderViewHost* RenderViewHost() {
155 return WebContents()->GetRenderViewHost();
158 // Wrapper around ui_test_utils::NavigateToURL that waits until
159 // DidFinishLoad() fires. Normally this function returns after
160 // DidStopLoading(), which caused flakiness as the NavigationObserver
161 // would sometimes see the DidFinishLoad event from a previous navigation and
162 // return immediately.
163 void NavigateToFile(const std::string& path) {
164 if (!embedded_test_server()->Started())
165 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
167 ASSERT_FALSE(CommandLine::ForCurrentProcess()->HasSwitch(
168 password_manager::switches::kEnableAutomaticPasswordSaving));
169 NavigationObserver observer(WebContents());
170 GURL url = embedded_test_server()->GetURL(path);
171 ui_test_utils::NavigateToURL(browser(), url);
175 // Executes |script| and uses the EXPECT macros to check the return value
176 // against |expected_return_value|.
177 void CheckScriptReturnValue(std::string& script, bool expected_return_value);
180 DISALLOW_COPY_AND_ASSIGN(PasswordManagerBrowserTest);
183 void PasswordManagerBrowserTest::CheckScriptReturnValue(
185 bool expected_return_value) {
186 const std::string wrapped_script =
187 std::string("window.domAutomationController.send(") + script + ");";
188 bool return_value = !expected_return_value;
189 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
190 RenderViewHost(), wrapped_script, &return_value));
191 EXPECT_EQ(expected_return_value, return_value) << "script = " << script;
194 // Actual tests ---------------------------------------------------------------
195 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
196 PromptForNormalSubmit) {
197 NavigateToFile("/password/password_form.html");
199 // Fill a form and submit through a <input type="submit"> button. Nothing
201 NavigationObserver observer(WebContents());
202 std::string fill_and_submit =
203 "document.getElementById('username_field').value = 'temp';"
204 "document.getElementById('password_field').value = 'random';"
205 "document.getElementById('input_submit_button').click()";
206 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
208 EXPECT_TRUE(observer.infobar_shown());
211 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
212 PromptForSubmitWithInPageNavigation) {
213 NavigateToFile("/password/password_navigate_before_submit.html");
215 // Fill a form and submit through a <input type="submit"> button. Nothing
216 // special. The form does an in-page navigation before submitting.
217 NavigationObserver observer(WebContents());
218 std::string fill_and_submit =
219 "document.getElementById('username_field').value = 'temp';"
220 "document.getElementById('password_field').value = 'random';"
221 "document.getElementById('input_submit_button').click()";
222 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
224 EXPECT_TRUE(observer.infobar_shown());
227 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
228 LoginSuccessWithUnrelatedForm) {
229 // Log in, see a form on the landing page. That form is not related to the
230 // login form (=has a different action), so we should offer saving the
232 NavigateToFile("/password/password_form.html");
234 NavigationObserver observer(WebContents());
235 std::string fill_and_submit =
236 "document.getElementById('username_unrelated').value = 'temp';"
237 "document.getElementById('password_unrelated').value = 'random';"
238 "document.getElementById('submit_unrelated').click()";
239 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
241 EXPECT_TRUE(observer.infobar_shown());
244 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, LoginFailed) {
245 // Log in, see a form on the landing page. That form is not related to the
246 // login form (=has a different action), so we should offer saving the
248 NavigateToFile("/password/password_form.html");
250 NavigationObserver observer(WebContents());
251 std::string fill_and_submit =
252 "document.getElementById('username_failed').value = 'temp';"
253 "document.getElementById('password_failed').value = 'random';"
254 "document.getElementById('submit_failed').click()";
255 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
257 EXPECT_FALSE(observer.infobar_shown());
260 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, Redirects) {
261 NavigateToFile("/password/password_form.html");
263 // Fill a form and submit through a <input type="submit"> button. The form
264 // points to a redirection page.
265 NavigationObserver observer(WebContents());
266 std::string fill_and_submit =
267 "document.getElementById('username_redirect').value = 'temp';"
268 "document.getElementById('password_redirect').value = 'random';"
269 "document.getElementById('submit_redirect').click()";
270 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
271 observer.disable_should_automatically_accept_infobar();
273 EXPECT_TRUE(observer.infobar_shown());
275 // The redirection page now redirects via Javascript. We check that the
277 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(),
278 "window.location.href = 'done.html';"));
280 EXPECT_FALSE(observer.infobar_removed());
283 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
284 PromptForSubmitUsingJavaScript) {
285 NavigateToFile("/password/password_form.html");
287 // Fill a form and submit using <button> that calls submit() on the form.
288 // This should work regardless of the type of element, as long as submit() is
290 NavigationObserver observer(WebContents());
291 std::string fill_and_submit =
292 "document.getElementById('username_field').value = 'temp';"
293 "document.getElementById('password_field').value = 'random';"
294 "document.getElementById('submit_button').click()";
295 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
297 EXPECT_TRUE(observer.infobar_shown());
300 // Flaky: crbug.com/301547, observed on win and mac. Probably happens on all
302 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
303 DISABLED_PromptForDynamicForm) {
304 NavigateToFile("/password/dynamic_password_form.html");
306 // Fill the dynamic password form and submit.
307 NavigationObserver observer(WebContents());
308 std::string fill_and_submit =
309 "document.getElementById('create_form_button').click();"
310 "window.setTimeout(function() {"
311 " document.dynamic_form.username.value = 'tempro';"
312 " document.dynamic_form.password.value = 'random';"
313 " document.dynamic_form.submit();"
315 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
317 EXPECT_TRUE(observer.infobar_shown());
320 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, NoPromptForNavigation) {
321 NavigateToFile("/password/password_form.html");
323 // Don't fill the password form, just navigate away. Shouldn't prompt.
324 NavigationObserver observer(WebContents());
325 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(),
326 "window.location.href = 'done.html';"));
328 EXPECT_FALSE(observer.infobar_shown());
331 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
332 NoPromptForSubFrameNavigation) {
333 NavigateToFile("/password/multi_frames.html");
335 // If you are filling out a password form in one frame and a different frame
336 // navigates, this should not trigger the infobar.
337 NavigationObserver observer(WebContents());
338 observer.SetPathToWaitFor("/password/done.html");
340 "var first_frame = document.getElementById('first_frame');"
341 "var frame_doc = first_frame.contentDocument;"
342 "frame_doc.getElementById('username_field').value = 'temp';"
343 "frame_doc.getElementById('password_field').value = 'random';";
344 std::string navigate_frame =
345 "var second_iframe = document.getElementById('second_frame');"
346 "second_iframe.contentWindow.location.href = 'done.html';";
348 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill));
349 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), navigate_frame));
351 EXPECT_FALSE(observer.infobar_shown());
354 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
355 PromptAfterSubmitWithSubFrameNavigation) {
356 NavigateToFile("/password/multi_frames.html");
358 // Make sure that we prompt to save password even if a sub-frame navigation
360 NavigationObserver observer(WebContents());
361 observer.SetPathToWaitFor("/password/done.html");
362 std::string navigate_frame =
363 "var second_iframe = document.getElementById('second_frame');"
364 "second_iframe.contentWindow.location.href = 'other.html';";
365 std::string fill_and_submit =
366 "var first_frame = document.getElementById('first_frame');"
367 "var frame_doc = first_frame.contentDocument;"
368 "frame_doc.getElementById('username_field').value = 'temp';"
369 "frame_doc.getElementById('password_field').value = 'random';"
370 "frame_doc.getElementById('input_submit_button').click();";
372 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), navigate_frame));
373 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
375 EXPECT_TRUE(observer.infobar_shown());
378 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
379 PromptForXHRSubmit) {
380 #if defined(OS_WIN) && defined(USE_ASH)
381 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
382 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
385 NavigateToFile("/password/password_xhr_submit.html");
387 // Verify that we show the save password prompt if a form returns false
388 // in its onsubmit handler but instead logs in/navigates via XHR.
389 // Note that calling 'submit()' on a form with javascript doesn't call
390 // the onsubmit handler, so we click the submit button instead.
391 NavigationObserver observer(WebContents());
392 std::string fill_and_submit =
393 "document.getElementById('username_field').value = 'temp';"
394 "document.getElementById('password_field').value = 'random';"
395 "document.getElementById('submit_button').click()";
396 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
398 EXPECT_TRUE(observer.infobar_shown());
401 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
402 PromptForXHRWithoutOnSubmit) {
403 NavigateToFile("/password/password_xhr_submit.html");
405 // Verify that if XHR navigation occurs and the form is properly filled out,
406 // we try and save the password even though onsubmit hasn't been called.
407 NavigationObserver observer(WebContents());
408 std::string fill_and_navigate =
409 "document.getElementById('username_field').value = 'temp';"
410 "document.getElementById('password_field').value = 'random';"
412 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_navigate));
414 EXPECT_TRUE(observer.infobar_shown());
417 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
418 NoPromptIfLinkClicked) {
419 NavigateToFile("/password/password_form.html");
421 // Verify that if the user takes a direct action to leave the page, we don't
422 // prompt to save the password even if the form is already filled out.
423 NavigationObserver observer(WebContents());
424 std::string fill_and_click_link =
425 "document.getElementById('username_field').value = 'temp';"
426 "document.getElementById('password_field').value = 'random';"
427 "document.getElementById('link').click();";
428 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_click_link));
430 EXPECT_FALSE(observer.infobar_shown());
433 // TODO(jam): http://crbug.com/350550
435 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
436 VerifyPasswordGenerationUpload) {
437 // Prevent Autofill requests from actually going over the wire.
438 net::TestURLFetcherFactory factory;
439 // Disable Autofill requesting access to AddressBook data. This causes
440 // the test to hang on Mac.
441 autofill::test::DisableSystemServices(browser()->profile()->GetPrefs());
443 // Visit a signup form.
444 NavigateToFile("/password/signup_form.html");
446 // Enter a password and save it.
447 NavigationObserver first_observer(WebContents());
448 std::string fill_and_submit =
449 "document.getElementById('other_info').value = 'stuff';"
450 "document.getElementById('username_field').value = 'my_username';"
451 "document.getElementById('password_field').value = 'password';"
452 "document.getElementById('input_submit_button').click()";
453 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
455 first_observer.Wait();
456 ASSERT_TRUE(first_observer.infobar_shown());
458 // Now navigate to a login form that has similar HTML markup.
459 NavigateToFile("/password/password_form.html");
461 // Simulate a user click to force an autofill of the form's DOM value, not
462 // just the suggested value.
463 content::SimulateMouseClick(
464 WebContents(), 0, blink::WebMouseEvent::ButtonLeft);
466 // The form should be filled with the previously submitted username.
467 std::string get_username =
468 "window.domAutomationController.send("
469 "document.getElementById('username_field').value);";
470 std::string actual_username;
471 ASSERT_TRUE(content::ExecuteScriptAndExtractString(RenderViewHost(),
474 ASSERT_EQ("my_username", actual_username);
476 // Submit the form and verify that there is no infobar (as the password
477 // has already been saved).
478 NavigationObserver second_observer(WebContents());
479 std::string submit_form =
480 "document.getElementById('input_submit_button').click()";
481 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit_form));
482 second_observer.Wait();
483 EXPECT_FALSE(second_observer.infobar_shown());
485 // Verify that we sent a ping to Autofill saying that the original form
486 // was likely an account creation form since it has more than 2 text input
487 // fields and was used for the first time on a different form.
488 base::HistogramBase* upload_histogram =
489 base::StatisticsRecorder::FindHistogram(
490 "PasswordGeneration.UploadStarted");
491 ASSERT_TRUE(upload_histogram);
492 scoped_ptr<base::HistogramSamples> snapshot =
493 upload_histogram->SnapshotSamples();
494 EXPECT_EQ(0, snapshot->GetCount(0 /* failure */));
495 EXPECT_EQ(1, snapshot->GetCount(1 /* success */));
499 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, PromptForSubmitFromIframe) {
500 NavigateToFile("/password/password_submit_from_iframe.html");
502 // Submit a form in an iframe, then cause the whole page to navigate without a
503 // user gesture. We expect the save password prompt to be shown here, because
504 // some pages use such iframes for login forms.
505 NavigationObserver observer(WebContents());
506 std::string fill_and_submit =
507 "var iframe = document.getElementById('test_iframe');"
508 "var iframe_doc = iframe.contentDocument;"
509 "iframe_doc.getElementById('username_field').value = 'temp';"
510 "iframe_doc.getElementById('password_field').value = 'random';"
511 "iframe_doc.getElementById('submit_button').click()";
513 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
515 EXPECT_TRUE(observer.infobar_shown());
518 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
519 PromptForInputElementWithoutName) {
520 // Check that the prompt is shown for forms where input elements lack the
521 // "name" attribute but the "id" is present.
522 NavigateToFile("/password/password_form.html");
524 NavigationObserver observer(WebContents());
525 std::string fill_and_submit =
526 "document.getElementById('username_field_no_name').value = 'temp';"
527 "document.getElementById('password_field_no_name').value = 'random';"
528 "document.getElementById('input_submit_button_no_name').click()";
529 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
531 EXPECT_TRUE(observer.infobar_shown());
534 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
535 PromptForInputElementWithoutId) {
536 // Check that the prompt is shown for forms where input elements lack the
537 // "id" attribute but the "name" attribute is present.
538 NavigateToFile("/password/password_form.html");
540 NavigationObserver observer(WebContents());
541 std::string fill_and_submit =
542 "document.getElementsByName('username_field_no_id')[0].value = 'temp';"
543 "document.getElementsByName('password_field_no_id')[0].value = 'random';"
544 "document.getElementsByName('input_submit_button_no_id')[0].click()";
545 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
547 EXPECT_TRUE(observer.infobar_shown());
550 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
551 NoPromptForInputElementWithoutIdAndName) {
552 // Check that no prompt is shown for forms where the input fields lack both
553 // the "id" and the "name" attributes.
554 NavigateToFile("/password/password_form.html");
556 NavigationObserver observer(WebContents());
557 std::string fill_and_submit =
558 "var form = document.getElementById('testform_elements_no_id_no_name');"
559 "var username = form.children[0];"
560 "username.value = 'temp';"
561 "var password = form.children[1];"
562 "password.value = 'random';"
563 "form.children[2].click()"; // form.children[2] is the submit button.
564 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
566 EXPECT_FALSE(observer.infobar_shown());
569 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, DeleteFrameBeforeSubmit) {
570 NavigateToFile("/password/multi_frames.html");
572 NavigationObserver observer(WebContents());
573 // Make sure we save some password info from an iframe and then destroy it.
574 std::string save_and_remove =
575 "var first_frame = document.getElementById('first_frame');"
576 "var frame_doc = first_frame.contentDocument;"
577 "frame_doc.getElementById('username_field').value = 'temp';"
578 "frame_doc.getElementById('password_field').value = 'random';"
579 "frame_doc.getElementById('input_submit_button').click();"
580 "first_frame.parentNode.removeChild(first_frame);";
581 // Submit from the main frame, but without navigating through the onsubmit
583 std::string navigate_frame =
584 "document.getElementById('username_field').value = 'temp';"
585 "document.getElementById('password_field').value = 'random';"
586 "document.getElementById('input_submit_button').click();"
587 "window.location.href = 'done.html';";
589 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), save_and_remove));
590 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), navigate_frame));
592 // The only thing we check here is that there is no use-after-free reported.
595 // Disabled on Windows due to flakiness: http://crbug.com/346297
597 #define MAYBE_PasswordValueAccessible DISABLED_PasswordValueAccessible
599 #define MAYBE_PasswordValueAccessible PasswordValueAccessible
601 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
602 MAYBE_PasswordValueAccessible) {
603 NavigateToFile("/password/form_and_link.html");
605 // Click on a link to open a new tab, then switch back to the first one.
606 EXPECT_EQ(1, browser()->tab_strip_model()->count());
608 "document.getElementById('testlink').click();";
609 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), click));
610 EXPECT_EQ(2, browser()->tab_strip_model()->count());
611 browser()->tab_strip_model()->ActivateTabAt(0, false);
613 // Fill in the credentials, and make sure they are saved.
614 NavigationObserver form_submit_observer(WebContents());
615 std::string fill_and_submit =
616 "document.getElementById('username_field').value = 'temp';"
617 "document.getElementById('password_field').value = 'random';"
618 "document.getElementById('input_submit_button').click();";
619 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
620 form_submit_observer.Wait();
621 EXPECT_TRUE(form_submit_observer.infobar_shown());
623 // Reload the original page to have the saved credentials autofilled.
624 NavigationObserver reload_observer(WebContents());
625 NavigateToFile("/password/form_and_link.html");
626 reload_observer.Wait();
628 // Check that while the username is immediately available, the password value
629 // needs a user interaction to show up.
630 std::string check_username =
631 "document.getElementById('username_field').value == 'temp'";
632 std::string check_password =
633 "document.getElementById('password_field').value == 'random'";
634 CheckScriptReturnValue(check_username, true);
635 CheckScriptReturnValue(check_password, false);
636 content::SimulateMouseClick(
637 WebContents(), 0, blink::WebMouseEvent::ButtonLeft);
638 CheckScriptReturnValue(check_username, true);
639 CheckScriptReturnValue(check_password, true);
642 // Test fix for crbug.com/338650.
643 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
644 DontPromptForPasswordFormWithDefaultValue) {
645 NavigateToFile("/password/password_form_with_default_value.html");
647 // Don't prompt if we navigate away even if there is a password value since
648 // it's not coming from the user.
649 NavigationObserver observer(WebContents());
650 NavigateToFile("/password/done.html");
652 EXPECT_FALSE(observer.infobar_shown());
655 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
656 PromptWhenEnableAutomaticPasswordSavingSwitchIsNotSet) {
657 NavigateToFile("/password/password_form.html");
659 // Fill a form and submit through a <input type="submit"> button.
660 NavigationObserver observer(WebContents());
661 std::string fill_and_submit =
662 "document.getElementById('username_field').value = 'temp';"
663 "document.getElementById('password_field').value = 'random';"
664 "document.getElementById('input_submit_button').click()";
665 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
667 EXPECT_TRUE(observer.infobar_shown());
670 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
671 DontPromptWhenEnableAutomaticPasswordSavingSwitchIsSet) {
672 password_manager::TestPasswordStore* password_store =
673 static_cast<password_manager::TestPasswordStore*>(
674 PasswordStoreFactory::GetForProfile(browser()->profile(),
675 Profile::IMPLICIT_ACCESS).get());
677 EXPECT_TRUE(password_store->IsEmpty());
679 NavigateToFile("/password/password_form.html");
681 // Add the enable-automatic-password-saving switch.
682 CommandLine::ForCurrentProcess()->AppendSwitch(
683 password_manager::switches::kEnableAutomaticPasswordSaving);
685 // Fill a form and submit through a <input type="submit"> button.
686 NavigationObserver observer(WebContents());
687 // Make sure that the only passwords saved are the auto-saved ones.
688 observer.disable_should_automatically_accept_infobar();
689 std::string fill_and_submit =
690 "document.getElementById('username_field').value = 'temp';"
691 "document.getElementById('password_field').value = 'random';"
692 "document.getElementById('input_submit_button').click()";
693 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
695 if (chrome::VersionInfo::GetChannel() ==
696 chrome::VersionInfo::CHANNEL_UNKNOWN) {
697 EXPECT_FALSE(observer.infobar_shown());
698 EXPECT_FALSE(password_store->IsEmpty());
700 EXPECT_TRUE(observer.infobar_shown());
701 EXPECT_TRUE(password_store->IsEmpty());
705 // Test fix for crbug.com/368690.
706 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, NoPromptWhenReloading) {
707 NavigateToFile("/password/password_form.html");
710 "document.getElementById('username_redirect').value = 'temp';"
711 "document.getElementById('password_redirect').value = 'random';";
712 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill));
714 NavigationObserver observer(WebContents());
715 GURL url = embedded_test_server()->GetURL("/password/password_form.html");
716 chrome::NavigateParams params(browser(), url,
717 content::PAGE_TRANSITION_RELOAD);
718 ui_test_utils::NavigateToURL(¶ms);
720 EXPECT_FALSE(observer.infobar_shown());