1 // Copyright (c) 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. 4 5 #include <string> 6 7 #include "base/basictypes.h" 8 #include "base/command_line.h" 9 #include "base/file_util.h" 10 #include "base/memory/ref_counted.h" 11 #include "base/memory/scoped_ptr.h" 12 #include "base/rand_util.h" 13 #include "base/strings/string16.h" 14 #include "base/strings/string_number_conversions.h" 15 #include "base/strings/string_split.h" 16 #include "base/strings/utf_string_conversions.h" 17 #include "base/time/time.h" 18 #include "chrome/browser/autofill/personal_data_manager_factory.h" 19 #include "chrome/browser/chrome_notification_types.h" 20 #include "chrome/browser/infobars/confirm_infobar_delegate.h" 21 #include "chrome/browser/infobars/infobar_service.h" 22 #include "chrome/browser/profiles/profile.h" 23 #include "chrome/browser/translate/translate_infobar_delegate.h" 24 #include "chrome/browser/translate/translate_manager.h" 25 #include "chrome/browser/ui/browser.h" 26 #include "chrome/browser/ui/browser_window.h" 27 #include "chrome/browser/ui/tabs/tab_strip_model.h" 28 #include "chrome/common/render_messages.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/content/browser/autofill_driver_impl.h" 33 #include "components/autofill/core/browser/autofill_common_test.h" 34 #include "components/autofill/core/browser/autofill_external_delegate.h" 35 #include "components/autofill/core/browser/autofill_manager.h" 36 #include "components/autofill/core/browser/autofill_manager_test_delegate.h" 37 #include "components/autofill/core/browser/autofill_profile.h" 38 #include "components/autofill/core/browser/personal_data_manager.h" 39 #include "components/autofill/core/browser/personal_data_manager_observer.h" 40 #include "components/autofill/core/browser/validation.h" 41 #include "content/public/browser/navigation_controller.h" 42 #include "content/public/browser/notification_observer.h" 43 #include "content/public/browser/notification_registrar.h" 44 #include "content/public/browser/notification_service.h" 45 #include "content/public/browser/render_view_host.h" 46 #include "content/public/browser/web_contents.h" 47 #include "content/public/test/browser_test_utils.h" 48 #include "content/public/test/test_renderer_host.h" 49 #include "content/public/test/test_utils.h" 50 #include "net/url_request/test_url_fetcher_factory.h" 51 #include "testing/gmock/include/gmock/gmock.h" 52 #include "testing/gtest/include/gtest/gtest.h" 53 #include "ui/base/keycodes/keyboard_codes.h" 54 55 56 namespace autofill { 57 58 static const char* kDataURIPrefix = "data:text/html;charset=utf-8,"; 59 static const char* kTestFormString = 60 "<form action=\"http://www.example.com/\" method=\"POST\">" 61 "<label for=\"firstname\">First name:</label>" 62 " <input type=\"text\" id=\"firstname\"" 63 " onFocus=\"domAutomationController.send(true)\"><br>" 64 "<label for=\"lastname\">Last name:</label>" 65 " <input type=\"text\" id=\"lastname\"><br>" 66 "<label for=\"address1\">Address line 1:</label>" 67 " <input type=\"text\" id=\"address1\"><br>" 68 "<label for=\"address2\">Address line 2:</label>" 69 " <input type=\"text\" id=\"address2\"><br>" 70 "<label for=\"city\">City:</label>" 71 " <input type=\"text\" id=\"city\"><br>" 72 "<label for=\"state\">State:</label>" 73 " <select id=\"state\">" 74 " <option value=\"\" selected=\"yes\">--</option>" 75 " <option value=\"CA\">California</option>" 76 " <option value=\"TX\">Texas</option>" 77 " </select><br>" 78 "<label for=\"zip\">ZIP code:</label>" 79 " <input type=\"text\" id=\"zip\"><br>" 80 "<label for=\"country\">Country:</label>" 81 " <select id=\"country\">" 82 " <option value=\"\" selected=\"yes\">--</option>" 83 " <option value=\"CA\">Canada</option>" 84 " <option value=\"US\">United States</option>" 85 " </select><br>" 86 "<label for=\"phone\">Phone number:</label>" 87 " <input type=\"text\" id=\"phone\"><br>" 88 "</form>"; 89 90 91 // AutofillManagerTestDelegateImpl -------------------------------------------- 92 93 class AutofillManagerTestDelegateImpl 94 : public autofill::AutofillManagerTestDelegate { 95 public: 96 AutofillManagerTestDelegateImpl() {} 97 virtual ~AutofillManagerTestDelegateImpl() {} 98 99 // autofill::AutofillManagerTestDelegate: 100 virtual void DidPreviewFormData() OVERRIDE { 101 loop_runner_->Quit(); 102 } 103 104 virtual void DidFillFormData() OVERRIDE { 105 loop_runner_->Quit(); 106 } 107 108 virtual void DidShowSuggestions() OVERRIDE { 109 loop_runner_->Quit(); 110 } 111 112 void Reset() { 113 loop_runner_ = new content::MessageLoopRunner(); 114 } 115 116 void Wait() { 117 loop_runner_->Run(); 118 } 119 120 private: 121 scoped_refptr<content::MessageLoopRunner> loop_runner_; 122 123 DISALLOW_COPY_AND_ASSIGN(AutofillManagerTestDelegateImpl); 124 }; 125 126 127 // WindowedPersonalDataManagerObserver ---------------------------------------- 128 129 class WindowedPersonalDataManagerObserver 130 : public PersonalDataManagerObserver, 131 public content::NotificationObserver { 132 public: 133 explicit WindowedPersonalDataManagerObserver(Browser* browser) 134 : alerted_(false), 135 has_run_message_loop_(false), 136 browser_(browser), 137 infobar_service_(NULL) { 138 PersonalDataManagerFactory::GetForProfile(browser_->profile())-> 139 AddObserver(this); 140 registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED, 141 content::NotificationService::AllSources()); 142 } 143 144 virtual ~WindowedPersonalDataManagerObserver() { 145 if (infobar_service_) { 146 while (infobar_service_->infobar_count() > 0) { 147 infobar_service_->RemoveInfoBar(infobar_service_->infobar_at(0)); 148 } 149 } 150 } 151 152 // PersonalDataManagerObserver: 153 virtual void OnPersonalDataChanged() OVERRIDE { 154 if (has_run_message_loop_) { 155 base::MessageLoopForUI::current()->Quit(); 156 has_run_message_loop_ = false; 157 } 158 alerted_ = true; 159 } 160 161 virtual void OnInsufficientFormData() OVERRIDE { 162 OnPersonalDataChanged(); 163 } 164 165 // content::NotificationObserver: 166 virtual void Observe(int type, 167 const content::NotificationSource& source, 168 const content::NotificationDetails& details) OVERRIDE { 169 infobar_service_ = InfoBarService::FromWebContents( 170 browser_->tab_strip_model()->GetActiveWebContents()); 171 infobar_service_->infobar_at(0)->AsConfirmInfoBarDelegate()->Accept(); 172 } 173 174 void Wait() { 175 if (!alerted_) { 176 has_run_message_loop_ = true; 177 content::RunMessageLoop(); 178 } 179 PersonalDataManagerFactory::GetForProfile(browser_->profile())-> 180 RemoveObserver(this); 181 } 182 183 private: 184 bool alerted_; 185 bool has_run_message_loop_; 186 Browser* browser_; 187 content::NotificationRegistrar registrar_; 188 InfoBarService* infobar_service_; 189 190 DISALLOW_COPY_AND_ASSIGN(WindowedPersonalDataManagerObserver); 191 }; 192 193 194 // TestAutofillExternalDelegate ----------------------------------------------- 195 196 class TestAutofillExternalDelegate : public AutofillExternalDelegate { 197 public: 198 TestAutofillExternalDelegate(content::WebContents* web_contents, 199 AutofillManager* autofill_manager, 200 AutofillDriver* autofill_driver) 201 : AutofillExternalDelegate(web_contents, autofill_manager, 202 autofill_driver), 203 keyboard_listener_(NULL) { 204 } 205 206 virtual ~TestAutofillExternalDelegate() {} 207 208 // AutofillExternalDelegate: 209 virtual void OnPopupShown(content::KeyboardListener* listener) OVERRIDE { 210 AutofillExternalDelegate::OnPopupShown(listener); 211 keyboard_listener_ = listener; 212 } 213 214 virtual void OnPopupHidden(content::KeyboardListener* listener) OVERRIDE { 215 keyboard_listener_ = NULL; 216 AutofillExternalDelegate::OnPopupHidden(listener); 217 } 218 219 content::KeyboardListener* keyboard_listener() { 220 return keyboard_listener_; 221 } 222 223 private: 224 // The popup that is currently registered as a keyboard listener, or NULL if 225 // there is none. 226 content::KeyboardListener* keyboard_listener_; 227 228 DISALLOW_COPY_AND_ASSIGN(TestAutofillExternalDelegate); 229 }; 230 231 232 // AutofillInteractiveTest ---------------------------------------------------- 233 234 class AutofillInteractiveTest : public InProcessBrowserTest { 235 protected: 236 AutofillInteractiveTest() {} 237 virtual ~AutofillInteractiveTest() {} 238 239 // InProcessBrowserTest: 240 virtual void SetUpOnMainThread() OVERRIDE { 241 // Don't want Keychain coming up on Mac. 242 test::DisableSystemServices(browser()->profile()); 243 244 // When testing the native UI, hook up a test external delegate, which 245 // allows us to forward keyboard events to the popup directly. 246 content::WebContents* web_contents = 247 browser()->tab_strip_model()->GetActiveWebContents(); 248 AutofillDriverImpl* autofill_driver = 249 AutofillDriverImpl::FromWebContents(web_contents); 250 AutofillManager* autofill_manager = autofill_driver->autofill_manager(); 251 scoped_ptr<AutofillExternalDelegate> external_delegate( 252 new TestAutofillExternalDelegate(web_contents, autofill_manager, 253 autofill_driver)); 254 autofill_driver->SetAutofillExternalDelegate(external_delegate.Pass()); 255 autofill_manager->SetTestDelegate(&test_delegate_); 256 } 257 258 virtual void CleanUpOnMainThread() OVERRIDE { 259 // Make sure to close any showing popups prior to tearing down the UI. 260 content::WebContents* web_contents = 261 browser()->tab_strip_model()->GetActiveWebContents(); 262 AutofillManager* autofill_manager = 263 AutofillDriverImpl::FromWebContents(web_contents)->autofill_manager(); 264 autofill_manager->delegate()->HideAutofillPopup(); 265 } 266 267 PersonalDataManager* GetPersonalDataManager() { 268 return PersonalDataManagerFactory::GetForProfile(browser()->profile()); 269 } 270 271 content::RenderViewHost* GetRenderViewHost() { 272 return browser()->tab_strip_model()->GetActiveWebContents()-> 273 GetRenderViewHost(); 274 } 275 276 TestAutofillExternalDelegate* GetExternalDelegate() { 277 content::WebContents* web_contents = 278 browser()->tab_strip_model()->GetActiveWebContents(); 279 AutofillDriverImpl* autofill_driver = 280 AutofillDriverImpl::FromWebContents(web_contents); 281 return static_cast<TestAutofillExternalDelegate*>( 282 autofill_driver->autofill_external_delegate()); 283 } 284 285 void CreateTestProfile() { 286 AutofillProfile profile; 287 test::SetProfileInfo( 288 &profile, "Milton", "C.", "Waddams", 289 "red.swingline (at) initech.com", "Initech", "4120 Freidrich Lane", 290 "Basement", "Austin", "Texas", "78744", "US", "5125551234"); 291 292 WindowedPersonalDataManagerObserver observer(browser()); 293 GetPersonalDataManager()->AddProfile(profile); 294 295 // AddProfile is asynchronous. Wait for it to finish before continuing the 296 // tests. 297 observer.Wait(); 298 } 299 300 void SetProfiles(std::vector<AutofillProfile>* profiles) { 301 WindowedPersonalDataManagerObserver observer(browser()); 302 GetPersonalDataManager()->SetProfiles(profiles); 303 observer.Wait(); 304 } 305 306 void SetProfile(const AutofillProfile& profile) { 307 std::vector<AutofillProfile> profiles; 308 profiles.push_back(profile); 309 SetProfiles(&profiles); 310 } 311 312 // Populates a webpage form using autofill data and keypress events. 313 // This function focuses the specified input field in the form, and then 314 // sends keypress events to the tab to cause the form to be populated. 315 void PopulateForm(const std::string& field_id) { 316 std::string js("document.getElementById('" + field_id + "').focus();"); 317 ASSERT_TRUE(content::ExecuteScript(GetRenderViewHost(), js)); 318 319 SendKeyToPageAndWait(ui::VKEY_DOWN); 320 SendKeyToPopupAndWait(ui::VKEY_DOWN); 321 SendKeyToPopupAndWait(ui::VKEY_RETURN); 322 } 323 324 void ExpectFieldValue(const std::string& field_name, 325 const std::string& expected_value) { 326 std::string value; 327 ASSERT_TRUE(content::ExecuteScriptAndExtractString( 328 browser()->tab_strip_model()->GetActiveWebContents(), 329 "window.domAutomationController.send(" 330 " document.getElementById('" + field_name + "').value);", 331 &value)); 332 EXPECT_EQ(expected_value, value); 333 } 334 335 void SimulateURLFetch(bool success) { 336 net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0); 337 ASSERT_TRUE(fetcher); 338 net::URLRequestStatus status; 339 status.set_status(success ? net::URLRequestStatus::SUCCESS : 340 net::URLRequestStatus::FAILED); 341 342 std::string script = " var google = {};" 343 "google.translate = (function() {" 344 " return {" 345 " TranslateService: function() {" 346 " return {" 347 " isAvailable : function() {" 348 " return true;" 349 " }," 350 " restore : function() {" 351 " return;" 352 " }," 353 " getDetectedLanguage : function() {" 354 " return \"ja\";" 355 " }," 356 " translatePage : function(originalLang, targetLang," 357 " onTranslateProgress) {" 358 " document.getElementsByTagName(\"body\")[0].innerHTML = '" + 359 std::string(kTestFormString) + 360 " ';" 361 " onTranslateProgress(100, true, false);" 362 " }" 363 " };" 364 " }" 365 " };" 366 "})();"; 367 368 fetcher->set_url(fetcher->GetOriginalURL()); 369 fetcher->set_status(status); 370 fetcher->set_response_code(success ? 200 : 500); 371 fetcher->SetResponseString(script); 372 fetcher->delegate()->OnURLFetchComplete(fetcher); 373 } 374 375 void FocusFirstNameField() { 376 bool result = false; 377 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( 378 GetRenderViewHost(), 379 "if (document.readyState === 'complete')" 380 " document.getElementById('firstname').focus();" 381 "else" 382 " domAutomationController.send(false);", 383 &result)); 384 ASSERT_TRUE(result); 385 } 386 387 void ExpectFilledTestForm() { 388 ExpectFieldValue("firstname", "Milton"); 389 ExpectFieldValue("lastname", "Waddams"); 390 ExpectFieldValue("address1", "4120 Freidrich Lane"); 391 ExpectFieldValue("address2", "Basement"); 392 ExpectFieldValue("city", "Austin"); 393 ExpectFieldValue("state", "TX"); 394 ExpectFieldValue("zip", "78744"); 395 ExpectFieldValue("country", "US"); 396 ExpectFieldValue("phone", "5125551234"); 397 } 398 399 void SendKeyToPageAndWait(ui::KeyboardCode key) { 400 test_delegate_.Reset(); 401 content::SimulateKeyPress( 402 browser()->tab_strip_model()->GetActiveWebContents(), 403 key, false, false, false, false); 404 test_delegate_.Wait(); 405 } 406 407 void SendKeyToPopupAndWait(ui::KeyboardCode key) { 408 // When testing the native UI, route popup-targeted key presses via the 409 // external delegate. 410 content::NativeWebKeyboardEvent event; 411 event.windowsKeyCode = key; 412 test_delegate_.Reset(); 413 GetExternalDelegate()->keyboard_listener()->HandleKeyPressEvent(event); 414 test_delegate_.Wait(); 415 } 416 417 void TryBasicFormFill() { 418 FocusFirstNameField(); 419 420 // Start filling the first name field with "M" and wait for the popup to be 421 // shown. 422 SendKeyToPageAndWait(ui::VKEY_M); 423 424 // Press the down arrow to select the suggestion and preview the autofilled 425 // form. 426 SendKeyToPopupAndWait(ui::VKEY_DOWN); 427 428 // The previewed values should not be accessible to JavaScript. 429 ExpectFieldValue("firstname", "M"); 430 ExpectFieldValue("lastname", std::string()); 431 ExpectFieldValue("address1", std::string()); 432 ExpectFieldValue("address2", std::string()); 433 ExpectFieldValue("city", std::string()); 434 ExpectFieldValue("state", std::string()); 435 ExpectFieldValue("zip", std::string()); 436 ExpectFieldValue("country", std::string()); 437 ExpectFieldValue("phone", std::string()); 438 // TODO(isherman): It would be nice to test that the previewed values are 439 // displayed: http://crbug.com/57220 440 441 // Press Enter to accept the autofill suggestions. 442 SendKeyToPopupAndWait(ui::VKEY_RETURN); 443 444 // The form should be filled. 445 ExpectFilledTestForm(); 446 } 447 448 private: 449 AutofillManagerTestDelegateImpl test_delegate_; 450 451 net::TestURLFetcherFactory url_fetcher_factory_; 452 453 DISALLOW_COPY_AND_ASSIGN(AutofillInteractiveTest); 454 }; 455 456 // Test that basic form fill is working. 457 IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, BasicFormFill) { 458 CreateTestProfile(); 459 460 // Load the test page. 461 ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), 462 GURL(std::string(kDataURIPrefix) + kTestFormString))); 463 464 // Invoke Autofill. 465 TryBasicFormFill(); 466 } 467 468 // Test that form filling can be initiated by pressing the down arrow. 469 IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, AutofillViaDownArrow) { 470 CreateTestProfile(); 471 472 // Load the test page. 473 ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), 474 GURL(std::string(kDataURIPrefix) + kTestFormString))); 475 476 // Focus a fillable field. 477 FocusFirstNameField(); 478 479 // Press the down arrow to initiate Autofill and wait for the popup to be 480 // shown. 481 SendKeyToPageAndWait(ui::VKEY_DOWN); 482 483 // Press the down arrow to select the suggestion and preview the autofilled 484 // form. 485 SendKeyToPopupAndWait(ui::VKEY_DOWN); 486 487 // Press Enter to accept the autofill suggestions. 488 SendKeyToPopupAndWait(ui::VKEY_RETURN); 489 490 // The form should be filled. 491 ExpectFilledTestForm(); 492 } 493 494 IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, AutofillSelectViaTab) { 495 CreateTestProfile(); 496 497 // Load the test page. 498 ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), 499 GURL(std::string(kDataURIPrefix) + kTestFormString))); 500 501 // Focus a fillable field. 502 FocusFirstNameField(); 503 504 // Press the down arrow to initiate Autofill and wait for the popup to be 505 // shown. 506 SendKeyToPageAndWait(ui::VKEY_DOWN); 507 508 // Press the down arrow to select the suggestion and preview the autofilled 509 // form. 510 SendKeyToPopupAndWait(ui::VKEY_DOWN); 511 512 // Press tab to accept the autofill suggestions. 513 SendKeyToPopupAndWait(ui::VKEY_TAB); 514 515 // The form should be filled. 516 ExpectFilledTestForm(); 517 } 518 519 // Test that a JavaScript onchange event is fired after auto-filling a form. 520 IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, OnChangeAfterAutofill) { 521 CreateTestProfile(); 522 523 const char* kOnChangeScript = 524 "<script>" 525 "focused_fired = false;" 526 "unfocused_fired = false;" 527 "changed_select_fired = false;" 528 "unchanged_select_fired = false;" 529 "document.getElementById('firstname').onchange = function() {" 530 " focused_fired = true;" 531 "};" 532 "document.getElementById('lastname').onchange = function() {" 533 " unfocused_fired = true;" 534 "};" 535 "document.getElementById('state').onchange = function() {" 536 " changed_select_fired = true;" 537 "};" 538 "document.getElementById('country').onchange = function() {" 539 " unchanged_select_fired = true;" 540 "};" 541 "document.getElementById('country').value = 'US';" 542 "</script>"; 543 544 // Load the test page. 545 ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), 546 GURL(std::string(kDataURIPrefix) + kTestFormString + kOnChangeScript))); 547 548 // Invoke Autofill. 549 FocusFirstNameField(); 550 551 // Start filling the first name field with "M" and wait for the popup to be 552 // shown. 553 SendKeyToPageAndWait(ui::VKEY_M); 554 555 // Press the down arrow to select the suggestion and preview the autofilled 556 // form. 557 SendKeyToPopupAndWait(ui::VKEY_DOWN); 558 559 // Press Enter to accept the autofill suggestions. 560 SendKeyToPopupAndWait(ui::VKEY_RETURN); 561 562 // The form should be filled. 563 ExpectFilledTestForm(); 564 565 // The change event should have already fired for unfocused fields, both of 566 // <input> and of <select> type. However, it should not yet have fired for the 567 // focused field. 568 bool focused_fired = false; 569 bool unfocused_fired = false; 570 bool changed_select_fired = false; 571 bool unchanged_select_fired = false; 572 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( 573 GetRenderViewHost(), 574 "domAutomationController.send(focused_fired);", 575 &focused_fired)); 576 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( 577 GetRenderViewHost(), 578 "domAutomationController.send(unfocused_fired);", 579 &unfocused_fired)); 580 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( 581 GetRenderViewHost(), 582 "domAutomationController.send(changed_select_fired);", 583 &changed_select_fired)); 584 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( 585 GetRenderViewHost(), 586 "domAutomationController.send(unchanged_select_fired);", 587 &unchanged_select_fired)); 588 EXPECT_FALSE(focused_fired); 589 EXPECT_TRUE(unfocused_fired); 590 EXPECT_TRUE(changed_select_fired); 591 EXPECT_FALSE(unchanged_select_fired); 592 593 // Unfocus the first name field. Its change event should fire. 594 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( 595 GetRenderViewHost(), 596 "document.getElementById('firstname').blur();" 597 "domAutomationController.send(focused_fired);", &focused_fired)); 598 EXPECT_TRUE(focused_fired); 599 } 600 601 // Test that we can autofill forms distinguished only by their |id| attribute. 602 IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, 603 AutofillFormsDistinguishedById) { 604 CreateTestProfile(); 605 606 // Load the test page. 607 const std::string kURL = 608 std::string(kDataURIPrefix) + kTestFormString + 609 "<script>" 610 "var mainForm = document.forms[0];" 611 "mainForm.id = 'mainForm';" 612 "var newForm = document.createElement('form');" 613 "newForm.action = mainForm.action;" 614 "newForm.method = mainForm.method;" 615 "newForm.id = 'newForm';" 616 "mainForm.parentNode.insertBefore(newForm, mainForm);" 617 "</script>"; 618 ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), GURL(kURL))); 619 620 // Invoke Autofill. 621 TryBasicFormFill(); 622 } 623 624 // Test that we properly autofill forms with repeated fields. 625 // In the wild, the repeated fields are typically either email fields 626 // (duplicated for "confirmation"); or variants that are hot-swapped via 627 // JavaScript, with only one actually visible at any given time. 628 IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, AutofillFormWithRepeatedField) { 629 CreateTestProfile(); 630 631 // Load the test page. 632 ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), 633 GURL(std::string(kDataURIPrefix) + 634 "<form action=\"http://www.example.com/\" method=\"POST\">" 635 "<label for=\"firstname\">First name:</label>" 636 " <input type=\"text\" id=\"firstname\"" 637 " onFocus=\"domAutomationController.send(true)\"><br>" 638 "<label for=\"lastname\">Last name:</label>" 639 " <input type=\"text\" id=\"lastname\"><br>" 640 "<label for=\"address1\">Address line 1:</label>" 641 " <input type=\"text\" id=\"address1\"><br>" 642 "<label for=\"address2\">Address line 2:</label>" 643 " <input type=\"text\" id=\"address2\"><br>" 644 "<label for=\"city\">City:</label>" 645 " <input type=\"text\" id=\"city\"><br>" 646 "<label for=\"state\">State:</label>" 647 " <select id=\"state\">" 648 " <option value=\"\" selected=\"yes\">--</option>" 649 " <option value=\"CA\">California</option>" 650 " <option value=\"TX\">Texas</option>" 651 " </select><br>" 652 "<label for=\"state_freeform\" style=\"display:none\">State:</label>" 653 " <input type=\"text\" id=\"state_freeform\"" 654 " style=\"display:none\"><br>" 655 "<label for=\"zip\">ZIP code:</label>" 656 " <input type=\"text\" id=\"zip\"><br>" 657 "<label for=\"country\">Country:</label>" 658 " <select id=\"country\">" 659 " <option value=\"\" selected=\"yes\">--</option>" 660 " <option value=\"CA\">Canada</option>" 661 " <option value=\"US\">United States</option>" 662 " </select><br>" 663 "<label for=\"phone\">Phone number:</label>" 664 " <input type=\"text\" id=\"phone\"><br>" 665 "</form>"))); 666 667 // Invoke Autofill. 668 TryBasicFormFill(); 669 ExpectFieldValue("state_freeform", std::string()); 670 } 671 672 // Test that we properly autofill forms with non-autofillable fields. 673 IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, 674 AutofillFormWithNonAutofillableField) { 675 CreateTestProfile(); 676 677 // Load the test page. 678 ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), 679 GURL(std::string(kDataURIPrefix) + 680 "<form action=\"http://www.example.com/\" method=\"POST\">" 681 "<label for=\"firstname\">First name:</label>" 682 " <input type=\"text\" id=\"firstname\"" 683 " onFocus=\"domAutomationController.send(true)\"><br>" 684 "<label for=\"middlename\">Middle name:</label>" 685 " <input type=\"text\" id=\"middlename\" autocomplete=\"off\" /><br>" 686 "<label for=\"lastname\">Last name:</label>" 687 " <input type=\"text\" id=\"lastname\"><br>" 688 "<label for=\"address1\">Address line 1:</label>" 689 " <input type=\"text\" id=\"address1\"><br>" 690 "<label for=\"address2\">Address line 2:</label>" 691 " <input type=\"text\" id=\"address2\"><br>" 692 "<label for=\"city\">City:</label>" 693 " <input type=\"text\" id=\"city\"><br>" 694 "<label for=\"state\">State:</label>" 695 " <select id=\"state\">" 696 " <option value=\"\" selected=\"yes\">--</option>" 697 " <option value=\"CA\">California</option>" 698 " <option value=\"TX\">Texas</option>" 699 " </select><br>" 700 "<label for=\"zip\">ZIP code:</label>" 701 " <input type=\"text\" id=\"zip\"><br>" 702 "<label for=\"country\">Country:</label>" 703 " <select id=\"country\">" 704 " <option value=\"\" selected=\"yes\">--</option>" 705 " <option value=\"CA\">Canada</option>" 706 " <option value=\"US\">United States</option>" 707 " </select><br>" 708 "<label for=\"phone\">Phone number:</label>" 709 " <input type=\"text\" id=\"phone\"><br>" 710 "</form>"))); 711 712 // Invoke Autofill. 713 TryBasicFormFill(); 714 } 715 716 // Test that we can Autofill dynamically generated forms. 717 IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, DynamicFormFill) { 718 CreateTestProfile(); 719 720 // Load the test page. 721 ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), 722 GURL(std::string(kDataURIPrefix) + 723 "<form id=\"form\" action=\"http://www.example.com/\"" 724 " method=\"POST\"></form>" 725 "<script>" 726 "function AddElement(name, label) {" 727 " var form = document.getElementById('form');" 728 "" 729 " var label_text = document.createTextNode(label);" 730 " var label_element = document.createElement('label');" 731 " label_element.setAttribute('for', name);" 732 " label_element.appendChild(label_text);" 733 " form.appendChild(label_element);" 734 "" 735 " if (name === 'state' || name === 'country') {" 736 " var select_element = document.createElement('select');" 737 " select_element.setAttribute('id', name);" 738 " select_element.setAttribute('name', name);" 739 "" 740 " /* Add an empty selected option. */" 741 " var default_option = new Option('--', '', true);" 742 " select_element.appendChild(default_option);" 743 "" 744 " /* Add the other options. */" 745 " if (name == 'state') {" 746 " var option1 = new Option('California', 'CA');" 747 " select_element.appendChild(option1);" 748 " var option2 = new Option('Texas', 'TX');" 749 " select_element.appendChild(option2);" 750 " } else {" 751 " var option1 = new Option('Canada', 'CA');" 752 " select_element.appendChild(option1);" 753 " var option2 = new Option('United States', 'US');" 754 " select_element.appendChild(option2);" 755 " }" 756 "" 757 " form.appendChild(select_element);" 758 " } else {" 759 " var input_element = document.createElement('input');" 760 " input_element.setAttribute('id', name);" 761 " input_element.setAttribute('name', name);" 762 "" 763 " /* Add the onFocus listener to the 'firstname' field. */" 764 " if (name === 'firstname') {" 765 " input_element.setAttribute(" 766 " 'onFocus', 'domAutomationController.send(true)');" 767 " }" 768 "" 769 " form.appendChild(input_element);" 770 " }" 771 "" 772 " form.appendChild(document.createElement('br'));" 773 "};" 774 "" 775 "function BuildForm() {" 776 " var elements = [" 777 " ['firstname', 'First name:']," 778 " ['lastname', 'Last name:']," 779 " ['address1', 'Address line 1:']," 780 " ['address2', 'Address line 2:']," 781 " ['city', 'City:']," 782 " ['state', 'State:']," 783 " ['zip', 'ZIP code:']," 784 " ['country', 'Country:']," 785 " ['phone', 'Phone number:']," 786 " ];" 787 "" 788 " for (var i = 0; i < elements.length; i++) {" 789 " var name = elements[i][0];" 790 " var label = elements[i][1];" 791 " AddElement(name, label);" 792 " }" 793 "};" 794 "</script>"))); 795 796 // Dynamically construct the form. 797 ASSERT_TRUE(content::ExecuteScript(GetRenderViewHost(), "BuildForm();")); 798 799 // Invoke Autofill. 800 TryBasicFormFill(); 801 } 802 803 // Test that form filling works after reloading the current page. 804 IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, AutofillAfterReload) { 805 CreateTestProfile(); 806 807 // Load the test page. 808 ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), 809 GURL(std::string(kDataURIPrefix) + kTestFormString))); 810 811 // Reload the page. 812 content::WebContents* web_contents = 813 browser()->tab_strip_model()->GetActiveWebContents(); 814 web_contents->GetController().Reload(false); 815 content::WaitForLoadStop(web_contents); 816 817 // Invoke Autofill. 818 TryBasicFormFill(); 819 } 820 821 // DISABLED: http://crbug.com/150084 822 IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, 823 DISABLED_AutofillAfterTranslate) { 824 CreateTestProfile(); 825 826 GURL url(std::string(kDataURIPrefix) + 827 "<form action=\"http://www.example.com/\" method=\"POST\">" 828 "<label for=\"fn\"></label>" 829 " <input type=\"text\" id=\"fn\"" 830 " onFocus=\"domAutomationController.send(true)\"" 831 "><br>" 832 "<label for=\"ln\"></label>" 833 " <input type=\"text\" id=\"ln\"><br>" 834 "<label for=\"a1\">Address line 1:</label>" 835 " <input type=\"text\" id=\"a1\"><br>" 836 "<label for=\"a2\">Address line 2:</label>" 837 " <input type=\"text\" id=\"a2\"><br>" 838 "<label for=\"ci\">City:</label>" 839 " <input type=\"text\" id=\"ci\"><br>" 840 "<label for=\"st\">State:</label>" 841 " <select id=\"st\">" 842 " <option value=\"\" selected=\"yes\">--</option>" 843 " <option value=\"CA\">California</option>" 844 " <option value=\"TX\">Texas</option>" 845 " </select><br>" 846 "<label for=\"z\">ZIP code:</label>" 847 " <input type=\"text\" id=\"z\"><br>" 848 "<label for=\"co\">Country:</label>" 849 " <select id=\"co\">" 850 " <option value=\"\" selected=\"yes\">--</option>" 851 " <option value=\"CA\">Canada</option>" 852 " <option value=\"US\">United States</option>" 853 " </select><br>" 854 "<label for=\"ph\">Phone number:</label>" 855 " <input type=\"text\" id=\"ph\"><br>" 856 "</form>"); 857 ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), url)); 858 859 // Get translation bar. 860 LanguageDetectionDetails details; 861 details.adopted_language = "ja"; 862 content::RenderViewHostTester::TestOnMessageReceived( 863 GetRenderViewHost(), 864 ChromeViewHostMsg_TranslateLanguageDetermined(0, details, true)); 865 TranslateInfoBarDelegate* delegate = InfoBarService::FromWebContents( 866 browser()->tab_strip_model()->GetActiveWebContents())->infobar_at(0)-> 867 AsTranslateInfoBarDelegate(); 868 ASSERT_TRUE(delegate); 869 EXPECT_EQ(TranslateInfoBarDelegate::BEFORE_TRANSLATE, 870 delegate->infobar_type()); 871 872 // Simulate translation button press. 873 delegate->Translate(); 874 875 // Simulate the translate script being retrieved. 876 // Pass fake google.translate lib as the translate script. 877 SimulateURLFetch(true); 878 879 content::WindowedNotificationObserver translation_observer( 880 chrome::NOTIFICATION_PAGE_TRANSLATED, 881 content::NotificationService::AllSources()); 882 883 // Simulate translation to kick onTranslateElementLoad. 884 // But right now, the call stucks here. 885 // Once click the text field, it starts again. 886 ASSERT_TRUE(content::ExecuteScript( 887 GetRenderViewHost(), "cr.googleTranslate.onTranslateElementLoad();")); 888 889 // Simulate the render notifying the translation has been done. 890 translation_observer.Wait(); 891 892 TryBasicFormFill(); 893 } 894 895 // Test phone fields parse correctly from a given profile. 896 // The high level key presses execute the following: Select the first text 897 // field, invoke the autofill popup list, select the first profile within the 898 // list, and commit to the profile to populate the form. 899 IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, ComparePhoneNumbers) { 900 ASSERT_TRUE(test_server()->Start()); 901 902 AutofillProfile profile; 903 profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Bob")); 904 profile.SetRawInfo(NAME_LAST, ASCIIToUTF16("Smith")); 905 profile.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("1234 H St.")); 906 profile.SetRawInfo(ADDRESS_HOME_CITY, ASCIIToUTF16("San Jose")); 907 profile.SetRawInfo(ADDRESS_HOME_STATE, ASCIIToUTF16("CA")); 908 profile.SetRawInfo(ADDRESS_HOME_ZIP, ASCIIToUTF16("95110")); 909 profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("1-408-555-4567")); 910 SetProfile(profile); 911 912 GURL url = test_server()->GetURL("files/autofill/form_phones.html"); 913 ui_test_utils::NavigateToURL(browser(), url); 914 PopulateForm("NAME_FIRST"); 915 916 ExpectFieldValue("NAME_FIRST", "Bob"); 917 ExpectFieldValue("NAME_LAST", "Smith"); 918 ExpectFieldValue("ADDRESS_HOME_LINE1", "1234 H St."); 919 ExpectFieldValue("ADDRESS_HOME_CITY", "San Jose"); 920 ExpectFieldValue("ADDRESS_HOME_STATE", "CA"); 921 ExpectFieldValue("ADDRESS_HOME_ZIP", "95110"); 922 ExpectFieldValue("PHONE_HOME_WHOLE_NUMBER", "14085554567"); 923 ExpectFieldValue("PHONE_HOME_CITY_CODE-1", "408"); 924 ExpectFieldValue("PHONE_HOME_CITY_CODE-2", "408"); 925 ExpectFieldValue("PHONE_HOME_NUMBER", "5554567"); 926 ExpectFieldValue("PHONE_HOME_NUMBER_3-1", "555"); 927 ExpectFieldValue("PHONE_HOME_NUMBER_3-2", "555"); 928 ExpectFieldValue("PHONE_HOME_NUMBER_4-1", "4567"); 929 ExpectFieldValue("PHONE_HOME_NUMBER_4-2", "4567"); 930 ExpectFieldValue("PHONE_HOME_EXT-1", std::string()); 931 ExpectFieldValue("PHONE_HOME_EXT-2", std::string()); 932 ExpectFieldValue("PHONE_HOME_COUNTRY_CODE-1", "1"); 933 } 934 935 // Test that Autofill does not fill in read-only fields. 936 IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, NoAutofillForReadOnlyFields) { 937 ASSERT_TRUE(test_server()->Start()); 938 939 std::string addr_line1("1234 H St."); 940 941 AutofillProfile profile; 942 profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Bob")); 943 profile.SetRawInfo(NAME_LAST, ASCIIToUTF16("Smith")); 944 profile.SetRawInfo(EMAIL_ADDRESS, ASCIIToUTF16("bsmith (at) gmail.com")); 945 profile.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16(addr_line1)); 946 profile.SetRawInfo(ADDRESS_HOME_CITY, ASCIIToUTF16("San Jose")); 947 profile.SetRawInfo(ADDRESS_HOME_STATE, ASCIIToUTF16("CA")); 948 profile.SetRawInfo(ADDRESS_HOME_ZIP, ASCIIToUTF16("95110")); 949 profile.SetRawInfo(COMPANY_NAME, ASCIIToUTF16("Company X")); 950 profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("408-871-4567")); 951 SetProfile(profile); 952 953 GURL url = test_server()->GetURL("files/autofill/read_only_field_test.html"); 954 ui_test_utils::NavigateToURL(browser(), url); 955 PopulateForm("firstname"); 956 957 ExpectFieldValue("email", std::string()); 958 ExpectFieldValue("address", addr_line1); 959 } 960 961 // Test form is fillable from a profile after form was reset. 962 // Steps: 963 // 1. Fill form using a saved profile. 964 // 2. Reset the form. 965 // 3. Fill form using a saved profile. 966 // Flakily times out: http://crbug.com/270341 967 IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, DISABLED_FormFillableOnReset) { 968 ASSERT_TRUE(test_server()->Start()); 969 970 CreateTestProfile(); 971 972 GURL url = test_server()->GetURL("files/autofill/autofill_test_form.html"); 973 ui_test_utils::NavigateToURL(browser(), url); 974 PopulateForm("NAME_FIRST"); 975 976 ASSERT_TRUE(content::ExecuteScript( 977 browser()->tab_strip_model()->GetActiveWebContents(), 978 "document.getElementById('testform').reset()")); 979 980 PopulateForm("NAME_FIRST"); 981 982 ExpectFieldValue("NAME_FIRST", "Milton"); 983 ExpectFieldValue("NAME_LAST", "Waddams"); 984 ExpectFieldValue("EMAIL_ADDRESS", "red.swingline (at) initech.com"); 985 ExpectFieldValue("ADDRESS_HOME_LINE1", "4120 Freidrich Lane"); 986 ExpectFieldValue("ADDRESS_HOME_CITY", "Austin"); 987 ExpectFieldValue("ADDRESS_HOME_STATE", "Texas"); 988 ExpectFieldValue("ADDRESS_HOME_ZIP", "78744"); 989 ExpectFieldValue("ADDRESS_HOME_COUNTRY", "United States"); 990 ExpectFieldValue("PHONE_HOME_WHOLE_NUMBER", "5125551234"); 991 } 992 993 // Test Autofill distinguishes a middle initial in a name. 994 // Flakily times out: http://crbug.com/270341 995 IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, 996 DISABLED_DistinguishMiddleInitialWithinName) { 997 ASSERT_TRUE(test_server()->Start()); 998 999 CreateTestProfile(); 1000 1001 GURL url = test_server()->GetURL( 1002 "files/autofill/autofill_middleinit_form.html"); 1003 ui_test_utils::NavigateToURL(browser(), url); 1004 PopulateForm("NAME_FIRST"); 1005 1006 ExpectFieldValue("NAME_MIDDLE", "C"); 1007 } 1008 1009 // Test forms with multiple email addresses are filled properly. 1010 // Entire form should be filled with one user gesture. 1011 // Flakily times out: http://crbug.com/270341 1012 IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, 1013 DISABLED_MultipleEmailFilledByOneUserGesture) { 1014 ASSERT_TRUE(test_server()->Start()); 1015 1016 std::string email("bsmith (at) gmail.com"); 1017 1018 AutofillProfile profile; 1019 profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Bob")); 1020 profile.SetRawInfo(NAME_LAST, ASCIIToUTF16("Smith")); 1021 profile.SetRawInfo(EMAIL_ADDRESS, ASCIIToUTF16(email)); 1022 profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("4088714567")); 1023 SetProfile(profile); 1024 1025 GURL url = test_server()->GetURL( 1026 "files/autofill/autofill_confirmemail_form.html"); 1027 ui_test_utils::NavigateToURL(browser(), url); 1028 PopulateForm("NAME_FIRST"); 1029 1030 ExpectFieldValue("EMAIL_CONFIRM", email); 1031 // TODO(isherman): verify entire form. 1032 } 1033 1034 // http://crbug.com/150084 1035 #if defined(OS_MACOSX) 1036 #define MAYBE_FormFillLatencyAfterSubmit FormFillLatencyAfterSubmit 1037 #else 1038 #define MAYBE_FormFillLatencyAfterSubmit DISABLED_FormFillLatencyAfterSubmit 1039 #endif 1040 // Test latency time on form submit with lots of stored Autofill profiles. 1041 // This test verifies when a profile is selected from the Autofill dictionary 1042 // that consists of thousands of profiles, the form does not hang after being 1043 // submitted. 1044 IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, 1045 MAYBE_FormFillLatencyAfterSubmit) { 1046 ASSERT_TRUE(test_server()->Start()); 1047 1048 std::vector<std::string> cities; 1049 cities.push_back("San Jose"); 1050 cities.push_back("San Francisco"); 1051 cities.push_back("Sacramento"); 1052 cities.push_back("Los Angeles"); 1053 1054 std::vector<std::string> streets; 1055 streets.push_back("St"); 1056 streets.push_back("Ave"); 1057 streets.push_back("Ln"); 1058 streets.push_back("Ct"); 1059 1060 const int kNumProfiles = 1500; 1061 base::Time start_time = base::Time::Now(); 1062 std::vector<AutofillProfile> profiles; 1063 for (int i = 0; i < kNumProfiles; i++) { 1064 AutofillProfile profile; 1065 string16 name(base::IntToString16(i)); 1066 string16 email(name + ASCIIToUTF16("@example.com")); 1067 string16 street = ASCIIToUTF16( 1068 base::IntToString(base::RandInt(0, 10000)) + " " + 1069 streets[base::RandInt(0, streets.size() - 1)]); 1070 string16 city = ASCIIToUTF16(cities[base::RandInt(0, cities.size() - 1)]); 1071 string16 zip(base::IntToString16(base::RandInt(0, 10000))); 1072 profile.SetRawInfo(NAME_FIRST, name); 1073 profile.SetRawInfo(EMAIL_ADDRESS, email); 1074 profile.SetRawInfo(ADDRESS_HOME_LINE1, street); 1075 profile.SetRawInfo(ADDRESS_HOME_CITY, city); 1076 profile.SetRawInfo(ADDRESS_HOME_STATE, WideToUTF16(L"CA")); 1077 profile.SetRawInfo(ADDRESS_HOME_ZIP, zip); 1078 profile.SetRawInfo(ADDRESS_HOME_COUNTRY, WideToUTF16(L"US")); 1079 profiles.push_back(profile); 1080 } 1081 SetProfiles(&profiles); 1082 // TODO(isherman): once we're sure this test doesn't timeout on any bots, this 1083 // can be removd. 1084 LOG(INFO) << "Created " << kNumProfiles << " profiles in " << 1085 (base::Time::Now() - start_time).InSeconds() << " seconds."; 1086 1087 GURL url = test_server()->GetURL( 1088 "files/autofill/latency_after_submit_test.html"); 1089 ui_test_utils::NavigateToURL(browser(), url); 1090 PopulateForm("NAME_FIRST"); 1091 1092 content::WindowedNotificationObserver load_stop_observer( 1093 content::NOTIFICATION_LOAD_STOP, 1094 content::Source<content::NavigationController>( 1095 &browser()->tab_strip_model()->GetActiveWebContents()-> 1096 GetController())); 1097 1098 ASSERT_TRUE(content::ExecuteScript( 1099 GetRenderViewHost(), 1100 "document.getElementById('testform').submit();")); 1101 // This will ensure the test didn't hang. 1102 load_stop_observer.Wait(); 1103 } 1104 1105 // Test that Chrome doesn't crash when autocomplete is disabled while the user 1106 // is interacting with the form. This is a regression test for 1107 // http://crbug.com/160476 1108 IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, 1109 DisableAutocompleteWhileFilling) { 1110 CreateTestProfile(); 1111 1112 // Load the test page. 1113 ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), 1114 GURL(std::string(kDataURIPrefix) + kTestFormString))); 1115 1116 // Invoke Autofill: Start filling the first name field with "M" and wait for 1117 // the popup to be shown. 1118 FocusFirstNameField(); 1119 SendKeyToPageAndWait(ui::VKEY_M); 1120 1121 // Now that the popup with suggestions is showing, disable autocomplete for 1122 // the active field. 1123 ASSERT_TRUE(content::ExecuteScript( 1124 GetRenderViewHost(), 1125 "document.querySelector('input').autocomplete = 'off';")); 1126 1127 // Press the down arrow to select the suggestion and attempt to preview the 1128 // autofilled form. 1129 content::NativeWebKeyboardEvent event; 1130 event.windowsKeyCode = ui::VKEY_DOWN; 1131 GetExternalDelegate()->keyboard_listener()->HandleKeyPressEvent(event); 1132 1133 // Wait for any IPCs to complete by performing an action that generates an 1134 // IPC that's easy to wait for. Chrome shouldn't crash. 1135 bool result = false; 1136 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( 1137 GetRenderViewHost(), 1138 "var city = document.getElementById('city');" 1139 "city.onfocus = function() { domAutomationController.send(true); };" 1140 "city.focus()", 1141 &result)); 1142 ASSERT_TRUE(result); 1143 SendKeyToPageAndWait(ui::VKEY_A); 1144 } 1145 1146 } // namespace autofill 1147