[Extensions] Make extension message bubble factory platform-abstract
[chromium-blink-merge.git] / chrome / browser / password_manager / password_manager_browsertest.cc
blob1bf5e34fbc2cf61e583307933ed89daa4c1463a3
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 DontPromptForPasswordFormWithReadonlyPasswordField) {
1193 NavigateToFile("/password/password_form_with_password_readonly.html");
1195 // Fill a form and submit through a <input type="submit"> button. Nothing
1196 // special.
1197 NavigationObserver observer(WebContents());
1198 scoped_ptr<PromptObserver> prompt_observer(
1199 PromptObserver::Create(WebContents()));
1200 std::string fill_and_submit =
1201 "document.getElementById('username_field').value = 'temp';"
1202 "document.getElementById('password_field').value = 'random';"
1203 "document.getElementById('input_submit_button').click()";
1204 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1205 observer.Wait();
1206 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
1209 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
1210 PromptWhenEnableAutomaticPasswordSavingSwitchIsNotSet) {
1211 NavigateToFile("/password/password_form.html");
1213 // Fill a form and submit through a <input type="submit"> button.
1214 NavigationObserver observer(WebContents());
1215 scoped_ptr<PromptObserver> prompt_observer(
1216 PromptObserver::Create(WebContents()));
1217 std::string fill_and_submit =
1218 "document.getElementById('username_field').value = 'temp';"
1219 "document.getElementById('password_field').value = 'random';"
1220 "document.getElementById('input_submit_button').click()";
1221 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1222 observer.Wait();
1223 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1226 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
1227 DontPromptWhenEnableAutomaticPasswordSavingSwitchIsSet) {
1228 password_manager::TestPasswordStore* password_store =
1229 static_cast<password_manager::TestPasswordStore*>(
1230 PasswordStoreFactory::GetForProfile(
1231 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS).get());
1233 EXPECT_TRUE(password_store->IsEmpty());
1235 NavigateToFile("/password/password_form.html");
1237 // Add the enable-automatic-password-saving switch.
1238 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1239 password_manager::switches::kEnableAutomaticPasswordSaving);
1241 // Fill a form and submit through a <input type="submit"> button.
1242 NavigationObserver observer(WebContents());
1243 scoped_ptr<PromptObserver> prompt_observer(
1244 PromptObserver::Create(WebContents()));
1245 // Make sure that the only passwords saved are the auto-saved ones.
1246 std::string fill_and_submit =
1247 "document.getElementById('username_field').value = 'temp';"
1248 "document.getElementById('password_field').value = 'random';"
1249 "document.getElementById('input_submit_button').click()";
1250 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1251 observer.Wait();
1252 if (chrome::VersionInfo::GetChannel() ==
1253 chrome::VersionInfo::CHANNEL_UNKNOWN) {
1254 // Passwords getting auto-saved, no prompt.
1255 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
1256 EXPECT_FALSE(password_store->IsEmpty());
1257 } else {
1258 // Prompt shown, and no passwords saved automatically.
1259 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1260 EXPECT_TRUE(password_store->IsEmpty());
1264 // Test fix for crbug.com/368690.
1265 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, NoPromptWhenReloading) {
1266 NavigateToFile("/password/password_form.html");
1268 std::string fill =
1269 "document.getElementById('username_redirect').value = 'temp';"
1270 "document.getElementById('password_redirect').value = 'random';";
1271 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill));
1273 NavigationObserver observer(WebContents());
1274 scoped_ptr<PromptObserver> prompt_observer(
1275 PromptObserver::Create(WebContents()));
1276 GURL url = embedded_test_server()->GetURL("/password/password_form.html");
1277 chrome::NavigateParams params(browser(), url,
1278 ui::PAGE_TRANSITION_RELOAD);
1279 ui_test_utils::NavigateToURL(&params);
1280 observer.Wait();
1281 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
1284 // Test that if a form gets dynamically added between the form parsing and
1285 // rendering, and while the main frame still loads, it still is registered, and
1286 // thus saving passwords from it works.
1287 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
1288 FormsAddedBetweenParsingAndRendering) {
1289 NavigateToFile("/password/between_parsing_and_rendering.html");
1291 NavigationObserver observer(WebContents());
1292 scoped_ptr<PromptObserver> prompt_observer(
1293 PromptObserver::Create(WebContents()));
1294 std::string submit =
1295 "document.getElementById('username').value = 'temp';"
1296 "document.getElementById('password').value = 'random';"
1297 "document.getElementById('submit-button').click();";
1298 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit));
1299 observer.Wait();
1301 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1304 // Test that if there was no previous page load then the PasswordManagerDriver
1305 // does not think that there were SSL errors on the current page. The test opens
1306 // a new tab with a URL for which the embedded test server issues a basic auth
1307 // challenge.
1308 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, NoLastLoadGoodLastLoad) {
1309 // Teach the embedded server to handle requests by issuing the basic auth
1310 // challenge.
1311 embedded_test_server()->RegisterRequestHandler(
1312 base::Bind(&HandleTestAuthRequest));
1314 LoginPromptBrowserTestObserver login_observer;
1315 // We need to register to all sources, because the navigation observer we are
1316 // interested in is for a new tab to be opened, and thus does not exist yet.
1317 login_observer.Register(content::NotificationService::AllSources());
1319 password_manager::TestPasswordStore* password_store =
1320 static_cast<password_manager::TestPasswordStore*>(
1321 PasswordStoreFactory::GetForProfile(
1322 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS).get());
1323 EXPECT_TRUE(password_store->IsEmpty());
1325 // Navigate to a page requiring HTTP auth. Wait for the tab to get the correct
1326 // WebContents, but don't wait for navigation, which only finishes after
1327 // authentication.
1328 ui_test_utils::NavigateToURLWithDisposition(
1329 browser(),
1330 embedded_test_server()->GetURL("/basic_auth"),
1331 NEW_FOREGROUND_TAB,
1332 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
1334 content::NavigationController* nav_controller =
1335 &WebContents()->GetController();
1336 NavigationObserver nav_observer(WebContents());
1337 scoped_ptr<PromptObserver> prompt_observer(
1338 PromptObserver::Create(WebContents()));
1339 WindowedAuthNeededObserver auth_needed_observer(nav_controller);
1340 auth_needed_observer.Wait();
1342 WindowedAuthSuppliedObserver auth_supplied_observer(nav_controller);
1343 // Offer valid credentials on the auth challenge.
1344 ASSERT_EQ(1u, login_observer.handlers().size());
1345 LoginHandler* handler = *login_observer.handlers().begin();
1346 ASSERT_TRUE(handler);
1347 // Any username/password will work.
1348 handler->SetAuth(base::UTF8ToUTF16("user"), base::UTF8ToUTF16("pwd"));
1349 auth_supplied_observer.Wait();
1351 // The password manager should be working correctly.
1352 nav_observer.Wait();
1353 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1354 prompt_observer->Accept();
1356 // Spin the message loop to make sure the password store had a chance to save
1357 // the password.
1358 base::RunLoop run_loop;
1359 run_loop.RunUntilIdle();
1360 EXPECT_FALSE(password_store->IsEmpty());
1363 // In some situations, multiple PasswordFormManager instances from
1364 // PasswordManager::pending_login_managers_ would match (via DoesManage) a form
1365 // to be provisionally saved. One of them might be a complete match, the other
1366 // all-but-action match. Normally, the former should be preferred, but if the
1367 // former has not finished matching, and the latter has, the latter should be
1368 // used (otherwise we'd give up even though we could have saved the password).
1369 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
1370 PreferPasswordFormManagerWhichFinishedMatching) {
1371 NavigateToFile("/password/create_form_copy_on_submit.html");
1373 NavigationObserver observer(WebContents());
1374 scoped_ptr<PromptObserver> prompt_observer(
1375 PromptObserver::Create(WebContents()));
1376 std::string submit =
1377 "document.getElementById('username').value = 'overwrite_me';"
1378 "document.getElementById('password').value = 'random';"
1379 "document.getElementById('non-form-button').click();";
1380 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit));
1381 observer.Wait();
1383 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1386 // Test that if login fails and content server pushes a different login form
1387 // with action URL having different schemes. Heuristic shall be able
1388 // identify such cases and *shall not* prompt to save incorrect password.
1389 IN_PROC_BROWSER_TEST_F(
1390 PasswordManagerBrowserTest,
1391 NoPromptForLoginFailedAndServerPushSeperateLoginForm_HttpToHttps) {
1392 std::string path =
1393 "/password/separate_login_form_with_onload_submit_script.html";
1394 GURL http_url(embedded_test_server()->GetURL(path));
1395 ASSERT_TRUE(http_url.SchemeIs(url::kHttpScheme));
1397 NavigationObserver observer(WebContents());
1398 scoped_ptr<PromptObserver> prompt_observer(
1399 PromptObserver::Create(WebContents()));
1400 ui_test_utils::NavigateToURL(browser(), http_url);
1402 observer.SetPathToWaitFor("/password/done_and_separate_login_form.html");
1403 observer.Wait();
1405 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
1408 IN_PROC_BROWSER_TEST_F(
1409 PasswordManagerBrowserTest,
1410 NoPromptForLoginFailedAndServerPushSeperateLoginForm_HttpsToHttp) {
1411 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1412 switches::kAllowRunningInsecureContent);
1413 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1414 switches::kIgnoreCertificateErrors);
1415 const base::FilePath::CharType kDocRoot[] =
1416 FILE_PATH_LITERAL("chrome/test/data");
1417 net::SpawnedTestServer https_test_server(
1418 net::SpawnedTestServer::TYPE_HTTPS,
1419 net::SpawnedTestServer::SSLOptions(
1420 net::SpawnedTestServer::SSLOptions::CERT_OK),
1421 base::FilePath(kDocRoot));
1422 ASSERT_TRUE(https_test_server.Start());
1424 // This test case cannot inject the scripts via content::ExecuteScript() in
1425 // files served through HTTPS. Therefore the scripts are made part of the HTML
1426 // site and executed on load.
1427 std::string path =
1428 "password/separate_login_form_with_onload_submit_script.html";
1429 GURL https_url(https_test_server.GetURL(path));
1430 ASSERT_TRUE(https_url.SchemeIs(url::kHttpsScheme));
1432 NavigationObserver observer(WebContents());
1433 scoped_ptr<PromptObserver> prompt_observer(
1434 PromptObserver::Create(WebContents()));
1435 ui_test_utils::NavigateToURL(browser(), https_url);
1437 observer.SetPathToWaitFor("/password/done_and_separate_login_form.html");
1438 observer.Wait();
1440 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
1443 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
1444 PromptWhenPasswordFormWithoutUsernameFieldSubmitted) {
1445 password_manager::TestPasswordStore* password_store =
1446 static_cast<password_manager::TestPasswordStore*>(
1447 PasswordStoreFactory::GetForProfile(
1448 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS).get());
1450 EXPECT_TRUE(password_store->IsEmpty());
1452 NavigateToFile("/password/form_with_only_password_field.html");
1454 NavigationObserver observer(WebContents());
1455 scoped_ptr<PromptObserver> prompt_observer(
1456 PromptObserver::Create(WebContents()));
1457 std::string submit =
1458 "document.getElementById('password').value = 'password';"
1459 "document.getElementById('submit-button').click();";
1460 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit));
1461 observer.Wait();
1463 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1464 prompt_observer->Accept();
1466 // Spin the message loop to make sure the password store had a chance to save
1467 // the password.
1468 base::RunLoop run_loop;
1469 run_loop.RunUntilIdle();
1470 EXPECT_FALSE(password_store->IsEmpty());
1473 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
1474 AutofillSuggetionsForPasswordFormWithoutUsernameField) {
1475 password_manager::TestPasswordStore* password_store =
1476 static_cast<password_manager::TestPasswordStore*>(
1477 PasswordStoreFactory::GetForProfile(
1478 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS).get());
1480 EXPECT_TRUE(password_store->IsEmpty());
1482 // Password form without username-field.
1483 NavigateToFile("/password/form_with_only_password_field.html");
1485 NavigationObserver observer(WebContents());
1486 scoped_ptr<PromptObserver> prompt_observer(
1487 PromptObserver::Create(WebContents()));
1488 std::string submit =
1489 "document.getElementById('password').value = 'mypassword';"
1490 "document.getElementById('submit-button').click();";
1491 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit));
1492 observer.Wait();
1494 prompt_observer->Accept();
1496 // Spin the message loop to make sure the password store had a chance to save
1497 // the password.
1498 base::RunLoop run_loop;
1499 run_loop.RunUntilIdle();
1500 EXPECT_FALSE(password_store->IsEmpty());
1502 // Now, navigate to same html password form and verify whether password is
1503 // autofilled.
1504 NavigateToFile("/password/form_with_only_password_field.html");
1506 // Let the user interact with the page, so that DOM gets modification events,
1507 // needed for autofilling fields.
1508 content::SimulateMouseClickAt(
1509 WebContents(), 0, blink::WebMouseEvent::ButtonLeft, gfx::Point(1, 1));
1511 // Wait until that interaction causes the password value to be revealed.
1512 WaitForElementValue("password", "mypassword");
1515 // Test that if a form gets autofilled, then it gets autofilled on re-creation
1516 // as well.
1517 // TODO(vabr): This is flaky everywhere. http://crbug.com/442704
1518 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
1519 DISABLED_ReCreatedFormsGetFilled) {
1520 NavigateToFile("/password/dynamic_password_form.html");
1522 // Fill in the credentials, and make sure they are saved.
1523 NavigationObserver form_submit_observer(WebContents());
1524 scoped_ptr<PromptObserver> prompt_observer(
1525 PromptObserver::Create(WebContents()));
1526 std::string create_fill_and_submit =
1527 "document.getElementById('create_form_button').click();"
1528 "window.setTimeout(function() {"
1529 " var form = document.getElementById('dynamic_form_id');"
1530 " form.username.value = 'temp';"
1531 " form.password.value = 'random';"
1532 " form.submit();"
1533 "}, 0)";
1534 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), create_fill_and_submit));
1535 form_submit_observer.Wait();
1536 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1537 prompt_observer->Accept();
1539 // Reload the original page to have the saved credentials autofilled.
1540 NavigationObserver reload_observer(WebContents());
1541 NavigateToFile("/password/dynamic_password_form.html");
1542 reload_observer.Wait();
1543 std::string create_form =
1544 "document.getElementById('create_form_button').click();";
1545 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), create_form));
1546 // Wait until the username is filled, to make sure autofill kicked in.
1547 WaitForElementValue("username_id", "temp");
1549 // Now the form gets deleted and created again. It should get autofilled
1550 // again.
1551 std::string delete_form =
1552 "var form = document.getElementById('dynamic_form_id');"
1553 "form.parentNode.removeChild(form);";
1554 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), delete_form));
1555 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), create_form));
1556 WaitForElementValue("username_id", "temp");
1559 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, PromptForPushState) {
1560 ActivateHistoryPushState();
1561 NavigateToFile("/password/password_push_state.html");
1563 // Verify that we show the save password prompt if 'history.pushState()'
1564 // is called after form submission is suppressed by, for example, calling
1565 // preventDefault in a form's submit event handler.
1566 // Note that calling 'submit()' on a form with javascript doesn't call
1567 // the onsubmit handler, so we click the submit button instead.
1568 NavigationObserver observer(WebContents());
1569 observer.SetQuitOnEntryCommitted(true);
1570 scoped_ptr<PromptObserver> prompt_observer(
1571 PromptObserver::Create(WebContents()));
1572 std::string fill_and_submit =
1573 "document.getElementById('username_field').value = 'temp';"
1574 "document.getElementById('password_field').value = 'random';"
1575 "document.getElementById('submit_button').click()";
1576 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1577 observer.Wait();
1578 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1581 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
1582 InFrameNavigationDoesNotClearPopupState) {
1583 // Mock out the AutofillClient so we know how long to wait. Unfortunately
1584 // there isn't otherwise a good even to wait on to verify that the popup
1585 // would have been shown.
1586 password_manager::ContentPasswordManagerDriverFactory* driver_factory =
1587 password_manager::ContentPasswordManagerDriverFactory::FromWebContents(
1588 WebContents());
1589 ObservingAutofillClient observing_autofill_client;
1590 driver_factory->TestingSetDriverForFrame(
1591 RenderViewHost()->GetMainFrame(),
1592 make_scoped_ptr(new password_manager::ContentPasswordManagerDriver(
1593 RenderViewHost()->GetMainFrame(),
1594 ChromePasswordManagerClient::FromWebContents(WebContents()),
1595 &observing_autofill_client)));
1597 NavigateToFile("/password/password_form.html");
1599 NavigationObserver form_submit_observer(WebContents());
1600 scoped_ptr<PromptObserver> prompt_observer(
1601 PromptObserver::Create(WebContents()));
1602 std::string fill =
1603 "document.getElementById('username_field').value = 'temp';"
1604 "document.getElementById('password_field').value = 'random123';"
1605 "document.getElementById('input_submit_button').click();";
1607 // Save credentials for the site.
1608 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill));
1609 form_submit_observer.Wait();
1610 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1611 prompt_observer->Accept();
1613 NavigateToFile("/password/password_form.html");
1614 ASSERT_TRUE(content::ExecuteScript(
1615 RenderViewHost(),
1616 "var usernameRect = document.getElementById('username_field')"
1617 ".getBoundingClientRect();"));
1619 // Trigger in page navigation.
1620 std::string in_page_navigate = "location.hash = '#blah';";
1621 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), in_page_navigate));
1623 // Click on the username field to display the popup.
1624 int top;
1625 ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
1626 RenderViewHost(),
1627 "window.domAutomationController.send(usernameRect.top);",
1628 &top));
1629 int left;
1630 ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
1631 RenderViewHost(),
1632 "window.domAutomationController.send(usernameRect.left);",
1633 &left));
1635 content::SimulateMouseClickAt(
1636 WebContents(), 0, blink::WebMouseEvent::ButtonLeft, gfx::Point(left + 1,
1637 top + 1));
1638 // Make sure the popup would be shown.
1639 observing_autofill_client.Wait();
1642 // Passwords from change password forms should only be offered for saving when
1643 // it is certain that the username is correct.
1644 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, ChangePwdCorrect) {
1645 NavigateToFile("/password/password_form.html");
1647 NavigationObserver observer(WebContents());
1648 scoped_ptr<PromptObserver> prompt_observer(
1649 PromptObserver::Create(WebContents()));
1650 std::string fill_and_submit =
1651 "document.getElementById('mark_chg_username_field').value = 'temp';"
1652 "document.getElementById('mark_chg_password_field').value = 'random';"
1653 "document.getElementById('mark_chg_new_password_1').value = 'random1';"
1654 "document.getElementById('mark_chg_new_password_2').value = 'random1';"
1655 "document.getElementById('mark_chg_submit_button').click()";
1656 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1657 observer.Wait();
1658 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1661 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, ChangePwdIncorrect) {
1662 NavigateToFile("/password/password_form.html");
1664 NavigationObserver observer(WebContents());
1665 scoped_ptr<PromptObserver> prompt_observer(
1666 PromptObserver::Create(WebContents()));
1667 std::string fill_and_submit =
1668 "document.getElementById('chg_not_username_field').value = 'temp';"
1669 "document.getElementById('chg_password_field').value = 'random';"
1670 "document.getElementById('chg_new_password_1').value = 'random1';"
1671 "document.getElementById('chg_new_password_2').value = 'random1';"
1672 "document.getElementById('chg_submit_button').click()";
1673 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1674 observer.Wait();
1675 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
1678 // As the two ChangePwd* tests above, only with submitting through
1679 // history.pushState().
1680 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, ChangePwdPushStateCorrect) {
1681 ActivateHistoryPushState();
1682 NavigateToFile("/password/password_push_state.html");
1684 NavigationObserver observer(WebContents());
1685 observer.SetQuitOnEntryCommitted(true);
1686 scoped_ptr<PromptObserver> prompt_observer(
1687 PromptObserver::Create(WebContents()));
1688 std::string fill_and_submit =
1689 "document.getElementById('mark_chg_username_field').value = 'temp';"
1690 "document.getElementById('mark_chg_password_field').value = 'random';"
1691 "document.getElementById('mark_chg_new_password_1').value = 'random1';"
1692 "document.getElementById('mark_chg_new_password_2').value = 'random1';"
1693 "document.getElementById('mark_chg_submit_button').click()";
1694 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1695 observer.Wait();
1696 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1699 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
1700 ChangePwdPushStateIncorrect) {
1701 ActivateHistoryPushState();
1702 NavigateToFile("/password/password_push_state.html");
1704 NavigationObserver observer(WebContents());
1705 observer.SetQuitOnEntryCommitted(true);
1706 scoped_ptr<PromptObserver> prompt_observer(
1707 PromptObserver::Create(WebContents()));
1708 std::string fill_and_submit =
1709 "document.getElementById('chg_not_username_field').value = 'temp';"
1710 "document.getElementById('chg_password_field').value = 'random';"
1711 "document.getElementById('chg_new_password_1').value = 'random1';"
1712 "document.getElementById('chg_new_password_2').value = 'random1';"
1713 "document.getElementById('chg_submit_button').click()";
1714 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1715 observer.Wait();
1716 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
1719 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, NoPromptOnBack) {
1720 // Go to a successful landing page through submitting first, so that it is
1721 // reachable through going back, and the remembered page transition is form
1722 // submit. There is no need to submit non-empty strings.
1723 NavigateToFile("/password/password_form.html");
1725 NavigationObserver dummy_submit_observer(WebContents());
1726 std::string just_submit =
1727 "document.getElementById('input_submit_button').click()";
1728 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), just_submit));
1729 dummy_submit_observer.Wait();
1731 // Now go to a page with a form again, fill the form, and go back instead of
1732 // submitting it.
1733 NavigateToFile("/password/dummy_submit.html");
1735 NavigationObserver observer(WebContents());
1736 scoped_ptr<PromptObserver> prompt_observer(
1737 PromptObserver::Create(WebContents()));
1738 // The (dummy) submit is necessary to provisionally save the typed password. A
1739 // user typing in the password field would not need to submit to provisionally
1740 // save it, but the script cannot trigger that just by assigning to the
1741 // field's value.
1742 std::string fill_and_back =
1743 "document.getElementById('password_field').value = 'random';"
1744 "document.getElementById('input_submit_button').click();"
1745 "window.history.back();";
1746 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_back));
1747 observer.Wait();
1748 EXPECT_FALSE(prompt_observer->IsShowingPrompt());
1751 // Regression test for http://crbug.com/452306
1752 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
1753 ChangingTextToPasswordFieldOnSignupForm) {
1754 NavigateToFile("/password/signup_form.html");
1756 // In this case, pretend that username_field is actually a password field
1757 // that starts as a text field to simulate placeholder.
1758 NavigationObserver observer(WebContents());
1759 scoped_ptr<PromptObserver> prompt_observer(
1760 PromptObserver::Create(WebContents()));
1761 std::string change_and_submit =
1762 "document.getElementById('other_info').value = 'username';"
1763 "document.getElementById('username_field').type = 'password';"
1764 "document.getElementById('username_field').value = 'mypass';"
1765 "document.getElementById('password_field').value = 'mypass';"
1766 "document.getElementById('testform').submit();";
1767 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), change_and_submit));
1768 observer.Wait();
1769 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1772 // Regression test for http://crbug.com/451631
1773 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
1774 SavingOnManyPasswordFieldsTest) {
1775 // Simulate Macy's registration page, which contains the normal 2 password
1776 // fields for confirming the new password plus 2 more fields for security
1777 // questions and credit card. Make sure that saving works correctly for such
1778 // sites.
1779 NavigateToFile("/password/many_password_signup_form.html");
1781 NavigationObserver observer(WebContents());
1782 scoped_ptr<PromptObserver> prompt_observer(
1783 PromptObserver::Create(WebContents()));
1784 std::string fill_and_submit =
1785 "document.getElementById('username_field').value = 'username';"
1786 "document.getElementById('password_field').value = 'mypass';"
1787 "document.getElementById('confirm_field').value = 'mypass';"
1788 "document.getElementById('security_answer').value = 'hometown';"
1789 "document.getElementById('SSN').value = '1234';"
1790 "document.getElementById('testform').submit();";
1791 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1792 observer.Wait();
1793 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1796 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
1797 SaveWhenIFrameDestroyedOnFormSubmit) {
1798 NavigateToFile("/password/frame_detached_on_submit.html");
1800 // Need to pay attention for a message that XHR has finished since there
1801 // is no navigation to wait for.
1802 content::DOMMessageQueue message_queue;
1804 scoped_ptr<PromptObserver> prompt_observer(
1805 PromptObserver::Create(WebContents()));
1806 std::string fill_and_submit =
1807 "var iframe = document.getElementById('login_iframe');"
1808 "var frame_doc = iframe.contentDocument;"
1809 "frame_doc.getElementById('username_field').value = 'temp';"
1810 "frame_doc.getElementById('password_field').value = 'random';"
1811 "frame_doc.getElementById('submit_button').click();";
1813 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
1814 std::string message;
1815 while (message_queue.WaitForMessage(&message)) {
1816 if (message == "\"SUBMISSION_FINISHED\"")
1817 break;
1820 EXPECT_TRUE(prompt_observer->IsShowingPrompt());
1823 // Tests that if a site embeds the login and signup forms into one <form>, the
1824 // login form still gets autofilled.
1825 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
1826 AutofillSuggetionsForLoginSignupForm) {
1827 password_manager::TestPasswordStore* password_store =
1828 static_cast<password_manager::TestPasswordStore*>(
1829 PasswordStoreFactory::GetForProfile(
1830 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS).get());
1832 EXPECT_TRUE(password_store->IsEmpty());
1834 NavigateToFile("/password/login_signup_form.html");
1836 NavigationObserver observer(WebContents());
1837 scoped_ptr<PromptObserver> prompt_observer(
1838 PromptObserver::Create(WebContents()));
1839 std::string submit =
1840 "document.getElementById('username').value = 'myusername';"
1841 "document.getElementById('password').value = 'mypassword';"
1842 "document.getElementById('submit').click();";
1843 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit));
1844 observer.Wait();
1846 prompt_observer->Accept();
1848 // Spin the message loop to make sure the password store had a chance to save
1849 // the password.
1850 base::RunLoop run_loop;
1851 run_loop.RunUntilIdle();
1852 EXPECT_FALSE(password_store->IsEmpty());
1854 // Now, navigate to the same html password form and verify whether password is
1855 // autofilled.
1856 NavigateToFile("/password/login_signup_form.html");
1858 // Let the user interact with the page, so that DOM gets modification events,
1859 // needed for autofilling fields.
1860 content::SimulateMouseClickAt(
1861 WebContents(), 0, blink::WebMouseEvent::ButtonLeft, gfx::Point(1, 1));
1863 // Wait until that interaction causes the password value to be revealed.
1864 WaitForElementValue("password", "mypassword");
1867 // Check that we can fill in cases where <base href> is set and the action of
1868 // the form is not set. Regression test for https://crbug.com/360230.
1869 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, BaseTagWithNoActionTest) {
1870 password_manager::TestPasswordStore* password_store =
1871 static_cast<password_manager::TestPasswordStore*>(
1872 PasswordStoreFactory::GetForProfile(
1873 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS).get());
1875 EXPECT_TRUE(password_store->IsEmpty());
1877 NavigateToFile("/password/password_xhr_submit.html");
1879 NavigationObserver observer(WebContents());
1880 scoped_ptr<PromptObserver> prompt_observer(
1881 PromptObserver::Create(WebContents()));
1882 std::string submit =
1883 "document.getElementById('username_field').value = 'myusername';"
1884 "document.getElementById('password_field').value = 'mypassword';"
1885 "document.getElementById('submit_button').click();";
1886 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit));
1887 observer.Wait();
1889 prompt_observer->Accept();
1891 // Spin the message loop to make sure the password store had a chance to save
1892 // the password.
1893 base::RunLoop run_loop;
1894 run_loop.RunUntilIdle();
1895 EXPECT_FALSE(password_store->IsEmpty());
1897 NavigateToFile("/password/password_xhr_submit.html");
1899 // Let the user interact with the page, so that DOM gets modification events,
1900 // needed for autofilling fields.
1901 content::SimulateMouseClickAt(
1902 WebContents(), 0, blink::WebMouseEvent::ButtonLeft, gfx::Point(1, 1));
1904 // Wait until that interaction causes the password value to be revealed.
1905 WaitForElementValue("password_field", "mypassword");