Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(307)

Side by Side Diff: chrome/browser/password_manager/credential_manager_browsertest.cc

Issue 2947413002: Restrict CM API interface request and message dispatch. (Closed)
Patch Set: Addressed comments from rockot@. Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/macros.h" 5 #include "base/macros.h"
6 #include "base/run_loop.h"
vasilii 2017/07/03 13:59:47 unused
engedy 2017/07/03 14:31:12 Done.
6 #include "base/stl_util.h" 7 #include "base/stl_util.h"
8 #include "base/strings/stringprintf.h"
7 #include "base/strings/utf_string_conversions.h" 9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/password_manager/chrome_password_manager_client.h"
8 #include "chrome/browser/password_manager/password_manager_test_base.h" 11 #include "chrome/browser/password_manager/password_manager_test_base.h"
9 #include "chrome/browser/password_manager/password_store_factory.h" 12 #include "chrome/browser/password_manager/password_store_factory.h"
10 #include "chrome/browser/profiles/profile.h" 13 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/profiles/profile_io_data.h" 14 #include "chrome/browser/profiles/profile_io_data.h"
12 #include "chrome/browser/ui/browser.h" 15 #include "chrome/browser/ui/browser.h"
13 #include "chrome/browser/ui/passwords/passwords_model_delegate.h" 16 #include "chrome/browser/ui/passwords/passwords_model_delegate.h"
17 #include "chrome/browser/ui/tabs/tab_strip_model.h"
14 #include "chrome/test/base/ui_test_utils.h" 18 #include "chrome/test/base/ui_test_utils.h"
15 #include "components/password_manager/core/browser/password_bubble_experiment.h" 19 #include "components/password_manager/core/browser/password_bubble_experiment.h"
16 #include "components/password_manager/core/browser/test_password_store.h" 20 #include "components/password_manager/core/browser/test_password_store.h"
21 #include "content/public/browser/web_contents.h"
22 #include "content/public/browser/web_contents_observer.h"
17 #include "content/public/test/browser_test.h" 23 #include "content/public/test/browser_test.h"
18 #include "content/public/test/browser_test_utils.h" 24 #include "content/public/test/browser_test_utils.h"
19 #include "net/dns/mock_host_resolver.h" 25 #include "net/dns/mock_host_resolver.h"
20 26
21 namespace { 27 namespace {
22 28
23 class CredentialManagerBrowserTest : public PasswordManagerBrowserTestBase { 29 class CredentialManagerBrowserTest : public PasswordManagerBrowserTestBase {
24 public: 30 public:
25 CredentialManagerBrowserTest() = default; 31 CredentialManagerBrowserTest() = default;
26 32
27 void SetUpOnMainThread() override { 33 void SetUpOnMainThread() override {
28 PasswordManagerBrowserTestBase::SetUpOnMainThread(); 34 PasswordManagerBrowserTestBase::SetUpOnMainThread();
29 // Redirect all requests to localhost. 35 // Redirect all requests to localhost.
30 host_resolver()->AddRule("*", "127.0.0.1"); 36 host_resolver()->AddRule("*", "127.0.0.1");
31 } 37 }
32 38
33 bool IsShowingAccountChooser() { 39 bool IsShowingAccountChooser() {
34 return PasswordsModelDelegateFromWebContents(WebContents())-> 40 return PasswordsModelDelegateFromWebContents(WebContents())->GetState() ==
35 GetState() == password_manager::ui::CREDENTIAL_REQUEST_STATE; 41 password_manager::ui::CREDENTIAL_REQUEST_STATE;
36 } 42 }
37 43
38 // Similarly to PasswordManagerBrowserTestBase::NavigateToFile this is a 44 // Similarly to PasswordManagerBrowserTestBase::NavigateToFile this is a
39 // wrapper around ui_test_utils::NavigateURL that waits until DidFinishLoad() 45 // wrapper around ui_test_utils::NavigateURL that waits until DidFinishLoad()
40 // fires. Different to NavigateToFile this method allows passing a test_server 46 // fires. Different to NavigateToFile this method allows passing a test_server
41 // and modifications to the hostname. 47 // and modifications to the hostname.
42 void NavigateToURL(const net::EmbeddedTestServer& test_server, 48 void NavigateToURL(const net::EmbeddedTestServer& test_server,
43 const std::string& hostname, 49 const std::string& hostname,
44 const std::string& relative_url) { 50 const std::string& relative_url) {
45 NavigationObserver observer(WebContents()); 51 NavigationObserver observer(WebContents());
46 GURL url = test_server.GetURL(hostname, relative_url); 52 GURL url = test_server.GetURL(hostname, relative_url);
47 ui_test_utils::NavigateToURL(browser(), url); 53 ui_test_utils::NavigateToURL(browser(), url);
48 observer.Wait(); 54 observer.Wait();
49 } 55 }
50 56
57 // Triggers a call to `navigator.credentials.get` to retrieve passwords, waits
58 // for success, and ASSERTs that |expect_has_results| is satisfied.
59 void TriggerNavigatorGetPasswordCredentialsAndExpectHasResult(
60 content::WebContents* web_contents,
61 bool expect_has_results) {
62 bool result = false;
63 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
64 web_contents,
65 "navigator.credentials.get({password: true}).then(c => {"
66 " window.domAutomationController.send(!!c);"
67 "});",
68 &result));
69 ASSERT_EQ(expect_has_results, result);
70 }
71
72 // Schedules a call to be made to navigator.credentials.store() in the
73 // `unload` handler to save a credential with |username| and |password|.
74 void ScheduleNavigatorStoreCredentialAtUnload(
75 content::WebContents* web_contents,
76 const char* username,
77 const char* password) {
78 ASSERT_TRUE(content::ExecuteScript(
79 web_contents,
80 base::StringPrintf(
81 "window.addEventListener(\"unload\", () => {"
82 " var c = new PasswordCredential({ id: '%s', password: '%s' });"
83 " navigator.credentials.store(c);"
84 "});",
85 username, password)));
86 }
87
88 // Tests the when navigator.credentials.store() is called in an `unload`
vasilii 2017/07/03 13:59:47 Tests the when?
engedy 2017/07/03 14:31:13 Sorry, typo. Fixed.
89 // handler before a same-RenderFrame navigation, the request is guaranteed to
90 // be serviced in the context of the initial document.
91 //
92 // If |preestablish_mojo_pipe| is set, then the CredentialManagerClient will
93 // establish the Mojo connection to the CredentialManagerImpl ahead of time,
94 // instead of letting the Mojo connection be established on-demand when the
95 // call to store() triggered from the unload handler.
96 void TestStoreInUnloadHandlerForSameSiteNavigation(
97 bool preestablish_mojo_pipe) {
98 // Use URLs that differ on subdomains so we can tell which one was used for
99 // saving, but they still belong to the same SiteInstance, so they will be
100 // renderered in the same RenderFrame (in the same process).
101 const GURL a_url1 = https_test_server().GetURL("foo.a.com", "/title1.html");
102 const GURL a_url2 = https_test_server().GetURL("bar.a.com", "/title2.html");
103
104 // Navigate to a mostly empty page.
105 ui_test_utils::NavigateToURL(browser(), a_url1);
106
107 ChromePasswordManagerClient* client =
108 ChromePasswordManagerClient::FromWebContents(WebContents());
109
110 if (preestablish_mojo_pipe) {
111 EXPECT_FALSE(client->has_binding_for_credential_manager());
112 ASSERT_NO_FATAL_FAILURE(
113 TriggerNavigatorGetPasswordCredentialsAndExpectHasResult(
114 WebContents(), false));
115 EXPECT_TRUE(client->has_binding_for_credential_manager());
116 }
117
118 // Schedule storing a credential on the `unload` event.
119 ASSERT_NO_FATAL_FAILURE(ScheduleNavigatorStoreCredentialAtUnload(
120 WebContents(), "user", "hunter2"));
121
122 // Trigger a same-site navigation carried out in the same RenderFrame.
123 content::RenderFrameHost* old_rfh = WebContents()->GetMainFrame();
124 ui_test_utils::NavigateToURL(browser(), a_url2);
125 ASSERT_EQ(old_rfh, WebContents()->GetMainFrame());
126
127 // Ensure that the old document no longer has a Mojo connection to the
128 // CredentialManagerImpl, nor can it get one later.
129 //
130 // FrameLoader::PrepareForCommit had already shut down the old Document
131 // before the provisional load could be commited in the renderer, so new
132 // InterfaceRequests cannot be issued anymore.
vasilii 2017/07/03 13:59:47 As I understand, it's all due to the same origin n
engedy 2017/07/03 14:31:12 I have clarified.
133 //
134 // Furthermore, because the AssociatedInterfaceRegistry, through which the
135 // associated interface to the CredentialManagerImpl is retrieved, is itself
136 // Channel-associated, an InterfaceRequest message that may have been issued
137 // before the load was committed on the renderer side will be guaranteed to
138 // arrive before FrameHostMsg_DidCommitProvisionalLoad.
139 //
140 // Hence it is sufficient to check that the Mojo connection is closed now.
141 EXPECT_FALSE(client->has_binding_for_credential_manager());
142
143 // Ensure that the navigator.credentials.store() call was serviced in the
144 // context of the old URL, |a_url|.
145 //
146 // The CredentialManager Mojo interface is Channel-associated, so message
147 // ordering with legacy IPC messages is preserved. Therefore, servicing the
148 // store() called from the `unload` handler, triggered from
149 // FrameLoader::PrepareForCommit, will be serviced before
150 // FrameHostMsg_DidCommitProvisionalLoad, thus before DidFinishNavigation,
151 ASSERT_TRUE(client->was_store_ever_called());
152
153 BubbleObserver prompt_observer(WebContents());
154 prompt_observer.WaitForSavePrompt();
155 ASSERT_TRUE(prompt_observer.IsShowingSavePrompt());
156 prompt_observer.AcceptSavePrompt();
157
158 WaitForPasswordStore();
159
160 password_manager::TestPasswordStore* test_password_store =
161 static_cast<password_manager::TestPasswordStore*>(
162 PasswordStoreFactory::GetForProfile(
163 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS)
164 .get());
165
166 ASSERT_EQ(1u, test_password_store->stored_passwords().size());
167 autofill::PasswordForm signin_form =
168 test_password_store->stored_passwords().begin()->second[0];
169 EXPECT_EQ(base::ASCIIToUTF16("user"), signin_form.username_value);
170 EXPECT_EQ(base::ASCIIToUTF16("hunter2"), signin_form.password_value);
171 EXPECT_EQ(a_url1.GetOrigin(), signin_form.origin);
172 }
173
174 // Tests the when navigator.credentials.store() is called in an `unload`
175 // handler before a cross-site transfer navigation, the request is ignored.
176 //
177 // If |preestablish_mojo_pipe| is set, then the CredentialManagerClient will
178 // establish the Mojo connection to the CredentialManagerImpl ahead of time,
179 // instead of letting the Mojo connection be established on-demand when the
180 // call to store() triggered from the unload handler.
181 void TestStoreInUnloadHandlerForCrossSiteNavigation(
182 bool preestablish_mojo_pipe) {
183 const GURL a_url = https_test_server().GetURL("a.com", "/title1.html");
184 const GURL b_url = https_test_server().GetURL("b.com", "/title2.html");
185
186 // Navigate to a mostly empty page.
187 ui_test_utils::NavigateToURL(browser(), a_url);
188
189 ChromePasswordManagerClient* client =
190 ChromePasswordManagerClient::FromWebContents(WebContents());
191
192 if (preestablish_mojo_pipe) {
193 EXPECT_FALSE(client->has_binding_for_credential_manager());
194 ASSERT_NO_FATAL_FAILURE(
195 TriggerNavigatorGetPasswordCredentialsAndExpectHasResult(
196 WebContents(), false));
197 EXPECT_TRUE(client->has_binding_for_credential_manager());
198 }
199
200 // Schedule storing a credential on the `unload` event.
201 ASSERT_NO_FATAL_FAILURE(ScheduleNavigatorStoreCredentialAtUnload(
202 WebContents(), "user", "hunter2"));
203
204 // Trigger a cross-site navigation that is carried out in a new renderer,
205 // and which will swap out the old RenderFrameHost.
206 content::RenderFrameDeletedObserver rfh_destruction_observer(
207 WebContents()->GetMainFrame());
208 ui_test_utils::NavigateToURL(browser(), b_url);
209
210 // Ensure that the navigator.credentials.store() call is never serviced.
211 // The sufficient conditions for this are:
212 // -- The swapped out RFH is destroyed, so the RenderFrame cannot
213 // establish a new Mojo connection to CredentialManagerImpl anymore.
214 // -- There is no already existing Mojo connection to CredentialManagerImpl
215 // either, which could be used to call store() in the future.
216 // -- There have not been any calls to store() in the past.
217 rfh_destruction_observer.WaitUntilDeleted();
vasilii 2017/07/03 13:59:47 I wonder if it's possible that NavigateToURL doesn
engedy 2017/07/03 14:31:12 Yes, it can happen, as the swapped out RFH is put
218 EXPECT_FALSE(client->has_binding_for_credential_manager());
219 EXPECT_FALSE(client->was_store_ever_called());
220 }
221
51 private: 222 private:
52 DISALLOW_COPY_AND_ASSIGN(CredentialManagerBrowserTest); 223 DISALLOW_COPY_AND_ASSIGN(CredentialManagerBrowserTest);
53 }; 224 };
54 225
55 // Tests. 226 // Tests.
56 227
57 IN_PROC_BROWSER_TEST_F(CredentialManagerBrowserTest, 228 IN_PROC_BROWSER_TEST_F(CredentialManagerBrowserTest,
58 AccountChooserWithOldCredentialAndNavigation) { 229 AccountChooserWithOldCredentialAndNavigation) {
59 // Save credentials with 'skip_zero_click'. 230 // Save credentials with 'skip_zero_click'.
60 scoped_refptr<password_manager::TestPasswordStore> password_store = 231 scoped_refptr<password_manager::TestPasswordStore> password_store =
61 static_cast<password_manager::TestPasswordStore*>( 232 static_cast<password_manager::TestPasswordStore*>(
62 PasswordStoreFactory::GetForProfile( 233 PasswordStoreFactory::GetForProfile(
63 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS).get()); 234 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS)
235 .get());
64 autofill::PasswordForm signin_form; 236 autofill::PasswordForm signin_form;
65 signin_form.signon_realm = embedded_test_server()->base_url().spec(); 237 signin_form.signon_realm = embedded_test_server()->base_url().spec();
66 signin_form.password_value = base::ASCIIToUTF16("password"); 238 signin_form.password_value = base::ASCIIToUTF16("password");
67 signin_form.username_value = base::ASCIIToUTF16("user"); 239 signin_form.username_value = base::ASCIIToUTF16("user");
68 signin_form.origin = embedded_test_server()->base_url(); 240 signin_form.origin = embedded_test_server()->base_url();
69 signin_form.skip_zero_click = true; 241 signin_form.skip_zero_click = true;
70 password_store->AddLogin(signin_form); 242 password_store->AddLogin(signin_form);
71 243
72 NavigateToFile("/password/password_form.html"); 244 NavigateToFile("/password/password_form.html");
73 std::string fill_password = 245 std::string fill_password =
74 "document.getElementById('username_field').value = 'user';" 246 "document.getElementById('username_field').value = 'user';"
75 "document.getElementById('password_field').value = 'password';"; 247 "document.getElementById('password_field').value = 'password';";
76 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_password)); 248 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_password));
77 249
78 // Call the API to trigger the notification to the client. 250 // Call the API to trigger the notification to the client.
79 ASSERT_TRUE(content::ExecuteScript( 251 ASSERT_TRUE(content::ExecuteScript(
80 RenderViewHost(), 252 RenderViewHost(),
81 "navigator.credentials.get({password: true})" 253 "navigator.credentials.get({password: true})"
82 ".then(cred => window.location = '/password/done.html')")); 254 ".then(cred => window.location = '/password/done.html')"));
83 // Mojo calls from the renderer are asynchronous. 255 // Mojo calls from the renderer are asynchronous.
84 BubbleObserver(WebContents()).WaitForAccountChooser(); 256 BubbleObserver(WebContents()).WaitForAccountChooser();
85 PasswordsModelDelegateFromWebContents(WebContents())->ChooseCredential( 257 PasswordsModelDelegateFromWebContents(WebContents())
86 signin_form, 258 ->ChooseCredential(
87 password_manager::CredentialType::CREDENTIAL_TYPE_PASSWORD); 259 signin_form,
260 password_manager::CredentialType::CREDENTIAL_TYPE_PASSWORD);
88 261
89 NavigationObserver observer(WebContents()); 262 NavigationObserver observer(WebContents());
90 observer.SetPathToWaitFor("/password/done.html"); 263 observer.SetPathToWaitFor("/password/done.html");
91 observer.Wait(); 264 observer.Wait();
92 265
93 // Verify that the form's 'skip_zero_click' is updated and not overwritten 266 // Verify that the form's 'skip_zero_click' is updated and not overwritten
94 // by the autofill password manager on successful login. 267 // by the autofill password manager on successful login.
95 WaitForPasswordStore(); 268 WaitForPasswordStore();
96 password_manager::TestPasswordStore::PasswordMap passwords_map = 269 password_manager::TestPasswordStore::PasswordMap passwords_map =
97 password_store->stored_passwords(); 270 password_store->stored_passwords();
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 NavigationObserver observer(WebContents()); 411 NavigationObserver observer(WebContents());
239 observer.SetPathToWaitFor("/password/done.html"); 412 observer.SetPathToWaitFor("/password/done.html");
240 observer.Wait(); 413 observer.Wait();
241 414
242 BubbleObserver prompt_observer(WebContents()); 415 BubbleObserver prompt_observer(WebContents());
243 // The autofill password manager shouldn't react to the successful login 416 // The autofill password manager shouldn't react to the successful login
244 // because it was suppressed when the site got the credential back. 417 // because it was suppressed when the site got the credential back.
245 EXPECT_FALSE(prompt_observer.IsShowingSavePrompt()); 418 EXPECT_FALSE(prompt_observer.IsShowingSavePrompt());
246 } 419 }
247 420
421 // Regression test for https://crbug.com/736357.
422 IN_PROC_BROWSER_TEST_F(CredentialManagerBrowserTest,
423 StoreInUnloadHandler_SameSite_OnDemandMojoPipe) {
424 TestStoreInUnloadHandlerForSameSiteNavigation(
425 false /* preestablish_mojo_pipe */);
426 }
427
428 // Regression test for https://crbug.com/736357.
429 IN_PROC_BROWSER_TEST_F(CredentialManagerBrowserTest,
430 StoreInUnloadHandler_SameSite_PreestablishedPipe) {
431 TestStoreInUnloadHandlerForSameSiteNavigation(
432 true /* preestablish_mojo_pipe */);
433 }
434 // Regression test for https://crbug.com/736357.
435 IN_PROC_BROWSER_TEST_F(CredentialManagerBrowserTest,
436 StoreInUnloadHandler_CrossSite_OnDemandMojoPipe) {
437 TestStoreInUnloadHandlerForCrossSiteNavigation(
438 false /* preestablish_mojo_pipe */);
439 }
440
441 // Regression test for https://crbug.com/736357.
442 IN_PROC_BROWSER_TEST_F(CredentialManagerBrowserTest,
443 StoreInUnloadHandler_CrossSite_PreestablishedPipe) {
444 TestStoreInUnloadHandlerForCrossSiteNavigation(
445 true /* preestablish_mojo_pipe */);
446 }
447
448 // Regression test for https://crbug.com/736357.
449 IN_PROC_BROWSER_TEST_F(CredentialManagerBrowserTest,
450 MojoConnectionRecreatedAfterNavigation) {
451 const GURL a_url1 = https_test_server().GetURL("a.com", "/title1.html");
452 const GURL a_url2 = https_test_server().GetURL("a.com", "/title2.html");
453 const GURL a_url2_ref = https_test_server().GetURL("a.com", "/title2.html#r");
454 const GURL b_url = https_test_server().GetURL("b.com", "/title2.html#ref");
455
456 // Enable 'auto signin' for the profile.
457 password_bubble_experiment::RecordAutoSignInPromptFirstRunExperienceWasShown(
458 browser()->profile()->GetPrefs());
459
460 // Navigate to a mostly empty page.
461 ui_test_utils::NavigateToURL(browser(), a_url1);
462
463 ChromePasswordManagerClient* client =
464 ChromePasswordManagerClient::FromWebContents(WebContents());
465
466 // Store a credential, and expect it to establish the Mojo connection.
467 EXPECT_FALSE(client->has_binding_for_credential_manager());
468 EXPECT_FALSE(client->was_store_ever_called());
469
470 ASSERT_TRUE(content::ExecuteScript(
471 WebContents(),
472 "var c = new PasswordCredential({ id: 'user', password: 'hunter2' });"
473 "navigator.credentials.store(c);"));
474
475 BubbleObserver prompt_observer(WebContents());
476 prompt_observer.WaitForSavePrompt();
477 ASSERT_TRUE(prompt_observer.IsShowingSavePrompt());
478 prompt_observer.AcceptSavePrompt();
479 WaitForPasswordStore();
480
481 EXPECT_TRUE(client->has_binding_for_credential_manager());
482 EXPECT_TRUE(client->was_store_ever_called());
483
484 // Trigger a same-site navigation.
485 content::RenderFrameHost* old_rfh = WebContents()->GetMainFrame();
486 ui_test_utils::NavigateToURL(browser(), a_url2);
487 ASSERT_EQ(old_rfh, WebContents()->GetMainFrame());
488
489 // Expect the Mojo connection closed.
490 EXPECT_FALSE(client->has_binding_for_credential_manager());
491
492 // Calling navigator.credentials.get() again should re-establish the Mojo
493 // connection and succeed.
494 ASSERT_NO_FATAL_FAILURE(
495 TriggerNavigatorGetPasswordCredentialsAndExpectHasResult(WebContents(),
496 true));
497 EXPECT_TRUE(client->has_binding_for_credential_manager());
498
499 // Same-document navigation. Call to get() succeeds.
500 ui_test_utils::NavigateToURL(browser(), a_url2_ref);
501 ASSERT_EQ(old_rfh, WebContents()->GetMainFrame());
502 EXPECT_TRUE(client->has_binding_for_credential_manager());
503 ASSERT_NO_FATAL_FAILURE(
504 TriggerNavigatorGetPasswordCredentialsAndExpectHasResult(WebContents(),
505 true));
506
507 // Cross-site navigation. Call to get() succeeds without results.
508 ui_test_utils::NavigateToURL(browser(), b_url);
509 ASSERT_NO_FATAL_FAILURE(
510 TriggerNavigatorGetPasswordCredentialsAndExpectHasResult(WebContents(),
511 false));
512
513 // Trigger a cross-site navigation back. Call to get() should still succeed,
514 // and once again with results.
515 ui_test_utils::NavigateToURL(browser(), a_url1);
516 ASSERT_NO_FATAL_FAILURE(
517 TriggerNavigatorGetPasswordCredentialsAndExpectHasResult(WebContents(),
518 true));
519 }
520
248 IN_PROC_BROWSER_TEST_F(CredentialManagerBrowserTest, SaveViaAPIAndAutofill) { 521 IN_PROC_BROWSER_TEST_F(CredentialManagerBrowserTest, SaveViaAPIAndAutofill) {
249 NavigateToFile("/password/password_form.html"); 522 NavigateToFile("/password/password_form.html");
250 523
251 ASSERT_TRUE(content::ExecuteScript( 524 ASSERT_TRUE(content::ExecuteScript(
252 RenderViewHost(), 525 RenderViewHost(),
253 "document.getElementById('input_submit_button').addEventListener('click'," 526 "document.getElementById('input_submit_button').addEventListener('click',"
254 "function(event) {" 527 "function(event) {"
255 "var c = new PasswordCredential({ id: 'user', password: 'API' });" 528 "var c = new PasswordCredential({ id: 'user', password: 'API' });"
256 "navigator.credentials.store(c);" 529 "navigator.credentials.store(c);"
257 "});")); 530 "});"));
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 622
350 // Reload the page and make sure it's autofilled. 623 // Reload the page and make sure it's autofilled.
351 NavigateToFile("/password/password_form.html"); 624 NavigateToFile("/password/password_form.html");
352 WaitForElementValue("username_field", "user"); 625 WaitForElementValue("username_field", "user");
353 content::SimulateMouseClickAt( 626 content::SimulateMouseClickAt(
354 WebContents(), 0, blink::WebMouseEvent::Button::kLeft, gfx::Point(1, 1)); 627 WebContents(), 0, blink::WebMouseEvent::Button::kLeft, gfx::Point(1, 1));
355 WaitForElementValue("password_field", "12345"); 628 WaitForElementValue("password_field", "12345");
356 } 629 }
357 630
358 } // namespace 631 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698