Temporarily disable "gate password autofill on user gesture" on mobile.
[chromium-blink-merge.git] / chrome / browser / password_manager / password_manager_browsertest.cc
blobdc12b4b6c3217dc3f17bd2ccdcb32a42a94cf752
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <string>
7 #include "base/command_line.h"
8 #include "base/metrics/histogram_samples.h"
9 #include "base/metrics/statistics_recorder.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/infobars/confirm_infobar_delegate.h"
12 #include "chrome/browser/infobars/infobar.h"
13 #include "chrome/browser/infobars/infobar_service.h"
14 #include "chrome/browser/password_manager/password_store_factory.h"
15 #include "chrome/browser/password_manager/test_password_store_service.h"
16 #include "chrome/browser/ui/browser.h"
17 #include "chrome/browser/ui/tabs/tab_strip_model.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/password_manager/core/browser/test_password_store.h"
23 #include "content/public/browser/notification_observer.h"
24 #include "content/public/browser/notification_registrar.h"
25 #include "content/public/browser/notification_service.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 ---------------------------------------------------------
40 namespace {
42 // Observer that waits for navigation to complete and for the password infobar
43 // to be shown.
44 class NavigationObserver : public content::NotificationObserver,
45 public content::WebContentsObserver {
46 public:
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 registrar_.Add(this,
55 chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED,
56 content::Source<InfoBarService>(infobar_service_));
57 registrar_.Add(this,
58 chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
59 content::Source<InfoBarService>(infobar_service_));
62 virtual ~NavigationObserver() {}
64 // Normally Wait() will not return until a main frame navigation occurs.
65 // If a path is set, Wait() will return after this path has been seen,
66 // regardless of the frame that navigated. Useful for multi-frame pages.
67 void SetPathToWaitFor(const std::string& path) {
68 wait_for_path_ = path;
71 // content::NotificationObserver:
72 virtual void Observe(int type,
73 const content::NotificationSource& source,
74 const content::NotificationDetails& details) OVERRIDE {
75 switch (type) {
76 case chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED:
77 if (should_automatically_accept_infobar_) {
78 infobar_service_->infobar_at(0)
79 ->delegate()
80 ->AsConfirmInfoBarDelegate()
81 ->Accept();
83 infobar_shown_ = true;
84 return;
85 case chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED:
86 infobar_removed_ = true;
87 return;
88 default:
89 NOTREACHED();
90 return;
94 // content::WebContentsObserver:
95 virtual void DidFinishLoad(
96 int64 frame_id,
97 const GURL& validated_url,
98 bool is_main_frame,
99 content::RenderViewHost* render_view_host) OVERRIDE {
100 if (!wait_for_path_.empty()) {
101 if (validated_url.path() == wait_for_path_)
102 message_loop_runner_->Quit();
103 } else if (is_main_frame) {
104 message_loop_runner_->Quit();
108 bool infobar_shown() const { return infobar_shown_; }
109 bool infobar_removed() const { return infobar_removed_; }
111 void disable_should_automatically_accept_infobar() {
112 should_automatically_accept_infobar_ = false;
115 void Wait() {
116 message_loop_runner_->Run();
119 private:
120 std::string wait_for_path_;
121 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
122 bool infobar_shown_;
123 bool infobar_removed_;
124 // If |should_automatically_accept_infobar_| is true, then whenever the test
125 // sees an infobar added, it will click its accepting button. Default = true.
126 bool should_automatically_accept_infobar_;
127 content::NotificationRegistrar registrar_;
128 InfoBarService* infobar_service_;
130 DISALLOW_COPY_AND_ASSIGN(NavigationObserver);
133 } // namespace
136 // PasswordManagerBrowserTest -------------------------------------------------
138 class PasswordManagerBrowserTest : public InProcessBrowserTest {
139 public:
140 PasswordManagerBrowserTest() {}
141 virtual ~PasswordManagerBrowserTest() {}
143 // InProcessBrowserTest:
144 virtual void SetUpOnMainThread() OVERRIDE {
145 // Use TestPasswordStore to remove a possible race. Normally the
146 // PasswordStore does its database manipulation on the DB thread, which
147 // creates a possible race during navigation. Specifically the
148 // PasswordManager will ignore any forms in a page if the load from the
149 // PasswordStore has not completed.
150 PasswordStoreFactory::GetInstance()->SetTestingFactory(
151 browser()->profile(), TestPasswordStoreService::Build);
154 protected:
155 content::WebContents* WebContents() {
156 return browser()->tab_strip_model()->GetActiveWebContents();
159 content::RenderViewHost* RenderViewHost() {
160 return WebContents()->GetRenderViewHost();
163 // Wrapper around ui_test_utils::NavigateToURL that waits until
164 // DidFinishLoad() fires. Normally this function returns after
165 // DidStopLoading(), which caused flakiness as the NavigationObserver
166 // would sometimes see the DidFinishLoad event from a previous navigation and
167 // return immediately.
168 void NavigateToFile(const std::string& path) {
169 if (!embedded_test_server()->Started())
170 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
172 NavigationObserver observer(WebContents());
173 GURL url = embedded_test_server()->GetURL(path);
174 ui_test_utils::NavigateToURL(browser(), url);
175 observer.Wait();
178 // Executes |script| and uses the EXPECT macros to check the return value
179 // against |expected_return_value|.
180 void CheckScriptReturnValue(std::string& script, bool expected_return_value);
182 private:
183 DISALLOW_COPY_AND_ASSIGN(PasswordManagerBrowserTest);
186 void PasswordManagerBrowserTest::CheckScriptReturnValue(
187 std::string& script,
188 bool expected_return_value) {
189 const std::string wrapped_script =
190 std::string("window.domAutomationController.send(") + script + ");";
191 bool return_value = !expected_return_value;
192 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
193 RenderViewHost(), wrapped_script, &return_value));
194 EXPECT_EQ(expected_return_value, return_value) << "script = " << script;
197 // Actual tests ---------------------------------------------------------------
198 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
199 PromptForNormalSubmit) {
200 NavigateToFile("/password/password_form.html");
202 // Fill a form and submit through a <input type="submit"> button. Nothing
203 // special.
204 NavigationObserver observer(WebContents());
205 std::string fill_and_submit =
206 "document.getElementById('username_field').value = 'temp';"
207 "document.getElementById('password_field').value = 'random';"
208 "document.getElementById('input_submit_button').click()";
209 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
210 observer.Wait();
211 EXPECT_TRUE(observer.infobar_shown());
214 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
215 PromptForSubmitWithInPageNavigation) {
216 NavigateToFile("/password/password_navigate_before_submit.html");
218 // Fill a form and submit through a <input type="submit"> button. Nothing
219 // special. The form does an in-page navigation before submitting.
220 NavigationObserver observer(WebContents());
221 std::string fill_and_submit =
222 "document.getElementById('username_field').value = 'temp';"
223 "document.getElementById('password_field').value = 'random';"
224 "document.getElementById('input_submit_button').click()";
225 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
226 observer.Wait();
227 EXPECT_TRUE(observer.infobar_shown());
230 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
231 LoginSuccessWithUnrelatedForm) {
232 // Log in, see a form on the landing page. That form is not related to the
233 // login form (=has a different action), so we should offer saving the
234 // password.
235 NavigateToFile("/password/password_form.html");
237 NavigationObserver observer(WebContents());
238 std::string fill_and_submit =
239 "document.getElementById('username_unrelated').value = 'temp';"
240 "document.getElementById('password_unrelated').value = 'random';"
241 "document.getElementById('submit_unrelated').click()";
242 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
243 observer.Wait();
244 EXPECT_TRUE(observer.infobar_shown());
247 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, LoginFailed) {
248 // Log in, see a form on the landing page. That form is not related to the
249 // login form (=has a different action), so we should offer saving the
250 // password.
251 NavigateToFile("/password/password_form.html");
253 NavigationObserver observer(WebContents());
254 std::string fill_and_submit =
255 "document.getElementById('username_failed').value = 'temp';"
256 "document.getElementById('password_failed').value = 'random';"
257 "document.getElementById('submit_failed').click()";
258 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
259 observer.Wait();
260 EXPECT_FALSE(observer.infobar_shown());
263 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, Redirects) {
264 NavigateToFile("/password/password_form.html");
266 // Fill a form and submit through a <input type="submit"> button. The form
267 // points to a redirection page.
268 NavigationObserver observer(WebContents());
269 std::string fill_and_submit =
270 "document.getElementById('username_redirect').value = 'temp';"
271 "document.getElementById('password_redirect').value = 'random';"
272 "document.getElementById('submit_redirect').click()";
273 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
274 observer.disable_should_automatically_accept_infobar();
275 observer.Wait();
276 EXPECT_TRUE(observer.infobar_shown());
278 // The redirection page now redirects via Javascript. We check that the
279 // infobar stays.
280 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(),
281 "window.location.href = 'done.html';"));
282 observer.Wait();
283 EXPECT_FALSE(observer.infobar_removed());
286 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
287 PromptForSubmitUsingJavaScript) {
288 NavigateToFile("/password/password_form.html");
290 // Fill a form and submit using <button> that calls submit() on the form.
291 // This should work regardless of the type of element, as long as submit() is
292 // called.
293 NavigationObserver observer(WebContents());
294 std::string fill_and_submit =
295 "document.getElementById('username_field').value = 'temp';"
296 "document.getElementById('password_field').value = 'random';"
297 "document.getElementById('submit_button').click()";
298 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
299 observer.Wait();
300 EXPECT_TRUE(observer.infobar_shown());
303 // Flaky: crbug.com/301547, observed on win and mac. Probably happens on all
304 // platforms.
305 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
306 DISABLED_PromptForDynamicForm) {
307 NavigateToFile("/password/dynamic_password_form.html");
309 // Fill the dynamic password form and submit.
310 NavigationObserver observer(WebContents());
311 std::string fill_and_submit =
312 "document.getElementById('create_form_button').click();"
313 "window.setTimeout(function() {"
314 " document.dynamic_form.username.value = 'tempro';"
315 " document.dynamic_form.password.value = 'random';"
316 " document.dynamic_form.submit();"
317 "}, 0)";
318 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
319 observer.Wait();
320 EXPECT_TRUE(observer.infobar_shown());
323 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, NoPromptForNavigation) {
324 NavigateToFile("/password/password_form.html");
326 // Don't fill the password form, just navigate away. Shouldn't prompt.
327 NavigationObserver observer(WebContents());
328 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(),
329 "window.location.href = 'done.html';"));
330 observer.Wait();
331 EXPECT_FALSE(observer.infobar_shown());
334 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
335 NoPromptForSubFrameNavigation) {
336 NavigateToFile("/password/multi_frames.html");
338 // If you are filling out a password form in one frame and a different frame
339 // navigates, this should not trigger the infobar.
340 NavigationObserver observer(WebContents());
341 observer.SetPathToWaitFor("/password/done.html");
342 std::string fill =
343 "var first_frame = document.getElementById('first_frame');"
344 "var frame_doc = first_frame.contentDocument;"
345 "frame_doc.getElementById('username_field').value = 'temp';"
346 "frame_doc.getElementById('password_field').value = 'random';";
347 std::string navigate_frame =
348 "var second_iframe = document.getElementById('second_frame');"
349 "second_iframe.contentWindow.location.href = 'done.html';";
351 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill));
352 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), navigate_frame));
353 observer.Wait();
354 EXPECT_FALSE(observer.infobar_shown());
357 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
358 PromptAfterSubmitWithSubFrameNavigation) {
359 NavigateToFile("/password/multi_frames.html");
361 // Make sure that we prompt to save password even if a sub-frame navigation
362 // happens first.
363 NavigationObserver observer(WebContents());
364 observer.SetPathToWaitFor("/password/done.html");
365 std::string navigate_frame =
366 "var second_iframe = document.getElementById('second_frame');"
367 "second_iframe.contentWindow.location.href = 'other.html';";
368 std::string fill_and_submit =
369 "var first_frame = document.getElementById('first_frame');"
370 "var frame_doc = first_frame.contentDocument;"
371 "frame_doc.getElementById('username_field').value = 'temp';"
372 "frame_doc.getElementById('password_field').value = 'random';"
373 "frame_doc.getElementById('input_submit_button').click();";
375 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), navigate_frame));
376 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
377 observer.Wait();
378 EXPECT_TRUE(observer.infobar_shown());
381 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
382 PromptForXHRSubmit) {
383 #if defined(OS_WIN) && defined(USE_ASH)
384 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
385 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
386 return;
387 #endif
388 NavigateToFile("/password/password_xhr_submit.html");
390 // Verify that we show the save password prompt if a form returns false
391 // in its onsubmit handler but instead logs in/navigates via XHR.
392 // Note that calling 'submit()' on a form with javascript doesn't call
393 // the onsubmit handler, so we click the submit button instead.
394 NavigationObserver observer(WebContents());
395 std::string fill_and_submit =
396 "document.getElementById('username_field').value = 'temp';"
397 "document.getElementById('password_field').value = 'random';"
398 "document.getElementById('submit_button').click()";
399 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
400 observer.Wait();
401 EXPECT_TRUE(observer.infobar_shown());
404 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
405 PromptForXHRWithoutOnSubmit) {
406 NavigateToFile("/password/password_xhr_submit.html");
408 // Verify that if XHR navigation occurs and the form is properly filled out,
409 // we try and save the password even though onsubmit hasn't been called.
410 NavigationObserver observer(WebContents());
411 std::string fill_and_navigate =
412 "document.getElementById('username_field').value = 'temp';"
413 "document.getElementById('password_field').value = 'random';"
414 "send_xhr()";
415 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_navigate));
416 observer.Wait();
417 EXPECT_TRUE(observer.infobar_shown());
420 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
421 NoPromptIfLinkClicked) {
422 NavigateToFile("/password/password_form.html");
424 // Verify that if the user takes a direct action to leave the page, we don't
425 // prompt to save the password even if the form is already filled out.
426 NavigationObserver observer(WebContents());
427 std::string fill_and_click_link =
428 "document.getElementById('username_field').value = 'temp';"
429 "document.getElementById('password_field').value = 'random';"
430 "document.getElementById('link').click();";
431 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_click_link));
432 observer.Wait();
433 EXPECT_FALSE(observer.infobar_shown());
436 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
437 VerifyPasswordGenerationUpload) {
438 // Prevent Autofill requests from actually going over the wire.
439 net::TestURLFetcherFactory factory;
440 // Disable Autofill requesting access to AddressBook data. This causes
441 // the test to hang on Mac.
442 autofill::test::DisableSystemServices(browser()->profile());
444 // Visit a signup form.
445 NavigateToFile("/password/signup_form.html");
447 // Enter a password and save it.
448 NavigationObserver first_observer(WebContents());
449 std::string fill_and_submit =
450 "document.getElementById('other_info').value = 'stuff';"
451 "document.getElementById('username_field').value = 'my_username';"
452 "document.getElementById('password_field').value = 'password';"
453 "document.getElementById('input_submit_button').click()";
454 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
456 first_observer.Wait();
457 ASSERT_TRUE(first_observer.infobar_shown());
459 // Now navigate to a login form that has similar HTML markup.
460 NavigateToFile("/password/password_form.html");
462 // Simulate a user click to force an autofill of the form's DOM value, not
463 // just the suggested value.
464 content::SimulateMouseClick(
465 WebContents(), 0, blink::WebMouseEvent::ButtonLeft);
467 // The form should be filled with the previously submitted username.
468 std::string get_username =
469 "window.domAutomationController.send("
470 "document.getElementById('username_field').value);";
471 std::string actual_username;
472 ASSERT_TRUE(content::ExecuteScriptAndExtractString(RenderViewHost(),
473 get_username,
474 &actual_username));
475 ASSERT_EQ("my_username", actual_username);
477 // Submit the form and verify that there is no infobar (as the password
478 // has already been saved).
479 NavigationObserver second_observer(WebContents());
480 std::string submit_form =
481 "document.getElementById('input_submit_button').click()";
482 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit_form));
483 second_observer.Wait();
484 EXPECT_FALSE(second_observer.infobar_shown());
486 // Verify that we sent a ping to Autofill saying that the original form
487 // was likely an account creation form since it has more than 2 text input
488 // fields and was used for the first time on a different form.
489 base::HistogramBase* upload_histogram =
490 base::StatisticsRecorder::FindHistogram(
491 "PasswordGeneration.UploadStarted");
492 ASSERT_TRUE(upload_histogram);
493 scoped_ptr<base::HistogramSamples> snapshot =
494 upload_histogram->SnapshotSamples();
495 EXPECT_EQ(0, snapshot->GetCount(0 /* failure */));
496 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));
514 observer.Wait();
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));
530 observer.Wait();
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));
546 observer.Wait();
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));
565 observer.Wait();
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
582 // handler.
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));
591 observer.Wait();
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/163072
596 // TODO(vabr): Also disabled on Android, because the tested feature is currently
597 // disabled there. http://crbug.com/345510#c13
598 #if defined(OS_WIN) || defined(OS_ANDROID)
599 #define MAYBE_PasswordValueAccessible DISABLED_PasswordValueAccessible
600 #else
601 #define MAYBE_PasswordValueAccessible PasswordValueAccessible
602 #endif
603 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
604 MAYBE_PasswordValueAccessible) {
605 NavigateToFile("/password/form_and_link.html");
607 // Click on a link to open a new tab, then switch back to the first one.
608 EXPECT_EQ(1, browser()->tab_strip_model()->count());
609 std::string click =
610 "document.getElementById('testlink').click();";
611 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), click));
612 EXPECT_EQ(2, browser()->tab_strip_model()->count());
613 browser()->tab_strip_model()->ActivateTabAt(0, false);
615 // Fill in the credentials, and make sure they are saved.
616 NavigationObserver form_submit_observer(WebContents());
617 std::string fill_and_submit =
618 "document.getElementById('username_field').value = 'temp';"
619 "document.getElementById('password_field').value = 'random';"
620 "document.getElementById('input_submit_button').click();";
621 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
622 form_submit_observer.Wait();
623 EXPECT_TRUE(form_submit_observer.infobar_shown());
625 // Reload the original page to have the saved credentials autofilled.
626 NavigationObserver reload_observer(WebContents());
627 NavigateToFile("/password/form_and_link.html");
628 reload_observer.Wait();
630 // Check that while the username is immediately available, the password value
631 // needs a user interaction to show up.
632 std::string check_username =
633 "document.getElementById('username_field').value == 'temp'";
634 std::string check_password =
635 "document.getElementById('password_field').value == 'random'";
636 CheckScriptReturnValue(check_username, true);
637 CheckScriptReturnValue(check_password, false);
638 content::SimulateMouseClick(
639 WebContents(), 0, blink::WebMouseEvent::ButtonLeft);
640 CheckScriptReturnValue(check_username, true);
641 CheckScriptReturnValue(check_password, true);
644 // Test fix for crbug.com/338650.
645 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
646 DontPromptForPasswordFormWithDefaultValue) {
647 NavigateToFile("/password/password_form_with_default_value.html");
649 // Don't prompt if we navigate away even if there is a password value since
650 // it's not coming from the user.
651 NavigationObserver observer(WebContents());
652 NavigateToFile("/password/done.html");
653 observer.Wait();
654 EXPECT_FALSE(observer.infobar_shown());