Add ENABLE_MEDIA_ROUTER define to builds other than Android and iOS.
[chromium-blink-merge.git] / chrome / browser / password_manager / password_manager_browsertest.cc
blob51718cb9780dfdd50a7fdc745ca8eed5c1d47afd
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <string>
7 #include "base/command_line.h"
8 #include "base/metrics/histogram_samples.h"
9 #include "base/metrics/statistics_recorder.h"
10 #include "base/path_service.h"
11 #include "base/run_loop.h"
12 #include "base/stl_util.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "chrome/browser/chrome_notification_types.h"
16 #include "chrome/browser/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 ---------------------------------------------------------
64 namespace {
66 // Observer that waits for navigation to complete and for the password infobar
67 // to be shown.
68 class NavigationObserver : public content::WebContentsObserver {
69 public:
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(); }
107 private:
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 {
119 public:
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());
129 AcceptImpl();
132 // Chooses the right implementation of PromptObserver and creates an instance
133 // of it.
134 static scoped_ptr<PromptObserver> Create(content::WebContents* web_contents);
136 protected:
137 PromptObserver() {}
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
141 // closed.
142 virtual void AcceptImpl() const = 0;
144 private:
145 DISALLOW_COPY_AND_ASSIGN(PromptObserver);
148 class InfoBarObserver : public PromptObserver,
149 public infobars::InfoBarManager::Observer {
150 public:
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);
162 private:
163 // PromptObserver:
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)
176 ->delegate()
177 ->AsConfirmInfoBarDelegate()
178 ->Accept());
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 {
203 public:
204 explicit BubbleObserver(content::WebContents* web_contents)
205 : ui_controller_(
206 ManagePasswordsUIController::FromWebContents(web_contents)) {}
208 ~BubbleObserver() override {}
210 private:
211 // PromptObserver:
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 {
227 public:
228 ObservingAutofillClient()
229 : message_loop_runner_(new content::MessageLoopRunner){}
230 ~ObservingAutofillClient() override {}
232 void Wait() {
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();
244 private:
245 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
247 DISALLOW_COPY_AND_ASSIGN(ObservingAutofillClient);
250 GURL GetFileURL(const char* filename) {
251 base::FilePath path;
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);
258 // static
259 scoped_ptr<PromptObserver> PromptObserver::Create(
260 content::WebContents* web_contents) {
261 if (ChromePasswordManagerClient::IsTheHotNewBubbleUIEnabled()) {
262 return scoped_ptr<PromptObserver>(new BubbleObserver(web_contents));
263 } else {
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();
282 } else {
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();
292 } // namespace
295 // PasswordManagerBrowserTest -------------------------------------------------
297 class PasswordManagerBrowserTest : public InProcessBrowserTest {
298 public:
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());
320 protected:
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);
338 observer.Wait();
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
354 // a flag.
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();
362 private:
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.
370 RETURN_CODE_OK,
371 RETURN_CODE_NO_ELEMENT,
372 RETURN_CODE_WRONG_VALUE,
373 RETURN_CODE_INVALID,
375 const std::string value_check_function = base::StringPrintf(
376 "function valueCheck() {"
377 " var element = document.getElementById('%s');"
378 " return element && element.value == '%s';"
379 "}",
380 element_id.c_str(),
381 expected_value.c_str());
382 const std::string script =
383 value_check_function +
384 base::StringPrintf(
385 "if (valueCheck()) {"
386 " /* Spin the event loop with setTimeout. */"
387 " setTimeout(window.domAutomationController.send(%d), 0);"
388 "} else {"
389 " var element = document.getElementById('%s');"
390 " if (!element)"
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);"
396 " } else {"
397 " window.domAutomationController.send(%d);"
398 " }"
399 " };"
400 "}",
401 RETURN_CODE_OK,
402 element_id.c_str(),
403 RETURN_CODE_NO_ELEMENT,
404 RETURN_CODE_OK,
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');",
420 element_id.c_str(),
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
441 // special.
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));
450 observer.Wait();
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));
468 observer.Wait();
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
476 // password.
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));
487 observer.Wait();
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
494 // password.
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));
505 observer.Wait();
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));
522 observer.Wait();
523 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
525 // The redirection page now redirects via Javascript. We check that the
526 // infobar stays.
527 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(),
528 "window.location.href = 'done.html';"));
529 observer.Wait();
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
539 // called.
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));
548 observer.Wait();
549 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
552 // Flaky: crbug.com/301547, observed on win and mac. Probably happens on all
553 // platforms.
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();"
568 "}, 0)";
569 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
570 observer.Wait();
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';"));
583 observer.Wait();
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");
597 std::string fill =
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));
608 observer.Wait();
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
617 // happens first.
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));
634 observer.Wait();
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));
654 observer.Wait();
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");
677 observer.Wait();
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))
686 return;
687 #endif
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));
702 observer.Wait();
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';"
718 "send_xhr()";
719 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_navigate));
720 observer.Wait();
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';"
739 "send_xhr()";
740 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_navigate));
741 observer.Wait();
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
757 // fields by script.
758 scoped_ptr<PromptObserver> prompt_observer(
759 PromptObserver::Create(WebContents()));
760 std::string fill_and_submit =
761 "navigate = false;"
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));
766 std::string message;
767 while (message_queue.WaitForMessage(&message)) {
768 if (message == "\"XHR_FINISHED\"")
769 break;
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
787 // fields by script.
788 scoped_ptr<PromptObserver> prompt_observer(
789 PromptObserver::Create(WebContents()));
790 std::string fill_and_submit =
791 "navigate = false;"
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));
797 std::string message;
798 while (message_queue.WaitForMessage(&message)) {
799 if (message == "\"XHR_FINISHED\"")
800 break;
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 =
819 "navigate = false;"
820 "document.getElementById('username_field').value = 'temp';"
821 "document.getElementById('submit_button').click();";
822 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
823 std::string message;
824 while (message_queue.WaitForMessage(&message)) {
825 if (message == "\"XHR_FINISHED\"")
826 break;
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 =
846 "navigate = false;"
847 "document.getElementById('signup_username_field').value = 'temp';"
848 "document.getElementById('signup_submit_button').click();";
849 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
850 std::string message;
851 while (message_queue.WaitForMessage(&message)) {
852 if (message == "\"XHR_FINISHED\"")
853 break;
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));
872 observer.Wait();
873 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
876 // TODO(jam): http://crbug.com/350550
877 #if !defined(OS_WIN)
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(),
918 get_username,
919 &actual_username));
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 */));
946 #endif
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));
965 observer.Wait();
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));
983 observer.Wait();
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));
1001 observer.Wait();
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));
1022 observer.Wait();
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));
1040 observer.Wait();
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
1047 // HTTP status 404.
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));
1058 observer.Wait();
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
1075 // handler.
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));
1084 observer.Wait();
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
1089 #if defined(OS_WIN)
1090 #define MAYBE_PasswordValueAccessible DISABLED_PasswordValueAccessible
1091 #else
1092 #define MAYBE_PasswordValueAccessible PasswordValueAccessible
1093 #endif
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());
1100 std::string click =
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
1141 // gesture events.
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;
1174 #endif
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");
1187 observer.Wait();
1188 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
1191 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
1192 PromptWhenEnableAutomaticPasswordSavingSwitchIsNotSet) {
1193 NavigateToFile("/password/password_form.html");
1195 // Fill a form and submit through a <input type="submit"> button.
1196 NavigationObserver observer(WebContents());
1197 scoped_ptr<PromptObserver> prompt_observer(
1198 PromptObserver::Create(WebContents()));
1199 std::string fill_and_submit =
1200 "document.getElementById('username_field').value = 'temp';"
1201 "document.getElementById('password_field').value = 'random';"
1202 "document.getElementById('input_submit_button').click()";
1203 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1204 observer.Wait();
1205 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1208 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
1209 DontPromptWhenEnableAutomaticPasswordSavingSwitchIsSet) {
1210 password_manager::TestPasswordStore* password_store =
1211 static_cast<password_manager::TestPasswordStore*>(
1212 PasswordStoreFactory::GetForProfile(
1213 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS).get());
1215 EXPECT_TRUE(password_store->IsEmpty());
1217 NavigateToFile("/password/password_form.html");
1219 // Add the enable-automatic-password-saving switch.
1220 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1221 password_manager::switches::kEnableAutomaticPasswordSaving);
1223 // Fill a form and submit through a <input type="submit"> button.
1224 NavigationObserver observer(WebContents());
1225 scoped_ptr<PromptObserver> prompt_observer(
1226 PromptObserver::Create(WebContents()));
1227 // Make sure that the only passwords saved are the auto-saved ones.
1228 std::string fill_and_submit =
1229 "document.getElementById('username_field').value = 'temp';"
1230 "document.getElementById('password_field').value = 'random';"
1231 "document.getElementById('input_submit_button').click()";
1232 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1233 observer.Wait();
1234 if (chrome::VersionInfo::GetChannel() ==
1235 chrome::VersionInfo::CHANNEL_UNKNOWN) {
1236 // Passwords getting auto-saved, no prompt.
1237 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
1238 EXPECT_FALSE(password_store->IsEmpty());
1239 } else {
1240 // Prompt shown, and no passwords saved automatically.
1241 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1242 EXPECT_TRUE(password_store->IsEmpty());
1246 // Test fix for crbug.com/368690.
1247 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, NoPromptWhenReloading) {
1248 NavigateToFile("/password/password_form.html");
1250 std::string fill =
1251 "document.getElementById('username_redirect').value = 'temp';"
1252 "document.getElementById('password_redirect').value = 'random';";
1253 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill));
1255 NavigationObserver observer(WebContents());
1256 scoped_ptr<PromptObserver> prompt_observer(
1257 PromptObserver::Create(WebContents()));
1258 GURL url = embedded_test_server()->GetURL("/password/password_form.html");
1259 chrome::NavigateParams params(browser(), url,
1260 ui::PAGE_TRANSITION_RELOAD);
1261 ui_test_utils::NavigateToURL(&params);
1262 observer.Wait();
1263 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
1266 // Test that if a form gets dynamically added between the form parsing and
1267 // rendering, and while the main frame still loads, it still is registered, and
1268 // thus saving passwords from it works.
1269 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
1270 FormsAddedBetweenParsingAndRendering) {
1271 NavigateToFile("/password/between_parsing_and_rendering.html");
1273 NavigationObserver observer(WebContents());
1274 scoped_ptr<PromptObserver> prompt_observer(
1275 PromptObserver::Create(WebContents()));
1276 std::string submit =
1277 "document.getElementById('username').value = 'temp';"
1278 "document.getElementById('password').value = 'random';"
1279 "document.getElementById('submit-button').click();";
1280 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit));
1281 observer.Wait();
1283 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1286 // Test that if there was no previous page load then the PasswordManagerDriver
1287 // does not think that there were SSL errors on the current page. The test opens
1288 // a new tab with a URL for which the embedded test server issues a basic auth
1289 // challenge.
1290 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, NoLastLoadGoodLastLoad) {
1291 // Teach the embedded server to handle requests by issuing the basic auth
1292 // challenge.
1293 embedded_test_server()->RegisterRequestHandler(
1294 base::Bind(&HandleTestAuthRequest));
1296 LoginPromptBrowserTestObserver login_observer;
1297 // We need to register to all sources, because the navigation observer we are
1298 // interested in is for a new tab to be opened, and thus does not exist yet.
1299 login_observer.Register(content::NotificationService::AllSources());
1301 password_manager::TestPasswordStore* password_store =
1302 static_cast<password_manager::TestPasswordStore*>(
1303 PasswordStoreFactory::GetForProfile(
1304 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS).get());
1305 EXPECT_TRUE(password_store->IsEmpty());
1307 // Navigate to a page requiring HTTP auth. Wait for the tab to get the correct
1308 // WebContents, but don't wait for navigation, which only finishes after
1309 // authentication.
1310 ui_test_utils::NavigateToURLWithDisposition(
1311 browser(),
1312 embedded_test_server()->GetURL("/basic_auth"),
1313 NEW_FOREGROUND_TAB,
1314 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
1316 content::NavigationController* nav_controller =
1317 &WebContents()->GetController();
1318 NavigationObserver nav_observer(WebContents());
1319 scoped_ptr<PromptObserver> prompt_observer(
1320 PromptObserver::Create(WebContents()));
1321 WindowedAuthNeededObserver auth_needed_observer(nav_controller);
1322 auth_needed_observer.Wait();
1324 WindowedAuthSuppliedObserver auth_supplied_observer(nav_controller);
1325 // Offer valid credentials on the auth challenge.
1326 ASSERT_EQ(1u, login_observer.handlers().size());
1327 LoginHandler* handler = *login_observer.handlers().begin();
1328 ASSERT_TRUE(handler);
1329 // Any username/password will work.
1330 handler->SetAuth(base::UTF8ToUTF16("user"), base::UTF8ToUTF16("pwd"));
1331 auth_supplied_observer.Wait();
1333 // The password manager should be working correctly.
1334 nav_observer.Wait();
1335 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1336 prompt_observer->Accept();
1338 // Spin the message loop to make sure the password store had a chance to save
1339 // the password.
1340 base::RunLoop run_loop;
1341 run_loop.RunUntilIdle();
1342 EXPECT_FALSE(password_store->IsEmpty());
1345 // In some situations, multiple PasswordFormManager instances from
1346 // PasswordManager::pending_login_managers_ would match (via DoesManage) a form
1347 // to be provisionally saved. One of them might be a complete match, the other
1348 // all-but-action match. Normally, the former should be preferred, but if the
1349 // former has not finished matching, and the latter has, the latter should be
1350 // used (otherwise we'd give up even though we could have saved the password).
1351 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
1352 PreferPasswordFormManagerWhichFinishedMatching) {
1353 NavigateToFile("/password/create_form_copy_on_submit.html");
1355 NavigationObserver observer(WebContents());
1356 scoped_ptr<PromptObserver> prompt_observer(
1357 PromptObserver::Create(WebContents()));
1358 std::string submit =
1359 "document.getElementById('username').value = 'overwrite_me';"
1360 "document.getElementById('password').value = 'random';"
1361 "document.getElementById('non-form-button').click();";
1362 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit));
1363 observer.Wait();
1365 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1368 // Test that if login fails and content server pushes a different login form
1369 // with action URL having different schemes. Heuristic shall be able
1370 // identify such cases and *shall not* prompt to save incorrect password.
1371 IN_PROC_BROWSER_TEST_F(
1372 PasswordManagerBrowserTest,
1373 NoPromptForLoginFailedAndServerPushSeperateLoginForm_HttpToHttps) {
1374 std::string path =
1375 "/password/separate_login_form_with_onload_submit_script.html";
1376 GURL http_url(embedded_test_server()->GetURL(path));
1377 ASSERT_TRUE(http_url.SchemeIs(url::kHttpScheme));
1379 NavigationObserver observer(WebContents());
1380 scoped_ptr<PromptObserver> prompt_observer(
1381 PromptObserver::Create(WebContents()));
1382 ui_test_utils::NavigateToURL(browser(), http_url);
1384 observer.SetPathToWaitFor("/password/done_and_separate_login_form.html");
1385 observer.Wait();
1387 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
1390 IN_PROC_BROWSER_TEST_F(
1391 PasswordManagerBrowserTest,
1392 NoPromptForLoginFailedAndServerPushSeperateLoginForm_HttpsToHttp) {
1393 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1394 switches::kAllowRunningInsecureContent);
1395 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1396 switches::kIgnoreCertificateErrors);
1397 const base::FilePath::CharType kDocRoot[] =
1398 FILE_PATH_LITERAL("chrome/test/data");
1399 net::SpawnedTestServer https_test_server(
1400 net::SpawnedTestServer::TYPE_HTTPS,
1401 net::SpawnedTestServer::SSLOptions(
1402 net::SpawnedTestServer::SSLOptions::CERT_OK),
1403 base::FilePath(kDocRoot));
1404 ASSERT_TRUE(https_test_server.Start());
1406 // This test case cannot inject the scripts via content::ExecuteScript() in
1407 // files served through HTTPS. Therefore the scripts are made part of the HTML
1408 // site and executed on load.
1409 std::string path =
1410 "password/separate_login_form_with_onload_submit_script.html";
1411 GURL https_url(https_test_server.GetURL(path));
1412 ASSERT_TRUE(https_url.SchemeIs(url::kHttpsScheme));
1414 NavigationObserver observer(WebContents());
1415 scoped_ptr<PromptObserver> prompt_observer(
1416 PromptObserver::Create(WebContents()));
1417 ui_test_utils::NavigateToURL(browser(), https_url);
1419 observer.SetPathToWaitFor("/password/done_and_separate_login_form.html");
1420 observer.Wait();
1422 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
1425 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
1426 PromptWhenPasswordFormWithoutUsernameFieldSubmitted) {
1427 password_manager::TestPasswordStore* password_store =
1428 static_cast<password_manager::TestPasswordStore*>(
1429 PasswordStoreFactory::GetForProfile(
1430 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS).get());
1432 EXPECT_TRUE(password_store->IsEmpty());
1434 NavigateToFile("/password/form_with_only_password_field.html");
1436 NavigationObserver observer(WebContents());
1437 scoped_ptr<PromptObserver> prompt_observer(
1438 PromptObserver::Create(WebContents()));
1439 std::string submit =
1440 "document.getElementById('password').value = 'password';"
1441 "document.getElementById('submit-button').click();";
1442 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit));
1443 observer.Wait();
1445 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1446 prompt_observer->Accept();
1448 // Spin the message loop to make sure the password store had a chance to save
1449 // the password.
1450 base::RunLoop run_loop;
1451 run_loop.RunUntilIdle();
1452 EXPECT_FALSE(password_store->IsEmpty());
1455 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
1456 AutofillSuggetionsForPasswordFormWithoutUsernameField) {
1457 password_manager::TestPasswordStore* password_store =
1458 static_cast<password_manager::TestPasswordStore*>(
1459 PasswordStoreFactory::GetForProfile(
1460 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS).get());
1462 EXPECT_TRUE(password_store->IsEmpty());
1464 // Password form without username-field.
1465 NavigateToFile("/password/form_with_only_password_field.html");
1467 NavigationObserver observer(WebContents());
1468 scoped_ptr<PromptObserver> prompt_observer(
1469 PromptObserver::Create(WebContents()));
1470 std::string submit =
1471 "document.getElementById('password').value = 'mypassword';"
1472 "document.getElementById('submit-button').click();";
1473 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit));
1474 observer.Wait();
1476 prompt_observer->Accept();
1478 // Spin the message loop to make sure the password store had a chance to save
1479 // the password.
1480 base::RunLoop run_loop;
1481 run_loop.RunUntilIdle();
1482 EXPECT_FALSE(password_store->IsEmpty());
1484 // Now, navigate to same html password form and verify whether password is
1485 // autofilled.
1486 NavigateToFile("/password/form_with_only_password_field.html");
1488 // Let the user interact with the page, so that DOM gets modification events,
1489 // needed for autofilling fields.
1490 content::SimulateMouseClickAt(
1491 WebContents(), 0, blink::WebMouseEvent::ButtonLeft, gfx::Point(1, 1));
1493 // Wait until that interaction causes the password value to be revealed.
1494 WaitForElementValue("password", "mypassword");
1497 // Test that if a form gets autofilled, then it gets autofilled on re-creation
1498 // as well.
1499 // TODO(vabr): This is flaky everywhere. http://crbug.com/442704
1500 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
1501 DISABLED_ReCreatedFormsGetFilled) {
1502 NavigateToFile("/password/dynamic_password_form.html");
1504 // Fill in the credentials, and make sure they are saved.
1505 NavigationObserver form_submit_observer(WebContents());
1506 scoped_ptr<PromptObserver> prompt_observer(
1507 PromptObserver::Create(WebContents()));
1508 std::string create_fill_and_submit =
1509 "document.getElementById('create_form_button').click();"
1510 "window.setTimeout(function() {"
1511 " var form = document.getElementById('dynamic_form_id');"
1512 " form.username.value = 'temp';"
1513 " form.password.value = 'random';"
1514 " form.submit();"
1515 "}, 0)";
1516 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), create_fill_and_submit));
1517 form_submit_observer.Wait();
1518 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1519 prompt_observer->Accept();
1521 // Reload the original page to have the saved credentials autofilled.
1522 NavigationObserver reload_observer(WebContents());
1523 NavigateToFile("/password/dynamic_password_form.html");
1524 reload_observer.Wait();
1525 std::string create_form =
1526 "document.getElementById('create_form_button').click();";
1527 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), create_form));
1528 // Wait until the username is filled, to make sure autofill kicked in.
1529 WaitForElementValue("username_id", "temp");
1531 // Now the form gets deleted and created again. It should get autofilled
1532 // again.
1533 std::string delete_form =
1534 "var form = document.getElementById('dynamic_form_id');"
1535 "form.parentNode.removeChild(form);";
1536 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), delete_form));
1537 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), create_form));
1538 WaitForElementValue("username_id", "temp");
1541 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, PromptForPushState) {
1542 ActivateHistoryPushState();
1543 NavigateToFile("/password/password_push_state.html");
1545 // Verify that we show the save password prompt if 'history.pushState()'
1546 // is called after form submission is suppressed by, for example, calling
1547 // preventDefault in a form's submit event handler.
1548 // Note that calling 'submit()' on a form with javascript doesn't call
1549 // the onsubmit handler, so we click the submit button instead.
1550 NavigationObserver observer(WebContents());
1551 observer.SetQuitOnEntryCommitted(true);
1552 scoped_ptr<PromptObserver> prompt_observer(
1553 PromptObserver::Create(WebContents()));
1554 std::string fill_and_submit =
1555 "document.getElementById('username_field').value = 'temp';"
1556 "document.getElementById('password_field').value = 'random';"
1557 "document.getElementById('submit_button').click()";
1558 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1559 observer.Wait();
1560 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1563 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
1564 InFrameNavigationDoesNotClearPopupState) {
1565 // Mock out the AutofillClient so we know how long to wait. Unfortunately
1566 // there isn't otherwise a good even to wait on to verify that the popup
1567 // would have been shown.
1568 password_manager::ContentPasswordManagerDriverFactory* driver_factory =
1569 password_manager::ContentPasswordManagerDriverFactory::FromWebContents(
1570 WebContents());
1571 ObservingAutofillClient observing_autofill_client;
1572 driver_factory->TestingSetDriverForFrame(
1573 RenderViewHost()->GetMainFrame(),
1574 make_scoped_ptr(new password_manager::ContentPasswordManagerDriver(
1575 RenderViewHost()->GetMainFrame(),
1576 ChromePasswordManagerClient::FromWebContents(WebContents()),
1577 &observing_autofill_client)));
1579 NavigateToFile("/password/password_form.html");
1581 NavigationObserver form_submit_observer(WebContents());
1582 scoped_ptr<PromptObserver> prompt_observer(
1583 PromptObserver::Create(WebContents()));
1584 std::string fill =
1585 "document.getElementById('username_field').value = 'temp';"
1586 "document.getElementById('password_field').value = 'random123';"
1587 "document.getElementById('input_submit_button').click();";
1589 // Save credentials for the site.
1590 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill));
1591 form_submit_observer.Wait();
1592 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1593 prompt_observer->Accept();
1595 NavigateToFile("/password/password_form.html");
1596 ASSERT_TRUE(content::ExecuteScript(
1597 RenderViewHost(),
1598 "var usernameRect = document.getElementById('username_field')"
1599 ".getBoundingClientRect();"));
1601 // Trigger in page navigation.
1602 std::string in_page_navigate = "location.hash = '#blah';";
1603 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), in_page_navigate));
1605 // Click on the username field to display the popup.
1606 int top;
1607 ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
1608 RenderViewHost(),
1609 "window.domAutomationController.send(usernameRect.top);",
1610 &top));
1611 int left;
1612 ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
1613 RenderViewHost(),
1614 "window.domAutomationController.send(usernameRect.left);",
1615 &left));
1617 content::SimulateMouseClickAt(
1618 WebContents(), 0, blink::WebMouseEvent::ButtonLeft, gfx::Point(left + 1,
1619 top + 1));
1620 // Make sure the popup would be shown.
1621 observing_autofill_client.Wait();
1624 // Passwords from change password forms should only be offered for saving when
1625 // it is certain that the username is correct.
1626 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, ChangePwdCorrect) {
1627 NavigateToFile("/password/password_form.html");
1629 NavigationObserver observer(WebContents());
1630 scoped_ptr<PromptObserver> prompt_observer(
1631 PromptObserver::Create(WebContents()));
1632 std::string fill_and_submit =
1633 "document.getElementById('mark_chg_username_field').value = 'temp';"
1634 "document.getElementById('mark_chg_password_field').value = 'random';"
1635 "document.getElementById('mark_chg_new_password_1').value = 'random1';"
1636 "document.getElementById('mark_chg_new_password_2').value = 'random1';"
1637 "document.getElementById('mark_chg_submit_button').click()";
1638 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1639 observer.Wait();
1640 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1643 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, ChangePwdIncorrect) {
1644 NavigateToFile("/password/password_form.html");
1646 NavigationObserver observer(WebContents());
1647 scoped_ptr<PromptObserver> prompt_observer(
1648 PromptObserver::Create(WebContents()));
1649 std::string fill_and_submit =
1650 "document.getElementById('chg_not_username_field').value = 'temp';"
1651 "document.getElementById('chg_password_field').value = 'random';"
1652 "document.getElementById('chg_new_password_1').value = 'random1';"
1653 "document.getElementById('chg_new_password_2').value = 'random1';"
1654 "document.getElementById('chg_submit_button').click()";
1655 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1656 observer.Wait();
1657 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
1660 // As the two ChangePwd* tests above, only with submitting through
1661 // history.pushState().
1662 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, ChangePwdPushStateCorrect) {
1663 ActivateHistoryPushState();
1664 NavigateToFile("/password/password_push_state.html");
1666 NavigationObserver observer(WebContents());
1667 observer.SetQuitOnEntryCommitted(true);
1668 scoped_ptr<PromptObserver> prompt_observer(
1669 PromptObserver::Create(WebContents()));
1670 std::string fill_and_submit =
1671 "document.getElementById('mark_chg_username_field').value = 'temp';"
1672 "document.getElementById('mark_chg_password_field').value = 'random';"
1673 "document.getElementById('mark_chg_new_password_1').value = 'random1';"
1674 "document.getElementById('mark_chg_new_password_2').value = 'random1';"
1675 "document.getElementById('mark_chg_submit_button').click()";
1676 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1677 observer.Wait();
1678 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1681 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
1682 ChangePwdPushStateIncorrect) {
1683 ActivateHistoryPushState();
1684 NavigateToFile("/password/password_push_state.html");
1686 NavigationObserver observer(WebContents());
1687 observer.SetQuitOnEntryCommitted(true);
1688 scoped_ptr<PromptObserver> prompt_observer(
1689 PromptObserver::Create(WebContents()));
1690 std::string fill_and_submit =
1691 "document.getElementById('chg_not_username_field').value = 'temp';"
1692 "document.getElementById('chg_password_field').value = 'random';"
1693 "document.getElementById('chg_new_password_1').value = 'random1';"
1694 "document.getElementById('chg_new_password_2').value = 'random1';"
1695 "document.getElementById('chg_submit_button').click()";
1696 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1697 observer.Wait();
1698 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
1701 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, NoPromptOnBack) {
1702 // Go to a successful landing page through submitting first, so that it is
1703 // reachable through going back, and the remembered page transition is form
1704 // submit. There is no need to submit non-empty strings.
1705 NavigateToFile("/password/password_form.html");
1707 NavigationObserver dummy_submit_observer(WebContents());
1708 std::string just_submit =
1709 "document.getElementById('input_submit_button').click()";
1710 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), just_submit));
1711 dummy_submit_observer.Wait();
1713 // Now go to a page with a form again, fill the form, and go back instead of
1714 // submitting it.
1715 NavigateToFile("/password/dummy_submit.html");
1717 NavigationObserver observer(WebContents());
1718 scoped_ptr<PromptObserver> prompt_observer(
1719 PromptObserver::Create(WebContents()));
1720 // The (dummy) submit is necessary to provisionally save the typed password. A
1721 // user typing in the password field would not need to submit to provisionally
1722 // save it, but the script cannot trigger that just by assigning to the
1723 // field's value.
1724 std::string fill_and_back =
1725 "document.getElementById('password_field').value = 'random';"
1726 "document.getElementById('input_submit_button').click();"
1727 "window.history.back();";
1728 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_back));
1729 observer.Wait();
1730 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
1733 // Regression test for http://crbug.com/452306
1734 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
1735 ChangingTextToPasswordFieldOnSignupForm) {
1736 NavigateToFile("/password/signup_form.html");
1738 // In this case, pretend that username_field is actually a password field
1739 // that starts as a text field to simulate placeholder.
1740 NavigationObserver observer(WebContents());
1741 scoped_ptr<PromptObserver> prompt_observer(
1742 PromptObserver::Create(WebContents()));
1743 std::string change_and_submit =
1744 "document.getElementById('other_info').value = 'username';"
1745 "document.getElementById('username_field').type = 'password';"
1746 "document.getElementById('username_field').value = 'mypass';"
1747 "document.getElementById('password_field').value = 'mypass';"
1748 "document.getElementById('testform').submit();";
1749 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), change_and_submit));
1750 observer.Wait();
1751 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1754 // Regression test for http://crbug.com/451631
1755 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
1756 SavingOnManyPasswordFieldsTest) {
1757 // Simulate Macy's registration page, which contains the normal 2 password
1758 // fields for confirming the new password plus 2 more fields for security
1759 // questions and credit card. Make sure that saving works correctly for such
1760 // sites.
1761 NavigateToFile("/password/many_password_signup_form.html");
1763 NavigationObserver observer(WebContents());
1764 scoped_ptr<PromptObserver> prompt_observer(
1765 PromptObserver::Create(WebContents()));
1766 std::string fill_and_submit =
1767 "document.getElementById('username_field').value = 'username';"
1768 "document.getElementById('password_field').value = 'mypass';"
1769 "document.getElementById('confirm_field').value = 'mypass';"
1770 "document.getElementById('security_answer').value = 'hometown';"
1771 "document.getElementById('SSN').value = '1234';"
1772 "document.getElementById('testform').submit();";
1773 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1774 observer.Wait();
1775 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1778 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
1779 SaveWhenIFrameDestroyedOnFormSubmit) {
1780 NavigateToFile("/password/frame_detached_on_submit.html");
1782 // Need to pay attention for a message that XHR has finished since there
1783 // is no navigation to wait for.
1784 content::DOMMessageQueue message_queue;
1786 scoped_ptr<PromptObserver> prompt_observer(
1787 PromptObserver::Create(WebContents()));
1788 std::string fill_and_submit =
1789 "var iframe = document.getElementById('login_iframe');"
1790 "var frame_doc = iframe.contentDocument;"
1791 "frame_doc.getElementById('username_field').value = 'temp';"
1792 "frame_doc.getElementById('password_field').value = 'random';"
1793 "frame_doc.getElementById('submit_button').click();";
1795 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1796 std::string message;
1797 while (message_queue.WaitForMessage(&message)) {
1798 if (message == "\"SUBMISSION_FINISHED\"")
1799 break;
1802 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1805 // Tests that if a site embeds the login and signup forms into one <form>, the
1806 // login form still gets autofilled.
1807 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
1808 AutofillSuggetionsForLoginSignupForm) {
1809 password_manager::TestPasswordStore* password_store =
1810 static_cast<password_manager::TestPasswordStore*>(
1811 PasswordStoreFactory::GetForProfile(
1812 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS).get());
1814 EXPECT_TRUE(password_store->IsEmpty());
1816 NavigateToFile("/password/login_signup_form.html");
1818 NavigationObserver observer(WebContents());
1819 scoped_ptr<PromptObserver> prompt_observer(
1820 PromptObserver::Create(WebContents()));
1821 std::string submit =
1822 "document.getElementById('username').value = 'myusername';"
1823 "document.getElementById('password').value = 'mypassword';"
1824 "document.getElementById('submit').click();";
1825 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit));
1826 observer.Wait();
1828 prompt_observer->Accept();
1830 // Spin the message loop to make sure the password store had a chance to save
1831 // the password.
1832 base::RunLoop run_loop;
1833 run_loop.RunUntilIdle();
1834 EXPECT_FALSE(password_store->IsEmpty());
1836 // Now, navigate to the same html password form and verify whether password is
1837 // autofilled.
1838 NavigateToFile("/password/login_signup_form.html");
1840 // Let the user interact with the page, so that DOM gets modification events,
1841 // needed for autofilling fields.
1842 content::SimulateMouseClickAt(
1843 WebContents(), 0, blink::WebMouseEvent::ButtonLeft, gfx::Point(1, 1));
1845 // Wait until that interaction causes the password value to be revealed.
1846 WaitForElementValue("password", "mypassword");
1849 // Check that we can fill in cases where <base href> is set and the action of
1850 // the form is not set. Regression test for https://crbug.com/360230.
1851 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, BaseTagWithNoActionTest) {
1852 password_manager::TestPasswordStore* password_store =
1853 static_cast<password_manager::TestPasswordStore*>(
1854 PasswordStoreFactory::GetForProfile(
1855 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS).get());
1857 EXPECT_TRUE(password_store->IsEmpty());
1859 NavigateToFile("/password/password_xhr_submit.html");
1861 NavigationObserver observer(WebContents());
1862 scoped_ptr<PromptObserver> prompt_observer(
1863 PromptObserver::Create(WebContents()));
1864 std::string submit =
1865 "document.getElementById('username_field').value = 'myusername';"
1866 "document.getElementById('password_field').value = 'mypassword';"
1867 "document.getElementById('submit_button').click();";
1868 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit));
1869 observer.Wait();
1871 prompt_observer->Accept();
1873 // Spin the message loop to make sure the password store had a chance to save
1874 // the password.
1875 base::RunLoop run_loop;
1876 run_loop.RunUntilIdle();
1877 EXPECT_FALSE(password_store->IsEmpty());
1879 NavigateToFile("/password/password_xhr_submit.html");
1881 // Let the user interact with the page, so that DOM gets modification events,
1882 // needed for autofilling fields.
1883 content::SimulateMouseClickAt(
1884 WebContents(), 0, blink::WebMouseEvent::ButtonLeft, gfx::Point(1, 1));
1886 // Wait until that interaction causes the password value to be revealed.
1887 WaitForElementValue("password_field", "mypassword");