autofill_dialog_controller_browsertest.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
1// Copyright (c) 2012 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 "base/bind.h" 6#include "base/command_line.h" 7#include "base/logging.h" 8#include "base/memory/ref_counted.h" 9#include "base/memory/weak_ptr.h" 10#include "base/message_loop/message_loop.h" 11#include "base/prefs/pref_service.h" 12#include "base/strings/utf_string_conversions.h" 13#include "base/time/time.h" 14#include "chrome/browser/autofill/personal_data_manager_factory.h" 15#include "chrome/browser/profiles/profile.h" 16#include "chrome/browser/ui/autofill/account_chooser_model.h" 17#include "chrome/browser/ui/autofill/autofill_dialog_controller_impl.h" 18#include "chrome/browser/ui/autofill/autofill_dialog_i18n_input.h" 19#include "chrome/browser/ui/autofill/autofill_dialog_view.h" 20#include "chrome/browser/ui/autofill/autofill_dialog_view_tester.h" 21#include "chrome/browser/ui/autofill/chrome_autofill_client.h" 22#include "chrome/browser/ui/autofill/data_model_wrapper.h" 23#include "chrome/browser/ui/autofill/mock_address_validator.h" 24#include "chrome/browser/ui/autofill/test_generated_credit_card_bubble_controller.h" 25#include "chrome/browser/ui/browser.h" 26#include "chrome/browser/ui/browser_tabstrip.h" 27#include "chrome/browser/ui/tabs/tab_strip_model.h" 28#include "chrome/common/chrome_switches.h" 29#include "chrome/common/pref_names.h" 30#include "chrome/common/url_constants.h" 31#include "chrome/test/base/in_process_browser_test.h" 32#include "chrome/test/base/ui_test_utils.h" 33#include "components/autofill/content/browser/risk/proto/fingerprint.pb.h" 34#include "components/autofill/content/browser/wallet/gaia_account.h" 35#include "components/autofill/content/browser/wallet/mock_wallet_client.h" 36#include "components/autofill/content/browser/wallet/wallet_service_url.h" 37#include "components/autofill/content/browser/wallet/wallet_test_util.h" 38#include "components/autofill/core/browser/autofill_metrics.h" 39#include "components/autofill/core/browser/autofill_test_utils.h" 40#include "components/autofill/core/browser/test_personal_data_manager.h" 41#include "components/autofill/core/browser/validation.h" 42#include "components/autofill/core/common/autofill_switches.h" 43#include "components/autofill/core/common/form_data.h" 44#include "components/autofill/core/common/form_field_data.h" 45#include "content/public/browser/browser_thread.h" 46#include "content/public/browser/interstitial_page.h" 47#include "content/public/browser/navigation_details.h" 48#include "content/public/browser/navigation_entry.h" 49#include "content/public/browser/notification_service.h" 50#include "content/public/browser/notification_types.h" 51#include "content/public/browser/page_navigator.h" 52#include "content/public/browser/web_contents.h" 53#include "content/public/browser/web_contents_delegate.h" 54#include "content/public/common/content_switches.h" 55#include "content/public/common/referrer.h" 56#include "content/public/common/url_constants.h" 57#include "content/public/test/browser_test_utils.h" 58#include "content/public/test/test_utils.h" 59#include "google_apis/gaia/google_service_auth_error.h" 60#include "net/test/spawned_test_server/spawned_test_server.h" 61#include "testing/gmock/include/gmock/gmock.h" 62#include "testing/gtest/include/gtest/gtest.h" 63#include "third_party/WebKit/public/web/WebInputEvent.h" 64#include "ui/base/page_transition_types.h" 65#include "ui/base/window_open_disposition.h" 66#include "url/gurl.h" 67 68#if defined(OS_WIN) 69#include "base/win/windows_version.h" 70#elif defined(OS_MACOSX) 71#include "base/mac/mac_util.h" 72#include "base/mac/scoped_nsautorelease_pool.h" 73#include "chrome/browser/ui/cocoa/run_loop_testing.h" 74#endif 75 76using base::ASCIIToUTF16; 77 78namespace autofill { 79 80namespace { 81 82using testing::Return; 83using testing::_; 84 85void MockCallback(AutofillClient::RequestAutocompleteResult, 86 const base::string16& message, 87 const FormStructure*) { 88} 89 90class MockAutofillMetrics : public AutofillMetrics { 91 public: 92 MockAutofillMetrics() 93 : dialog_dismissal_action_(static_cast<DialogDismissalAction>(-1)) {} 94 virtual ~MockAutofillMetrics() {} 95 96 virtual void LogDialogUiDuration( 97 const base::TimeDelta& duration, 98 DialogDismissalAction dismissal_action) const OVERRIDE { 99 // Ignore constness for testing. 100 MockAutofillMetrics* mutable_this = const_cast<MockAutofillMetrics*>(this); 101 mutable_this->dialog_dismissal_action_ = dismissal_action; 102 } 103 104 AutofillMetrics::DialogDismissalAction dialog_dismissal_action() const { 105 return dialog_dismissal_action_; 106 } 107 108 MOCK_CONST_METHOD1(LogDialogDismissalState, 109 void(DialogDismissalState state)); 110 111 private: 112 DialogDismissalAction dialog_dismissal_action_; 113 114 DISALLOW_COPY_AND_ASSIGN(MockAutofillMetrics); 115}; 116 117class TestAutofillDialogController : public AutofillDialogControllerImpl { 118 public: 119 TestAutofillDialogController( 120 content::WebContents* contents, 121 const FormData& form_data, 122 const AutofillMetrics& metric_logger, 123 scoped_refptr<content::MessageLoopRunner> runner) 124 : AutofillDialogControllerImpl(contents, 125 form_data, 126 form_data.origin, 127 base::Bind(&MockCallback)), 128 metric_logger_(metric_logger), 129 mock_wallet_client_( 130 Profile::FromBrowserContext(contents->GetBrowserContext())-> 131 GetRequestContext(), this, form_data.origin), 132 message_loop_runner_(runner), 133 use_validation_(false), 134 sign_in_user_index_(0U), 135 weak_ptr_factory_(this) { 136 test_manager_.Init( 137 NULL, 138 Profile::FromBrowserContext(contents->GetBrowserContext())->GetPrefs(), 139 false); 140 } 141 142 virtual ~TestAutofillDialogController() {} 143 144 virtual GURL SignInUrl() const OVERRIDE { 145 return GURL(chrome::kChromeUIVersionURL); 146 } 147 148 virtual void ViewClosed() OVERRIDE { 149 message_loop_runner_->Quit(); 150 AutofillDialogControllerImpl::ViewClosed(); 151 } 152 153 virtual base::string16 InputValidityMessage( 154 DialogSection section, 155 ServerFieldType type, 156 const base::string16& value) OVERRIDE { 157 if (!use_validation_) 158 return base::string16(); 159 return AutofillDialogControllerImpl::InputValidityMessage( 160 section, type, value); 161 } 162 163 virtual ValidityMessages InputsAreValid( 164 DialogSection section, 165 const FieldValueMap& inputs) OVERRIDE { 166 if (!use_validation_) 167 return ValidityMessages(); 168 return AutofillDialogControllerImpl::InputsAreValid(section, inputs); 169 } 170 171 // Saving to Chrome is tested in AutofillDialogControllerImpl unit tests. 172 // TODO(estade): test that the view defaults to saving to Chrome. 173 virtual bool ShouldOfferToSaveInChrome() const OVERRIDE { 174 return true; 175 } 176 177 void ForceFinishSubmit() { 178 DoFinishSubmit(); 179 } 180 181 // Increase visibility for testing. 182 using AutofillDialogControllerImpl::view; 183 using AutofillDialogControllerImpl::popup_input_type; 184 185 MOCK_METHOD0(LoadRiskFingerprintData, void()); 186 187 virtual std::vector<DialogNotification> CurrentNotifications() OVERRIDE { 188 return notifications_; 189 } 190 191 void set_notifications(const std::vector<DialogNotification>& notifications) { 192 notifications_ = notifications; 193 } 194 195 TestPersonalDataManager* GetTestingManager() { 196 return &test_manager_; 197 } 198 199 MockAddressValidator* GetMockValidator() { 200 return &mock_validator_; 201 } 202 203 using AutofillDialogControllerImpl::IsEditingExistingData; 204 using AutofillDialogControllerImpl::IsManuallyEditingSection; 205 using AutofillDialogControllerImpl::IsPayingWithWallet; 206 using AutofillDialogControllerImpl::IsSubmitPausedOn; 207 using AutofillDialogControllerImpl::OnDidLoadRiskFingerprintData; 208 using AutofillDialogControllerImpl::AccountChooserModelForTesting; 209 using AutofillDialogControllerImpl:: 210 ClearLastWalletItemsFetchTimestampForTesting; 211 212 void set_use_validation(bool use_validation) { 213 use_validation_ = use_validation; 214 } 215 216 base::WeakPtr<TestAutofillDialogController> AsWeakPtr() { 217 return weak_ptr_factory_.GetWeakPtr(); 218 } 219 220 wallet::MockWalletClient* GetTestingWalletClient() { 221 return &mock_wallet_client_; 222 } 223 224 void set_sign_in_user_index(size_t sign_in_user_index) { 225 sign_in_user_index_ = sign_in_user_index; 226 } 227 228 protected: 229 virtual PersonalDataManager* GetManager() const OVERRIDE { 230 return &const_cast<TestAutofillDialogController*>(this)->test_manager_; 231 } 232 233 virtual AddressValidator* GetValidator() OVERRIDE { 234 return &mock_validator_; 235 } 236 237 virtual wallet::WalletClient* GetWalletClient() OVERRIDE { 238 return &mock_wallet_client_; 239 } 240 241 virtual bool IsSignInContinueUrl(const GURL& url, size_t* user_index) const 242 OVERRIDE { 243 *user_index = sign_in_user_index_; 244 return url == wallet::GetSignInContinueUrl(); 245 } 246 247 private: 248 // To specify our own metric logger. 249 virtual const AutofillMetrics& GetMetricLogger() const OVERRIDE { 250 return metric_logger_; 251 } 252 253 const AutofillMetrics& metric_logger_; 254 TestPersonalDataManager test_manager_; 255 testing::NiceMock<MockAddressValidator> mock_validator_; 256 testing::NiceMock<wallet::MockWalletClient> mock_wallet_client_; 257 scoped_refptr<content::MessageLoopRunner> message_loop_runner_; 258 bool use_validation_; 259 260 // A list of notifications to show in the notification area of the dialog. 261 // This is used to control what |CurrentNotifications()| returns for testing. 262 std::vector<DialogNotification> notifications_; 263 264 // The user index that is assigned in IsSignInContinueUrl(). 265 size_t sign_in_user_index_; 266 267 // Allows generation of WeakPtrs, so controller liveness can be tested. 268 base::WeakPtrFactory<TestAutofillDialogController> weak_ptr_factory_; 269 270 DISALLOW_COPY_AND_ASSIGN(TestAutofillDialogController); 271}; 272 273// This is a copy of ui_test_utils::UrlLoadObserver, except it observes 274// NAV_ENTRY_COMMITTED instead of LOAD_STOP. This is to match the notification 275// that AutofillDialogControllerImpl observes. Since NAV_ENTRY_COMMITTED comes 276// before LOAD_STOP, and the controller deletes the web contents after receiving 277// the former, we will sometimes fail to observe a LOAD_STOP. 278// TODO(estade): Should the controller observe LOAD_STOP instead? 279class NavEntryCommittedObserver : public content::WindowedNotificationObserver { 280 public: 281 NavEntryCommittedObserver(const GURL& url, 282 const content::NotificationSource& source) 283 : WindowedNotificationObserver(content::NOTIFICATION_NAV_ENTRY_COMMITTED, 284 source), 285 url_(url) {} 286 287 virtual ~NavEntryCommittedObserver() {} 288 289 // content::NotificationObserver: 290 virtual void Observe(int type, 291 const content::NotificationSource& source, 292 const content::NotificationDetails& details) OVERRIDE { 293 content::LoadCommittedDetails* load_details = 294 content::Details<content::LoadCommittedDetails>(details).ptr(); 295 if (load_details->entry->GetVirtualURL() != url_) 296 return; 297 298 WindowedNotificationObserver::Observe(type, source, details); 299 } 300 301 private: 302 GURL url_; 303 304 DISALLOW_COPY_AND_ASSIGN(NavEntryCommittedObserver); 305}; 306 307} // namespace 308 309class AutofillDialogControllerTest : public InProcessBrowserTest { 310 public: 311 AutofillDialogControllerTest() : controller_(NULL) {} 312 virtual ~AutofillDialogControllerTest() {} 313 314 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 315 command_line->AppendSwitch(::switches::kReduceSecurityForTesting); 316 } 317 318 virtual void SetUpOnMainThread() OVERRIDE { 319 autofill::test::DisableSystemServices(browser()->profile()->GetPrefs()); 320 InitializeController(); 321 } 322 323 protected: 324 bool SectionHasField(DialogSection section, ServerFieldType type) { 325 const DetailInputs& fields = 326 controller()->RequestedFieldsForSection(section); 327 for (size_t i = 0; i < fields.size(); ++i) { 328 if (type == fields[i].type) 329 return true; 330 } 331 return false; 332 } 333 334 // A helper function that cycles the MessageLoop, and on Mac, the Cocoa run 335 // loop. It also drains the NSAutoreleasePool. 336 void CycleRunLoops() { 337 content::RunAllPendingInMessageLoop(); 338#if defined(OS_MACOSX) 339 chrome::testing::NSRunLoopRunAllPending(); 340 AutoreleasePool()->Recycle(); 341#endif 342 } 343 344 void InitializeControllerWithoutShowing() { 345 if (controller_) 346 controller_->Hide(); 347 348 FormData form; 349 form.name = ASCIIToUTF16("TestForm"); 350 form.user_submitted = true; 351 352 FormFieldData field; 353 field.autocomplete_attribute = "shipping tel"; 354 form.fields.push_back(field); 355 356 FormFieldData cc; 357 cc.autocomplete_attribute = "cc-number"; 358 form.fields.push_back(cc); 359 360 test_generated_bubble_controller_ = 361 new testing::NiceMock<TestGeneratedCreditCardBubbleController>( 362 GetActiveWebContents()); 363 ASSERT_TRUE(test_generated_bubble_controller_->IsInstalled()); 364 365 message_loop_runner_ = new content::MessageLoopRunner; 366 controller_ = new TestAutofillDialogController( 367 GetActiveWebContents(), 368 form, 369 metric_logger_, 370 message_loop_runner_); 371 } 372 373 void InitializeController() { 374 InitializeControllerWithoutShowing(); 375 controller_->Show(); 376 CycleRunLoops(); // Ensures dialog is fully visible. 377 } 378 379 content::WebContents* GetActiveWebContents() { 380 return browser()->tab_strip_model()->GetActiveWebContents(); 381 } 382 383 content::RenderViewHost* GetRenderViewHost() { 384 return GetActiveWebContents()->GetRenderViewHost(); 385 } 386 387 scoped_ptr<AutofillDialogViewTester> GetViewTester() { 388 return AutofillDialogViewTester::For(controller()->view()).Pass(); 389 } 390 391 const MockAutofillMetrics& metric_logger() { return metric_logger_; } 392 TestAutofillDialogController* controller() { return controller_; } 393 394 void RunMessageLoop() { 395 message_loop_runner_->Run(); 396 } 397 398 // Loads an HTML page in |GetActiveWebContents()| with markup as follows: 399 // <form>|form_inner_html|</form>. After loading, emulates a click event on 400 // the page as requestAutocomplete() must be in response to a user gesture. 401 // Returns the |AutofillDialogControllerImpl| created by this invocation. 402 AutofillDialogControllerImpl* SetUpHtmlAndInvoke( 403 const std::string& form_inner_html) { 404 content::WebContents* contents = GetActiveWebContents(); 405 ChromeAutofillClient* client = 406 ChromeAutofillClient::FromWebContents(contents); 407 CHECK(!client->GetDialogControllerForTesting()); 408 409 ui_test_utils::NavigateToURL( 410 browser(), GURL(std::string("data:text/html,") + 411 "<!doctype html>" 412 "<html>" 413 "<body>" 414 "<form>" + form_inner_html + "</form>" 415 "<script>" 416 "var invalidEvents = [];" 417 "function recordInvalid(e) {" 418 "if (e.type != 'invalid') throw 'only invalid events allowed';" 419 "invalidEvents.push(e);" 420 "}" 421 "function send(msg) {" 422 "domAutomationController.setAutomationId(0);" 423 "domAutomationController.send(msg);" 424 "}" 425 "document.forms[0].onautocompleteerror = function(e) {" 426 "send('error: ' + e.reason);" 427 "};" 428 "document.forms[0].onautocomplete = function() {" 429 "send('success');" 430 "};" 431 "window.onclick = function() {" 432 "var inputs = document.forms[0].querySelectorAll('input');" 433 "for (var i = 0; i < inputs.length; ++i) {" 434 "inputs[i].oninvalid = recordInvalid;" 435 "}" 436 "document.forms[0].requestAutocomplete();" 437 "send('clicked');" 438 "};" 439 "function loadIframe() {" 440 " var iframe = document.createElement('iframe');" 441 " iframe.onload = function() {" 442 " send('iframe loaded');" 443 " };" 444 " iframe.src = 'about:blank';" 445 " document.body.appendChild(iframe);" 446 "}" 447 "function getValueForFieldOfType(type) {" 448 " var fields = document.getElementsByTagName('input');" 449 " for (var i = 0; i < fields.length; i++) {" 450 " if (fields[i].autocomplete == type) {" 451 " send(fields[i].value);" 452 " return;" 453 " }" 454 " }" 455 " send('');" 456 "};" 457 "</script>" 458 "</body>" 459 "</html>")); 460 461 InitiateDialog(); 462 AutofillDialogControllerImpl* controller = 463 static_cast<AutofillDialogControllerImpl*>( 464 client->GetDialogControllerForTesting()); 465 return controller; 466 } 467 468 // Loads an html page on a provided server, the causes it to launch rAc. 469 // Returns whether rAc succesfully launched. 470 bool RunTestPage(const net::SpawnedTestServer& server) { 471 GURL url = server.GetURL( 472 "files/request_autocomplete/test_page.html"); 473 ui_test_utils::NavigateToURL(browser(), url); 474 475 // Pass through the broken SSL interstitial, if any. 476 content::WebContents* contents = GetActiveWebContents(); 477 content::InterstitialPage* interstitial_page = 478 contents->GetInterstitialPage(); 479 if (interstitial_page) { 480 ui_test_utils::UrlLoadObserver observer( 481 url, 482 content::Source<content::NavigationController>( 483 &contents->GetController())); 484 interstitial_page->Proceed(); 485 observer.Wait(); 486 } 487 488 InitiateDialog(); 489 490 ChromeAutofillClient* client = 491 ChromeAutofillClient::FromWebContents(contents); 492 AutofillDialogControllerImpl* controller = 493 static_cast<AutofillDialogControllerImpl*>( 494 client->GetDialogControllerForTesting()); 495 return !!controller; 496 } 497 498 // Wait for a message from the DOM automation controller (from JS in the 499 // page). Requires |SetUpHtmlAndInvoke()| be called first. 500 void ExpectDomMessage(const std::string& expected) { 501 std::string message; 502 ASSERT_TRUE(dom_message_queue_->WaitForMessage(&message)); 503 dom_message_queue_->ClearQueue(); 504 EXPECT_EQ("\"" + expected + "\"", message); 505 } 506 507 void InitiateDialog() { 508 dom_message_queue_.reset(new content::DOMMessageQueue); 509 510 // Triggers the onclick handler which invokes requestAutocomplete(). 511 content::WebContents* contents = GetActiveWebContents(); 512 content::SimulateMouseClick(contents, 0, blink::WebMouseEvent::ButtonLeft); 513 ExpectDomMessage("clicked"); 514 } 515 516 // Returns the value filled into the first field with autocomplete attribute 517 // equal to |autocomplete_type|, or an empty string if there is no such field. 518 std::string GetValueForHTMLFieldOfType(const std::string& autocomplete_type) { 519 std::string script = "getValueForFieldOfType('" + autocomplete_type + "');"; 520 std::string result; 521 EXPECT_TRUE(content::ExecuteScriptAndExtractString(GetRenderViewHost(), 522 script, 523 &result)); 524 return result; 525 } 526 527 void AddCreditcardToProfile(Profile* profile, const CreditCard& card) { 528 PersonalDataManagerFactory::GetForProfile(profile)->AddCreditCard(card); 529 WaitForWebDB(); 530 } 531 532 void AddAutofillProfileToProfile(Profile* profile, 533 const AutofillProfile& autofill_profile) { 534 PersonalDataManagerFactory::GetForProfile(profile)->AddProfile( 535 autofill_profile); 536 WaitForWebDB(); 537 } 538 539 TestGeneratedCreditCardBubbleController* test_generated_bubble_controller() { 540 return test_generated_bubble_controller_; 541 } 542 543 private: 544 void WaitForWebDB() { 545 content::RunAllPendingInMessageLoop(content::BrowserThread::DB); 546 } 547 548 testing::NiceMock<MockAutofillMetrics> metric_logger_; 549 TestAutofillDialogController* controller_; // Weak reference. 550 scoped_refptr<content::MessageLoopRunner> message_loop_runner_; 551 scoped_ptr<content::DOMMessageQueue> dom_message_queue_; 552 553 // Weak; owned by the active web contents. 554 TestGeneratedCreditCardBubbleController* test_generated_bubble_controller_; 555 556 DISALLOW_COPY_AND_ASSIGN(AutofillDialogControllerTest); 557}; 558 559// Submit the form data. 560IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, Submit) { 561 GetViewTester()->SubmitForTesting(); 562 RunMessageLoop(); 563 564 EXPECT_EQ(AutofillMetrics::DIALOG_ACCEPTED, 565 metric_logger().dialog_dismissal_action()); 566} 567 568// Cancel out of the dialog. 569IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, Cancel) { 570 EXPECT_CALL(metric_logger(), 571 LogDialogDismissalState( 572 AutofillMetrics::DIALOG_CANCELED_NO_INVALID_FIELDS)); 573 574 GetViewTester()->CancelForTesting(); 575 RunMessageLoop(); 576 577 EXPECT_EQ(AutofillMetrics::DIALOG_CANCELED, 578 metric_logger().dialog_dismissal_action()); 579} 580 581// Take some other action that dismisses the dialog. 582IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, Hide) { 583 EXPECT_CALL(metric_logger(), 584 LogDialogDismissalState( 585 AutofillMetrics::DIALOG_CANCELED_NO_INVALID_FIELDS)); 586 controller()->Hide(); 587 588 RunMessageLoop(); 589 590 EXPECT_EQ(AutofillMetrics::DIALOG_CANCELED, 591 metric_logger().dialog_dismissal_action()); 592} 593 594IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, CancelWithSuggestions) { 595 EXPECT_CALL(metric_logger(), 596 LogDialogDismissalState( 597 AutofillMetrics::DIALOG_CANCELED_NO_EDITS)); 598 599 CreditCard card(test::GetVerifiedCreditCard()); 600 controller()->GetTestingManager()->AddTestingCreditCard(&card); 601 AutofillProfile profile(test::GetVerifiedProfile()); 602 controller()->GetTestingManager()->AddTestingProfile(&profile); 603 604 EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_CC)); 605 EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_BILLING)); 606 EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_SHIPPING)); 607 608 GetViewTester()->CancelForTesting(); 609 RunMessageLoop(); 610 611 EXPECT_EQ(AutofillMetrics::DIALOG_CANCELED, 612 metric_logger().dialog_dismissal_action()); 613} 614 615IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AcceptWithSuggestions) { 616 EXPECT_CALL(metric_logger(), 617 LogDialogDismissalState( 618 AutofillMetrics::DIALOG_ACCEPTED_EXISTING_AUTOFILL_DATA)); 619 620 CreditCard card(test::GetVerifiedCreditCard()); 621 controller()->GetTestingManager()->AddTestingCreditCard(&card); 622 AutofillProfile profile(test::GetVerifiedProfile()); 623 controller()->GetTestingManager()->AddTestingProfile(&profile); 624 625 EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_CC)); 626 EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_BILLING)); 627 EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_SHIPPING)); 628 629 GetViewTester()->SubmitForTesting(); 630 RunMessageLoop(); 631 632 EXPECT_EQ(AutofillMetrics::DIALOG_ACCEPTED, 633 metric_logger().dialog_dismissal_action()); 634} 635 636// Ensure that Hide() will only destroy the controller object after the 637// message loop has run. Otherwise, there may be read-after-free issues 638// during some tests. 639IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, DeferredDestruction) { 640 base::WeakPtr<TestAutofillDialogController> weak_ptr = 641 controller()->AsWeakPtr(); 642 EXPECT_TRUE(weak_ptr.get()); 643 644 controller()->Hide(); 645 EXPECT_TRUE(weak_ptr.get()); 646 647 RunMessageLoop(); 648 EXPECT_FALSE(weak_ptr.get()); 649} 650 651// Ensure that the expected metric is logged when the dialog is closed during 652// signin. 653IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, CloseDuringSignin) { 654 controller()->SignInLinkClicked(); 655 656 EXPECT_CALL(metric_logger(), 657 LogDialogDismissalState( 658 AutofillMetrics::DIALOG_CANCELED_DURING_SIGNIN)); 659 GetViewTester()->CancelForTesting(); 660 661 RunMessageLoop(); 662 663 EXPECT_EQ(AutofillMetrics::DIALOG_CANCELED, 664 metric_logger().dialog_dismissal_action()); 665} 666 667IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, FillInputFromAutofill) { 668 AutofillProfile full_profile(test::GetFullProfile()); 669 const base::string16 formatted_phone(ASCIIToUTF16("+1 (310) 555 1234")); 670 full_profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, formatted_phone); 671 controller()->GetTestingManager()->AddTestingProfile(&full_profile); 672 673 // Dialog is already asking for a new billing address. 674 EXPECT_TRUE(controller()->IsManuallyEditingSection(SECTION_BILLING)); 675 676 // Select "Add new shipping address...". 677 ui::MenuModel* model = controller()->MenuModelForSection(SECTION_SHIPPING); 678 model->ActivatedAt(model->GetItemCount() - 2); 679 ASSERT_TRUE(controller()->IsManuallyEditingSection(SECTION_SHIPPING)); 680 681 // Enter something in a shipping input. 682 const DetailInputs& inputs = 683 controller()->RequestedFieldsForSection(SECTION_SHIPPING); 684 const ServerFieldType triggering_type = inputs[0].type; 685 base::string16 value = full_profile.GetRawInfo(triggering_type); 686 scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); 687 view->SetTextContentsOfInput(triggering_type, 688 value.substr(0, value.size() / 2)); 689 view->ActivateInput(triggering_type); 690 691 ASSERT_EQ(triggering_type, controller()->popup_input_type()); 692 controller()->DidAcceptSuggestion(base::string16(), 0); 693 694 // All inputs should be filled. 695 AutofillProfileWrapper wrapper(&full_profile); 696 for (size_t i = 0; i < inputs.size(); ++i) { 697 EXPECT_EQ(wrapper.GetInfoForDisplay(AutofillType(inputs[i].type)), 698 view->GetTextContentsOfInput(inputs[i].type)); 699 700 // Double check the correct formatting is used for the phone number. 701 if (inputs[i].type == PHONE_HOME_WHOLE_NUMBER) 702 EXPECT_EQ(formatted_phone, view->GetTextContentsOfInput(inputs[i].type)); 703 } 704 705 // Inputs from the other section (billing) should be left alone. 706 const DetailInputs& other_section_inputs = 707 controller()->RequestedFieldsForSection(SECTION_BILLING); 708 for (size_t i = 0; i < inputs.size(); ++i) { 709 base::string16 input_value = 710 view->GetTextContentsOfInput(other_section_inputs[i].type); 711 // If there's a combobox, the string should be non-empty. 712 if (controller()->ComboboxModelForAutofillType( 713 other_section_inputs[i].type)) { 714 EXPECT_NE(base::string16(), input_value); 715 } else { 716 EXPECT_EQ(base::string16(), input_value); 717 } 718 } 719 720 // Now simulate some user edits and try again. 721 std::vector<base::string16> expectations; 722 for (size_t i = 0; i < inputs.size(); ++i) { 723 if (controller()->ComboboxModelForAutofillType(inputs[i].type)) { 724 expectations.push_back(base::string16()); 725 continue; 726 } 727 base::string16 users_input = i % 2 == 0 ? base::string16() 728 : ASCIIToUTF16("dummy"); 729 view->SetTextContentsOfInput(inputs[i].type, users_input); 730 // Empty inputs should be filled, others should be left alone. 731 base::string16 expectation = 732 inputs[i].type == triggering_type || users_input.empty() ? 733 wrapper.GetInfoForDisplay(AutofillType(inputs[i].type)) : 734 users_input; 735 expectations.push_back(expectation); 736 } 737 738 view->SetTextContentsOfInput(triggering_type, 739 value.substr(0, value.size() / 2)); 740 view->ActivateInput(triggering_type); 741 ASSERT_EQ(triggering_type, controller()->popup_input_type()); 742 controller()->DidAcceptSuggestion(base::string16(), 0); 743 744 for (size_t i = 0; i < inputs.size(); ++i) { 745 if (controller()->ComboboxModelForAutofillType(inputs[i].type)) 746 continue; 747 EXPECT_EQ(expectations[i], view->GetTextContentsOfInput(inputs[i].type)); 748 } 749 750 EXPECT_CALL(metric_logger(), 751 LogDialogDismissalState( 752 AutofillMetrics::DIALOG_ACCEPTED_SAVE_TO_AUTOFILL)); 753 view->SubmitForTesting(); 754} 755 756// This test makes sure that picking a profile variant in the Autofill 757// popup works as expected. 758IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, 759 FillInputFromAutofillVariant) { 760 AutofillProfile full_profile(test::GetFullProfile()); 761 762 // Set up some variant data. 763 std::vector<base::string16> names; 764 names.push_back(ASCIIToUTF16("John Doe")); 765 names.push_back(ASCIIToUTF16("Jane Doe")); 766 full_profile.SetRawMultiInfo(NAME_FULL, names); 767 std::vector<base::string16> emails; 768 emails.push_back(ASCIIToUTF16("user@example.com")); 769 emails.push_back(ASCIIToUTF16("admin@example.com")); 770 full_profile.SetRawMultiInfo(EMAIL_ADDRESS, emails); 771 controller()->GetTestingManager()->AddTestingProfile(&full_profile); 772 773 const DetailInputs& inputs = 774 controller()->RequestedFieldsForSection(SECTION_BILLING); 775 const ServerFieldType triggering_type = inputs[0].type; 776 EXPECT_EQ(NAME_BILLING_FULL, triggering_type); 777 scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); 778 view->ActivateInput(triggering_type); 779 780 ASSERT_EQ(triggering_type, controller()->popup_input_type()); 781 782 // Choose the variant suggestion. 783 controller()->DidAcceptSuggestion(base::string16(), 1); 784 785 // All inputs should be filled. 786 AutofillProfileWrapper wrapper( 787 &full_profile, AutofillType(NAME_BILLING_FULL), 1); 788 for (size_t i = 0; i < inputs.size(); ++i) { 789 EXPECT_EQ(wrapper.GetInfoForDisplay(AutofillType(inputs[i].type)), 790 view->GetTextContentsOfInput(inputs[i].type)); 791 } 792 793 // Make sure the wrapper applies the variant index to the right group. 794 EXPECT_EQ(names[1], wrapper.GetInfo(AutofillType(NAME_BILLING_FULL))); 795 // Make sure the wrapper doesn't apply the variant index to the wrong group. 796 EXPECT_EQ(emails[0], wrapper.GetInfo(AutofillType(EMAIL_ADDRESS))); 797} 798 799// Tests that changing the value of a CC expiration date combobox works as 800// expected when Autofill is used to fill text inputs. 801// 802// Flaky on Win7, WinXP, and Win Aura. http://crbug.com/270314. 803#if defined(OS_WIN) 804#define MAYBE_FillComboboxFromAutofill DISABLED_FillComboboxFromAutofill 805#else 806#define MAYBE_FillComboboxFromAutofill FillComboboxFromAutofill 807#endif 808IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, 809 MAYBE_FillComboboxFromAutofill) { 810 CreditCard card1; 811 test::SetCreditCardInfo(&card1, "JJ Smith", "4111111111111111", "12", "2018"); 812 controller()->GetTestingManager()->AddTestingCreditCard(&card1); 813 CreditCard card2; 814 test::SetCreditCardInfo(&card2, "B Bird", "3111111111111111", "11", "2017"); 815 controller()->GetTestingManager()->AddTestingCreditCard(&card2); 816 AutofillProfile full_profile(test::GetFullProfile()); 817 controller()->GetTestingManager()->AddTestingProfile(&full_profile); 818 819 const DetailInputs& inputs = 820 controller()->RequestedFieldsForSection(SECTION_CC); 821 const ServerFieldType triggering_type = inputs[0].type; 822 base::string16 value = card1.GetRawInfo(triggering_type); 823 scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); 824 view->SetTextContentsOfInput(triggering_type, 825 value.substr(0, value.size() / 2)); 826 view->ActivateInput(triggering_type); 827 828 ASSERT_EQ(triggering_type, controller()->popup_input_type()); 829 controller()->DidAcceptSuggestion(base::string16(), 0); 830 831 // All inputs should be filled. 832 AutofillCreditCardWrapper wrapper1(&card1); 833 for (size_t i = 0; i < inputs.size(); ++i) { 834 EXPECT_EQ(wrapper1.GetInfo(AutofillType(inputs[i].type)), 835 view->GetTextContentsOfInput(inputs[i].type)); 836 } 837 838 // Try again with different data. Only expiration date and the triggering 839 // input should be overwritten. 840 value = card2.GetRawInfo(triggering_type); 841 view->SetTextContentsOfInput(triggering_type, 842 value.substr(0, value.size() / 2)); 843 view->ActivateInput(triggering_type); 844 ASSERT_EQ(triggering_type, controller()->popup_input_type()); 845 controller()->DidAcceptSuggestion(base::string16(), 0); 846 847 AutofillCreditCardWrapper wrapper2(&card2); 848 for (size_t i = 0; i < inputs.size(); ++i) { 849 const ServerFieldType type = inputs[i].type; 850 if (type == triggering_type || 851 type == CREDIT_CARD_EXP_MONTH || 852 type == CREDIT_CARD_EXP_4_DIGIT_YEAR) { 853 EXPECT_EQ(wrapper2.GetInfo(AutofillType(type)), 854 view->GetTextContentsOfInput(type)); 855 } else if (type == CREDIT_CARD_VERIFICATION_CODE) { 856 EXPECT_TRUE(view->GetTextContentsOfInput(type).empty()); 857 } else { 858 EXPECT_EQ(wrapper1.GetInfo(AutofillType(type)), 859 view->GetTextContentsOfInput(type)); 860 } 861 } 862 863 // Now fill from a profile. It should not overwrite any CC info. 864 const DetailInputs& billing_inputs = 865 controller()->RequestedFieldsForSection(SECTION_BILLING); 866 const ServerFieldType billing_triggering_type = billing_inputs[0].type; 867 value = full_profile.GetRawInfo(triggering_type); 868 view->SetTextContentsOfInput(billing_triggering_type, 869 value.substr(0, value.size() / 2)); 870 view->ActivateInput(billing_triggering_type); 871 872 ASSERT_EQ(billing_triggering_type, controller()->popup_input_type()); 873 controller()->DidAcceptSuggestion(base::string16(), 0); 874 875 for (size_t i = 0; i < inputs.size(); ++i) { 876 const ServerFieldType type = inputs[i].type; 877 if (type == triggering_type || 878 type == CREDIT_CARD_EXP_MONTH || 879 type == CREDIT_CARD_EXP_4_DIGIT_YEAR) { 880 EXPECT_EQ(wrapper2.GetInfo(AutofillType(type)), 881 view->GetTextContentsOfInput(type)); 882 } else if (type == CREDIT_CARD_VERIFICATION_CODE) { 883 EXPECT_TRUE(view->GetTextContentsOfInput(type).empty()); 884 } else { 885 EXPECT_EQ(wrapper1.GetInfo(AutofillType(type)), 886 view->GetTextContentsOfInput(type)); 887 } 888 } 889} 890 891IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, ShouldShowErrorBubble) { 892 controller()->set_use_validation(true); 893 EXPECT_TRUE(controller()->ShouldShowErrorBubble()); 894 895 CreditCard card(test::GetCreditCard()); 896 ASSERT_FALSE(card.IsVerified()); 897 controller()->GetTestingManager()->AddTestingCreditCard(&card); 898 899 EXPECT_TRUE(controller()->IsManuallyEditingSection(SECTION_CC)); 900 scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); 901 view->SetTextContentsOfInput( 902 CREDIT_CARD_NUMBER, 903 card.GetRawInfo(CREDIT_CARD_NUMBER).substr(0, 1)); 904 905 view->ActivateInput(CREDIT_CARD_NUMBER); 906 EXPECT_FALSE(controller()->ShouldShowErrorBubble()); 907 908 controller()->FocusMoved(); 909 EXPECT_TRUE(controller()->ShouldShowErrorBubble()); 910 911 EXPECT_CALL(metric_logger(), 912 LogDialogDismissalState( 913 AutofillMetrics::DIALOG_CANCELED_WITH_INVALID_FIELDS)); 914 controller()->Hide(); 915} 916 917// Ensure that expired cards trigger invalid suggestions. 918IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, ExpiredCard) { 919 CreditCard verified_card(test::GetCreditCard()); 920 verified_card.set_origin("Chrome settings"); 921 ASSERT_TRUE(verified_card.IsVerified()); 922 controller()->GetTestingManager()->AddTestingCreditCard(&verified_card); 923 924 CreditCard expired_card(test::GetCreditCard()); 925 expired_card.set_origin("Chrome settings"); 926 expired_card.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2007")); 927 ASSERT_TRUE(expired_card.IsVerified()); 928 ASSERT_FALSE( 929 autofill::IsValidCreditCardExpirationDate( 930 expired_card.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR), 931 expired_card.GetRawInfo(CREDIT_CARD_EXP_MONTH), 932 base::Time::Now())); 933 controller()->GetTestingManager()->AddTestingCreditCard(&expired_card); 934 935 ui::MenuModel* model = controller()->MenuModelForSection(SECTION_CC); 936 ASSERT_EQ(4, model->GetItemCount()); 937 938 ASSERT_TRUE(model->IsItemCheckedAt(0)); 939 EXPECT_FALSE(controller()->IsEditingExistingData(SECTION_CC)); 940 941 model->ActivatedAt(1); 942 ASSERT_TRUE(model->IsItemCheckedAt(1)); 943 EXPECT_TRUE(controller()->IsEditingExistingData(SECTION_CC)); 944} 945 946// Notifications with long message text should not make the dialog bigger. 947IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, LongNotifications) { 948 const gfx::Size no_notification_size = GetViewTester()->GetSize(); 949 ASSERT_GT(no_notification_size.width(), 0); 950 951 std::vector<DialogNotification> notifications; 952 notifications.push_back( 953 DialogNotification(DialogNotification::DEVELOPER_WARNING, ASCIIToUTF16( 954 "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do " 955 "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim " 956 "ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut " 957 "aliquip ex ea commodo consequat. Duis aute irure dolor in " 958 "reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla " 959 "pariatur. Excepteur sint occaecat cupidatat non proident, sunt in " 960 "culpa qui officia deserunt mollit anim id est laborum."))); 961 controller()->set_notifications(notifications); 962 controller()->view()->UpdateNotificationArea(); 963 964 EXPECT_EQ(no_notification_size.width(), 965 GetViewTester()->GetSize().width()); 966} 967 968IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AutocompleteEvent) { 969 AutofillDialogControllerImpl* controller = 970 SetUpHtmlAndInvoke("<input autocomplete='cc-name'>"); 971 ASSERT_TRUE(controller); 972 973 AddCreditcardToProfile(controller->profile(), test::GetVerifiedCreditCard()); 974 AddAutofillProfileToProfile(controller->profile(), 975 test::GetVerifiedProfile()); 976 977 scoped_ptr<AutofillDialogViewTester> view = 978 AutofillDialogViewTester::For( 979 static_cast<TestAutofillDialogController*>(controller)->view()); 980 view->SetTextContentsOfSuggestionInput(SECTION_CC, ASCIIToUTF16("123")); 981 view->SubmitForTesting(); 982 ExpectDomMessage("success"); 983} 984 985IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, 986 AutocompleteErrorEventReasonInvalid) { 987 AutofillDialogControllerImpl* controller = 988 SetUpHtmlAndInvoke("<input autocomplete='cc-name' pattern='.*zebra.*'>"); 989 ASSERT_TRUE(controller); 990 991 const CreditCard& credit_card = test::GetVerifiedCreditCard(); 992 ASSERT_TRUE( 993 credit_card.GetRawInfo(CREDIT_CARD_NAME).find(ASCIIToUTF16("zebra")) == 994 base::string16::npos); 995 AddCreditcardToProfile(controller->profile(), credit_card); 996 AddAutofillProfileToProfile(controller->profile(), 997 test::GetVerifiedProfile()); 998 999 scoped_ptr<AutofillDialogViewTester> view = 1000 AutofillDialogViewTester::For( 1001 static_cast<TestAutofillDialogController*>(controller)->view()); 1002 view->SetTextContentsOfSuggestionInput(SECTION_CC, ASCIIToUTF16("123")); 1003 view->SubmitForTesting(); 1004 ExpectDomMessage("error: invalid"); 1005 1006 int invalid_count = -1; 1007 ASSERT_TRUE(content::ExecuteScriptAndExtractInt( 1008 GetRenderViewHost(), "send(invalidEvents.length);", &invalid_count)); 1009 EXPECT_EQ(1, invalid_count); 1010 1011 std::string invalid_type; 1012 ASSERT_TRUE(content::ExecuteScriptAndExtractString( 1013 GetRenderViewHost(), 1014 "send(invalidEvents[0].target.autocomplete);", 1015 &invalid_type)); 1016 EXPECT_EQ("cc-name", invalid_type); 1017} 1018 1019IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, 1020 AutocompleteErrorEventReasonCancel) { 1021 AutofillDialogControllerImpl* controller = 1022 SetUpHtmlAndInvoke("<input autocomplete='cc-name'>"); 1023 ASSERT_TRUE(controller); 1024 AutofillDialogViewTester::For( 1025 static_cast<TestAutofillDialogController*>(controller)->view())-> 1026 CancelForTesting(); 1027 ExpectDomMessage("error: cancel"); 1028} 1029 1030// http://crbug.com/318526 1031#if defined(OS_MACOSX) 1032#define MAYBE_ErrorWithFrameNavigation DISABLED_ErrorWithFrameNavigation 1033#else 1034#define MAYBE_ErrorWithFrameNavigation ErrorWithFrameNavigation 1035#endif 1036IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, 1037 MAYBE_ErrorWithFrameNavigation) { 1038 AutofillDialogControllerImpl* controller = 1039 SetUpHtmlAndInvoke("<input autocomplete='cc-name'>"); 1040 ASSERT_TRUE(controller); 1041 1042 std::string unused; 1043 ASSERT_TRUE(content::ExecuteScriptAndExtractString(GetRenderViewHost(), 1044 "loadIframe();", 1045 &unused)); 1046 ExpectDomMessage("iframe loaded"); 1047 1048 AutofillDialogViewTester::For( 1049 static_cast<TestAutofillDialogController*>(controller)->view())-> 1050 CancelForTesting(); 1051 ExpectDomMessage("error: cancel"); 1052} 1053 1054IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, NoCvcSegfault) { 1055 controller()->set_use_validation(true); 1056 1057 CreditCard credit_card(test::GetVerifiedCreditCard()); 1058 controller()->GetTestingManager()->AddTestingCreditCard(&credit_card); 1059 EXPECT_FALSE(controller()->IsEditingExistingData(SECTION_CC)); 1060 1061 ASSERT_NO_FATAL_FAILURE(GetViewTester()->SubmitForTesting()); 1062} 1063 1064// Flaky on Win7, WinXP, and Win Aura. http://crbug.com/270314. 1065#if defined(OS_WIN) 1066#define MAYBE_PreservedSections DISABLED_PreservedSections 1067#else 1068#define MAYBE_PreservedSections PreservedSections 1069#endif 1070IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, MAYBE_PreservedSections) { 1071 controller()->set_use_validation(true); 1072 1073 scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); 1074 view->SetTextContentsOfInput(CREDIT_CARD_NUMBER, 1075 ASCIIToUTF16("4111111111111111")); 1076 1077 // Create some invalid, manually inputted shipping data. 1078 view->SetTextContentsOfInput(ADDRESS_HOME_ZIP, ASCIIToUTF16("shipping zip")); 1079 1080 // Switch to Wallet by simulating a successful server response. 1081 controller()->OnDidFetchWalletCookieValue(std::string()); 1082 controller()->OnDidGetWalletItems( 1083 wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED)); 1084 ASSERT_TRUE(controller()->IsPayingWithWallet()); 1085 1086 // The valid data should be preserved. 1087 EXPECT_EQ(ASCIIToUTF16("4111111111111111"), 1088 view->GetTextContentsOfInput(CREDIT_CARD_NUMBER)); 1089 1090 // The invalid data should be dropped. 1091 EXPECT_TRUE(view->GetTextContentsOfInput(ADDRESS_HOME_ZIP).empty()); 1092 1093 // Switch back to Autofill. 1094 ui::MenuModel* account_chooser = controller()->MenuModelForAccountChooser(); 1095 account_chooser->ActivatedAt(account_chooser->GetItemCount() - 1); 1096 ASSERT_FALSE(controller()->IsPayingWithWallet()); 1097 1098 // The valid data should still be preserved when switched back. 1099 EXPECT_EQ(ASCIIToUTF16("4111111111111111"), 1100 view->GetTextContentsOfInput(CREDIT_CARD_NUMBER)); 1101} 1102 1103IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, 1104 GeneratedCardLastFourAfterVerifyCvv) { 1105 controller()->OnDidFetchWalletCookieValue(std::string()); 1106 1107 scoped_ptr<wallet::WalletItems> wallet_items = 1108 wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED); 1109 wallet_items->AddInstrument(wallet::GetTestMaskedInstrument()); 1110 wallet_items->AddAddress(wallet::GetTestShippingAddress()); 1111 1112 base::string16 last_four = 1113 wallet_items->instruments()[0]->TypeAndLastFourDigits(); 1114 controller()->OnDidGetWalletItems(wallet_items.Pass()); 1115 1116 scoped_ptr<AutofillDialogViewTester> test_view = GetViewTester(); 1117 EXPECT_FALSE(test_view->IsShowingOverlay()); 1118 EXPECT_CALL(*controller(), LoadRiskFingerprintData()); 1119 controller()->OnAccept(); 1120 EXPECT_TRUE(test_view->IsShowingOverlay()); 1121 1122 EXPECT_CALL(*controller()->GetTestingWalletClient(), GetFullWallet(_)); 1123 scoped_ptr<risk::Fingerprint> fingerprint(new risk::Fingerprint()); 1124 fingerprint->mutable_machine_characteristics()->mutable_screen_size()-> 1125 set_width(1024); 1126 controller()->OnDidLoadRiskFingerprintData(fingerprint.Pass()); 1127 1128 controller()->OnDidGetFullWallet( 1129 wallet::GetTestFullWalletWithRequiredActions( 1130 std::vector<wallet::RequiredAction>(1, wallet::VERIFY_CVV))); 1131 1132 ASSERT_TRUE(controller()->IsSubmitPausedOn(wallet::VERIFY_CVV)); 1133 1134 std::string fake_cvc("123"); 1135 test_view->SetTextContentsOfSuggestionInput(SECTION_CC_BILLING, 1136 ASCIIToUTF16(fake_cvc)); 1137 1138 EXPECT_FALSE(test_view->IsShowingOverlay()); 1139 EXPECT_CALL(*controller()->GetTestingWalletClient(), 1140 AuthenticateInstrument(_, fake_cvc)); 1141 controller()->OnAccept(); 1142 EXPECT_TRUE(test_view->IsShowingOverlay()); 1143 1144 EXPECT_CALL(metric_logger(), 1145 LogDialogDismissalState( 1146 AutofillMetrics::DIALOG_ACCEPTED_EXISTING_WALLET_DATA)); 1147 1148 EXPECT_CALL(*controller()->GetTestingWalletClient(), GetFullWallet(_)); 1149 controller()->OnDidAuthenticateInstrument(true); 1150 controller()->OnDidGetFullWallet(wallet::GetTestFullWallet()); 1151 controller()->ForceFinishSubmit(); 1152 1153 RunMessageLoop(); 1154 1155 EXPECT_EQ(1, test_generated_bubble_controller()->bubbles_shown()); 1156 EXPECT_EQ(last_four, test_generated_bubble_controller()->backing_card_name()); 1157} 1158 1159// Simulates the user signing in to the dialog from the inline web contents. 1160IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, SimulateSuccessfulSignIn) { 1161#if defined(OS_WIN) 1162 // TODO(msw): Fix potential flakiness on Windows XP; http://crbug.com/333641 1163 if (base::win::GetVersion() <= base::win::VERSION_XP) 1164 return; 1165#endif 1166 browser()->profile()->GetPrefs()->SetBoolean( 1167 ::prefs::kAutofillDialogPayWithoutWallet, 1168 true); 1169 1170 InitializeController(); 1171 1172 controller()->OnDidFetchWalletCookieValue(std::string()); 1173 controller()->OnDidGetWalletItems( 1174 wallet::GetTestWalletItemsWithRequiredAction(wallet::GAIA_AUTH)); 1175 1176 NavEntryCommittedObserver sign_in_page_observer( 1177 controller()->SignInUrl(), 1178 content::NotificationService::AllSources()); 1179 1180 // Simulate a user clicking "Sign In" (which loads dialog's web contents). 1181 controller()->SignInLinkClicked(); 1182 EXPECT_TRUE(controller()->ShouldShowSignInWebView()); 1183 1184 scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); 1185 content::WebContents* sign_in_contents = view->GetSignInWebContents(); 1186 ASSERT_TRUE(sign_in_contents); 1187 1188 sign_in_page_observer.Wait(); 1189 1190 NavEntryCommittedObserver continue_page_observer( 1191 wallet::GetSignInContinueUrl(), 1192 content::NotificationService::AllSources()); 1193 1194 EXPECT_EQ(sign_in_contents->GetURL(), controller()->SignInUrl()); 1195 1196 AccountChooserModel* account_chooser_model = 1197 controller()->AccountChooserModelForTesting(); 1198 EXPECT_FALSE(account_chooser_model->WalletIsSelected()); 1199 1200 content::OpenURLParams params(wallet::GetSignInContinueUrl(), 1201 content::Referrer(), 1202 CURRENT_TAB, 1203 ui::PAGE_TRANSITION_LINK, 1204 true); 1205 1206 sign_in_contents->GetDelegate()->OpenURLFromTab(sign_in_contents, params); 1207 1208 EXPECT_CALL(*controller()->GetTestingWalletClient(), GetWalletItems(_, _)); 1209 continue_page_observer.Wait(); 1210 content::RunAllPendingInMessageLoop(); 1211 1212 EXPECT_FALSE(controller()->ShouldShowSignInWebView()); 1213 1214 scoped_ptr<wallet::WalletItems> wallet_items = 1215 wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED); 1216 wallet_items->AddInstrument(wallet::GetTestMaskedInstrument()); 1217 controller()->OnDidGetWalletItems(wallet_items.Pass()); 1218 1219 // Wallet should now be selected and Chrome shouldn't have crashed (which can 1220 // happen if the WebContents is deleted while proccessing a nav entry commit). 1221 EXPECT_TRUE(account_chooser_model->WalletIsSelected()); 1222 EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_CC_BILLING)); 1223 EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_SHIPPING)); 1224 1225 EXPECT_CALL(metric_logger(), 1226 LogDialogDismissalState( 1227 AutofillMetrics::DIALOG_ACCEPTED_EXISTING_WALLET_DATA)); 1228 view->SubmitForTesting(); 1229 controller()->OnDidGetFullWallet(wallet::GetTestFullWallet()); 1230 controller()->ForceFinishSubmit(); 1231} 1232 1233IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AddAccount) { 1234#if defined(OS_WIN) 1235 // TODO(msw): Fix potential flakiness on Windows XP; http://crbug.com/333641 1236 if (base::win::GetVersion() <= base::win::VERSION_XP) 1237 return; 1238#endif 1239 1240 controller()->OnDidFetchWalletCookieValue(std::string()); 1241 std::vector<std::string> usernames; 1242 usernames.push_back("user_0@example.com"); 1243 controller()->OnDidGetWalletItems( 1244 wallet::GetTestWalletItemsWithUsers(usernames, 0)); 1245 1246 // Switch to Autofill. 1247 AccountChooserModel* account_chooser_model = 1248 controller()->AccountChooserModelForTesting(); 1249 account_chooser_model->ActivatedAt( 1250 account_chooser_model->GetItemCount() - 1); 1251 1252 NavEntryCommittedObserver sign_in_page_observer( 1253 controller()->SignInUrl(), 1254 content::NotificationService::AllSources()); 1255 1256 // Simulate a user clicking "add account". 1257 account_chooser_model->ActivatedAt( 1258 account_chooser_model->GetItemCount() - 2); 1259 EXPECT_TRUE(controller()->ShouldShowSignInWebView()); 1260 1261 scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); 1262 content::WebContents* sign_in_contents = view->GetSignInWebContents(); 1263 ASSERT_TRUE(sign_in_contents); 1264 1265 sign_in_page_observer.Wait(); 1266 1267 NavEntryCommittedObserver continue_page_observer( 1268 wallet::GetSignInContinueUrl(), 1269 content::NotificationService::AllSources()); 1270 1271 EXPECT_EQ(sign_in_contents->GetURL(), controller()->SignInUrl()); 1272 1273 EXPECT_FALSE(account_chooser_model->WalletIsSelected()); 1274 1275 // User signs into new account, account 3. 1276 controller()->set_sign_in_user_index(3U); 1277 content::OpenURLParams params(wallet::GetSignInContinueUrl(), 1278 content::Referrer(), 1279 CURRENT_TAB, 1280 ui::PAGE_TRANSITION_LINK, 1281 true); 1282 sign_in_contents->GetDelegate()->OpenURLFromTab(sign_in_contents, params); 1283 1284 EXPECT_CALL(*controller()->GetTestingWalletClient(), GetWalletItems(_, _)); 1285 continue_page_observer.Wait(); 1286 content::RunAllPendingInMessageLoop(); 1287 1288 EXPECT_FALSE(controller()->ShouldShowSignInWebView()); 1289 EXPECT_EQ(3U, controller()->GetTestingWalletClient()->user_index()); 1290 1291 usernames.push_back("user_1@example.com"); 1292 usernames.push_back("user_2@example.com"); 1293 usernames.push_back("user_3@example.com"); 1294 usernames.push_back("user_4@example.com"); 1295 // Curveball: wallet items comes back with user 4 selected. 1296 controller()->OnDidGetWalletItems( 1297 wallet::GetTestWalletItemsWithUsers(usernames, 4U)); 1298 1299 EXPECT_TRUE(account_chooser_model->WalletIsSelected()); 1300 EXPECT_EQ(4U, account_chooser_model->GetActiveWalletAccountIndex()); 1301 EXPECT_EQ(4U, controller()->GetTestingWalletClient()->user_index()); 1302} 1303 1304// Verify that filling a form works correctly, including filling the CVC when 1305// that is requested separately. 1306IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, 1307 FillFormIncludesCVC) { 1308 AutofillDialogControllerImpl* controller = 1309 SetUpHtmlAndInvoke("<input autocomplete='cc-csc'>"); 1310 ASSERT_TRUE(controller); 1311 1312 AddCreditcardToProfile(controller->profile(), test::GetVerifiedCreditCard()); 1313 AddAutofillProfileToProfile(controller->profile(), 1314 test::GetVerifiedProfile()); 1315 1316 scoped_ptr<AutofillDialogViewTester> view = 1317 AutofillDialogViewTester::For( 1318 static_cast<TestAutofillDialogController*>(controller)->view()); 1319 view->SetTextContentsOfSuggestionInput(SECTION_CC, ASCIIToUTF16("123")); 1320 view->SubmitForTesting(); 1321 ExpectDomMessage("success"); 1322 EXPECT_EQ("123", GetValueForHTMLFieldOfType("cc-csc")); 1323} 1324 1325IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AddNewClearsComboboxes) { 1326 // Ensure the input under test is a combobox. 1327 ASSERT_TRUE( 1328 controller()->ComboboxModelForAutofillType(CREDIT_CARD_EXP_MONTH)); 1329 1330 // Set up an expired card. 1331 CreditCard card; 1332 test::SetCreditCardInfo(&card, "Roy Demeo", "4111111111111111", "8", "2013"); 1333 card.set_origin("Chrome settings"); 1334 ASSERT_TRUE(card.IsVerified()); 1335 1336 // Add the card and check that there's a menu for that section. 1337 controller()->GetTestingManager()->AddTestingCreditCard(&card); 1338 ASSERT_TRUE(controller()->MenuModelForSection(SECTION_CC)); 1339 1340 // Select the invalid, suggested card from the menu. 1341 controller()->MenuModelForSection(SECTION_CC)->ActivatedAt(0); 1342 EXPECT_TRUE(controller()->IsEditingExistingData(SECTION_CC)); 1343 1344 // Get the contents of the combobox of the credit card's expiration month. 1345 scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); 1346 base::string16 cc_exp_month_text = 1347 view->GetTextContentsOfInput(CREDIT_CARD_EXP_MONTH); 1348 1349 // Select "New X..." from the suggestion menu to clear the section's inputs. 1350 controller()->MenuModelForSection(SECTION_CC)->ActivatedAt(1); 1351 EXPECT_FALSE(controller()->IsEditingExistingData(SECTION_CC)); 1352 1353 // Ensure that the credit card expiration month has changed. 1354 EXPECT_NE(cc_exp_month_text, 1355 view->GetTextContentsOfInput(CREDIT_CARD_EXP_MONTH)); 1356} 1357 1358IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, TabOpensToJustRight) { 1359 ASSERT_TRUE(browser()->is_type_tabbed()); 1360 1361 // Tabs should currently be: / rAc() \. 1362 content::WebContents* dialog_invoker = controller()->GetWebContents(); 1363 EXPECT_EQ(dialog_invoker, GetActiveWebContents()); 1364 1365 TabStripModel* tab_strip = browser()->tab_strip_model(); 1366 ASSERT_EQ(1, tab_strip->count()); 1367 EXPECT_EQ(0, tab_strip->GetIndexOfWebContents(dialog_invoker)); 1368 1369 // Open a tab to about:blank in the background at the end of the tab strip. 1370 chrome::AddTabAt(browser(), GURL(), -1, false); 1371 // Tabs should now be: / rAc() \/ blank \. 1372 EXPECT_EQ(2, tab_strip->count()); 1373 EXPECT_EQ(0, tab_strip->active_index()); 1374 EXPECT_EQ(dialog_invoker, GetActiveWebContents()); 1375 1376 content::WebContents* blank_tab = tab_strip->GetWebContentsAt(1); 1377 1378 // Simulate clicking "Manage X...". 1379 controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(2); 1380 // Tab should now be: / rAc() \/ manage 1 \/ blank \. 1381 EXPECT_EQ(3, tab_strip->count()); 1382 int dialog_index = tab_strip->GetIndexOfWebContents(dialog_invoker); 1383 EXPECT_EQ(0, dialog_index); 1384 EXPECT_EQ(1, tab_strip->active_index()); 1385 EXPECT_EQ(2, tab_strip->GetIndexOfWebContents(blank_tab)); 1386 1387 content::WebContents* first_manage_tab = tab_strip->GetWebContentsAt(1); 1388 1389 // Re-activate the dialog's tab (like a user would have to). 1390 tab_strip->ActivateTabAt(dialog_index, true); 1391 EXPECT_EQ(dialog_invoker, GetActiveWebContents()); 1392 1393 // Simulate clicking "Manage X...". 1394 controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(2); 1395 // Tabs should now be: / rAc() \/ manage 2 \/ manage 1 \/ blank \. 1396 EXPECT_EQ(4, tab_strip->count()); 1397 EXPECT_EQ(0, tab_strip->GetIndexOfWebContents(dialog_invoker)); 1398 EXPECT_EQ(1, tab_strip->active_index()); 1399 EXPECT_EQ(2, tab_strip->GetIndexOfWebContents(first_manage_tab)); 1400 EXPECT_EQ(3, tab_strip->GetIndexOfWebContents(blank_tab)); 1401} 1402 1403IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, 1404 SignInWebViewOpensLinksInNewTab) { 1405 controller()->OnDidFetchWalletCookieValue(std::string()); 1406 controller()->OnDidGetWalletItems( 1407 wallet::GetTestWalletItemsWithRequiredAction(wallet::GAIA_AUTH)); 1408 1409 NavEntryCommittedObserver sign_in_page_observer( 1410 controller()->SignInUrl(), 1411 content::NotificationService::AllSources()); 1412 1413 controller()->SignInLinkClicked(); 1414 1415 content::WebContents* sign_in_contents = 1416 GetViewTester()->GetSignInWebContents(); 1417 ASSERT_TRUE(sign_in_contents); 1418 1419 sign_in_page_observer.Wait(); 1420 1421 content::OpenURLParams params(GURL("http://google.com"), 1422 content::Referrer(), 1423 CURRENT_TAB, 1424 ui::PAGE_TRANSITION_LINK, 1425 true); 1426 params.user_gesture = true; 1427 1428 int num_tabs = browser()->tab_strip_model()->count(); 1429 sign_in_contents->GetDelegate()->OpenURLFromTab(sign_in_contents, params); 1430 EXPECT_EQ(num_tabs + 1, browser()->tab_strip_model()->count()); 1431} 1432 1433IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, RefreshOnManageTabClose) { 1434 ASSERT_TRUE(browser()->is_type_tabbed()); 1435 1436 // GetWalletItems(_, _) is called when controller() is created in SetUp(). 1437 EXPECT_CALL(*controller()->GetTestingWalletClient(), GetWalletItems(_, _)); 1438 controller()->OnDidFetchWalletCookieValue(std::string()); 1439 controller()->OnDidGetWalletItems( 1440 wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED)); 1441 1442 content::WebContents* dialog_invoker = controller()->GetWebContents(); 1443 ChromeAutofillClient::FromWebContents(dialog_invoker) 1444 ->SetDialogControllerForTesting(controller()->AsWeakPtr()); 1445 1446 // Open a new tab by selecting "Manage my shipping details..." in Wallet mode. 1447 EXPECT_EQ(1, browser()->tab_strip_model()->count()); 1448 controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(2); 1449 EXPECT_EQ(2, browser()->tab_strip_model()->count()); 1450 ASSERT_NE(dialog_invoker, GetActiveWebContents()); 1451 1452 // Closing the tab opened by "Manage my shipping details..." should refresh 1453 // the dialog. 1454 controller()->ClearLastWalletItemsFetchTimestampForTesting(); 1455 EXPECT_CALL(*controller()->GetTestingWalletClient(), GetWalletItems(_, _)); 1456 GetActiveWebContents()->Close(); 1457} 1458 1459// Changes from Wallet to Autofill and verifies that the combined billing/cc 1460// sections are showing (or not) at the correct times. 1461IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, 1462 ChangingDataSourceShowsCorrectSections) { 1463 scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); 1464 EXPECT_TRUE(view->IsShowingSection(SECTION_CC)); 1465 EXPECT_TRUE(view->IsShowingSection(SECTION_BILLING)); 1466 EXPECT_FALSE(view->IsShowingSection(SECTION_CC_BILLING)); 1467 1468 // Switch the dialog to paying with Wallet. 1469 controller()->OnDidFetchWalletCookieValue(std::string()); 1470 controller()->OnDidGetWalletItems( 1471 wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED)); 1472 ASSERT_TRUE(controller()->IsPayingWithWallet()); 1473 1474 EXPECT_FALSE(view->IsShowingSection(SECTION_CC)); 1475 EXPECT_FALSE(view->IsShowingSection(SECTION_BILLING)); 1476 EXPECT_TRUE(view->IsShowingSection(SECTION_CC_BILLING)); 1477 1478 // Now switch back to Autofill to ensure this direction works as well. 1479 ui::MenuModel* account_chooser = controller()->MenuModelForAccountChooser(); 1480 account_chooser->ActivatedAt(account_chooser->GetItemCount() - 1); 1481 1482 EXPECT_TRUE(view->IsShowingSection(SECTION_CC)); 1483 EXPECT_TRUE(view->IsShowingSection(SECTION_BILLING)); 1484 EXPECT_FALSE(view->IsShowingSection(SECTION_CC_BILLING)); 1485} 1486 1487IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, 1488 DoesWorkOnHttpWithFlag) { 1489 net::SpawnedTestServer http_server( 1490 net::SpawnedTestServer::TYPE_HTTP, 1491 net::SpawnedTestServer::kLocalhost, 1492 base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); 1493 ASSERT_TRUE(http_server.Start()); 1494 EXPECT_TRUE(RunTestPage(http_server)); 1495} 1496 1497// Like the parent test, but doesn't add the --reduce-security-for-testing flag. 1498class AutofillDialogControllerSecurityTest : 1499 public AutofillDialogControllerTest { 1500 public: 1501 AutofillDialogControllerSecurityTest() {} 1502 virtual ~AutofillDialogControllerSecurityTest() {} 1503 1504 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 1505 CHECK(!command_line->HasSwitch(::switches::kReduceSecurityForTesting)); 1506 } 1507 1508 typedef net::BaseTestServer::SSLOptions SSLOptions; 1509 1510 private: 1511 DISALLOW_COPY_AND_ASSIGN(AutofillDialogControllerSecurityTest); 1512}; 1513 1514IN_PROC_BROWSER_TEST_F(AutofillDialogControllerSecurityTest, 1515 DoesntWorkOnHttp) { 1516 net::SpawnedTestServer http_server( 1517 net::SpawnedTestServer::TYPE_HTTP, 1518 net::SpawnedTestServer::kLocalhost, 1519 base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); 1520 ASSERT_TRUE(http_server.Start()); 1521 EXPECT_FALSE(RunTestPage(http_server)); 1522} 1523 1524IN_PROC_BROWSER_TEST_F(AutofillDialogControllerSecurityTest, 1525 DoesWorkOnHttpWithFlags) { 1526 net::SpawnedTestServer https_server( 1527 net::SpawnedTestServer::TYPE_HTTPS, 1528 SSLOptions(SSLOptions::CERT_OK), 1529 base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); 1530 ASSERT_TRUE(https_server.Start()); 1531 EXPECT_TRUE(RunTestPage(https_server)); 1532} 1533 1534IN_PROC_BROWSER_TEST_F(AutofillDialogControllerSecurityTest, 1535 DoesntWorkOnBrokenHttps) { 1536 net::SpawnedTestServer https_server( 1537 net::SpawnedTestServer::TYPE_HTTPS, 1538 SSLOptions(SSLOptions::CERT_EXPIRED), 1539 base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); 1540 ASSERT_TRUE(https_server.Start()); 1541 EXPECT_FALSE(RunTestPage(https_server)); 1542} 1543 1544IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, 1545 CountryChangeRebuildsSection) { 1546 EXPECT_FALSE(SectionHasField(SECTION_BILLING, ADDRESS_BILLING_SORTING_CODE)); 1547 EXPECT_FALSE(SectionHasField(SECTION_SHIPPING, ADDRESS_HOME_SORTING_CODE)); 1548 1549 // Select "Add new shipping address...". 1550 controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(1); 1551 1552 // Add some valid user input that should be preserved when country changes. 1553 scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); 1554 view->SetTextContentsOfInput(NAME_FULL, ASCIIToUTF16("B. Loblaw")); 1555 1556 // Change both sections' countries. 1557 view->SetTextContentsOfInput(ADDRESS_BILLING_COUNTRY, ASCIIToUTF16("France")); 1558 view->ActivateInput(ADDRESS_BILLING_COUNTRY); 1559 view->SetTextContentsOfInput(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("Belarus")); 1560 view->ActivateInput(ADDRESS_HOME_COUNTRY); 1561 1562 // Verify the name is still there. 1563 EXPECT_EQ(ASCIIToUTF16("B. Loblaw"), view->GetTextContentsOfInput(NAME_FULL)); 1564 1565 EXPECT_TRUE(SectionHasField(SECTION_BILLING, ADDRESS_BILLING_SORTING_CODE)); 1566 EXPECT_TRUE(SectionHasField(SECTION_SHIPPING, ADDRESS_HOME_SORTING_CODE)); 1567} 1568 1569// Changing the data source to or from Wallet preserves the shipping country, 1570// but not the billing country because Wallet only supports US billing 1571// addresses. 1572IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, 1573 ChangingDataSourcePreservesCountry) { 1574 InitializeControllerWithoutShowing(); 1575 controller()->GetTestingManager()->set_default_country_code("CA"); 1576 controller()->Show(); 1577 CycleRunLoops(); 1578 1579 AutofillProfile verified_profile(test::GetVerifiedProfile()); 1580 controller()->GetTestingManager()->AddTestingProfile(&verified_profile); 1581 1582 CreditCard verified_card(test::GetVerifiedCreditCard()); 1583 controller()->GetTestingManager()->AddTestingCreditCard(&verified_card); 1584 EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_SHIPPING)); 1585 1586 controller()->OnDidFetchWalletCookieValue(std::string()); 1587 scoped_ptr<wallet::WalletItems> items = 1588 wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED); 1589 items->AddAccount(wallet::GetTestGaiaAccount()); 1590 items->AddInstrument(wallet::GetTestMaskedInstrument()); 1591 items->AddAddress(wallet::GetTestShippingAddress()); 1592 controller()->OnDidGetWalletItems(items.Pass()); 1593 1594 EXPECT_TRUE(controller()->IsPayingWithWallet()); 1595 1596 // Select "Add new shipping address...". 1597 controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(2); 1598 EXPECT_TRUE(controller()->IsManuallyEditingSection(SECTION_SHIPPING)); 1599 1600 // Default shipping country matches PDM's default, but default billing is 1601 // always US in Wallet mode. 1602 scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); 1603 ASSERT_EQ(ASCIIToUTF16("Canada"), 1604 view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY)); 1605 ASSERT_EQ(ASCIIToUTF16("United States"), 1606 view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY)); 1607 1608 // Switch the shipping country. 1609 view->SetTextContentsOfInput(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("Belarus")); 1610 EXPECT_EQ(ASCIIToUTF16("Belarus"), 1611 view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY)); 1612 view->ActivateInput(ADDRESS_HOME_COUNTRY); 1613 1614 // Switch to using Autofill instead of Wallet. 1615 ui::MenuModel* account_chooser = controller()->MenuModelForAccountChooser(); 1616 account_chooser->ActivatedAt(account_chooser->GetItemCount() - 1); 1617 1618 EXPECT_FALSE(controller()->IsPayingWithWallet()); 1619 1620 // Shipping country should have stayed the same. 1621 EXPECT_EQ(ASCIIToUTF16("Belarus"), 1622 view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY)); 1623 ASSERT_TRUE(SectionHasField(SECTION_SHIPPING, ADDRESS_HOME_SORTING_CODE)); 1624 1625 controller()->MenuModelForSection(SECTION_BILLING)->ActivatedAt(1); 1626 view->SetTextContentsOfInput(ADDRESS_BILLING_COUNTRY, 1627 ASCIIToUTF16("Belarus")); 1628 view->ActivateInput(ADDRESS_BILLING_COUNTRY); 1629 EXPECT_EQ(ASCIIToUTF16("Belarus"), 1630 view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY)); 1631 ASSERT_TRUE(SectionHasField(SECTION_BILLING, ADDRESS_BILLING_SORTING_CODE)); 1632 1633 // Switch back to Wallet. Country should go back to US. 1634 account_chooser->ActivatedAt(0); 1635 EXPECT_EQ(ASCIIToUTF16("United States"), 1636 view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY)); 1637 ASSERT_FALSE( 1638 SectionHasField(SECTION_CC_BILLING, ADDRESS_BILLING_SORTING_CODE)); 1639 1640 // Make sure shipping is still on Belarus. 1641 EXPECT_EQ(ASCIIToUTF16("Belarus"), 1642 view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY)); 1643 ASSERT_TRUE(SectionHasField(SECTION_SHIPPING, ADDRESS_HOME_SORTING_CODE)); 1644} 1645 1646IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AddNewResetsCountry) { 1647 AutofillProfile verified_profile(test::GetVerifiedProfile()); 1648 controller()->GetTestingManager()->AddTestingProfile(&verified_profile); 1649 1650 // Select "Add new billing/shipping address...". 1651 controller()->MenuModelForSection(SECTION_BILLING)->ActivatedAt(1); 1652 controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(2); 1653 1654 scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); 1655 ASSERT_EQ(ASCIIToUTF16("United States"), 1656 view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY)); 1657 ASSERT_EQ(ASCIIToUTF16("United States"), 1658 view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY)); 1659 1660 // Switch both billing and shipping countries. 1661 view->SetTextContentsOfInput(ADDRESS_BILLING_COUNTRY, ASCIIToUTF16("Brazil")); 1662 view->ActivateInput(ADDRESS_BILLING_COUNTRY); 1663 view->SetTextContentsOfInput(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("France")); 1664 view->ActivateInput(ADDRESS_HOME_COUNTRY); 1665 1666 // Select "Add new billing/shipping address...". 1667 controller()->MenuModelForSection(SECTION_BILLING)->ActivatedAt(1); 1668 controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(2); 1669 1670 EXPECT_EQ(ASCIIToUTF16("United States"), 1671 view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY)); 1672 EXPECT_EQ(ASCIIToUTF16("United States"), 1673 view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY)); 1674} 1675 1676IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, 1677 FillingFormRebuildsInputs) { 1678 AutofillProfile full_profile(test::GetFullProfile()); 1679 full_profile.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("DE")); 1680 controller()->GetTestingManager()->AddTestingProfile(&full_profile); 1681 1682 // Select "Add new shipping address...". 1683 controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(1); 1684 1685 scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); 1686 ASSERT_EQ(ASCIIToUTF16("United States"), 1687 view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY)); 1688 ASSERT_EQ(ASCIIToUTF16("United States"), 1689 view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY)); 1690 1691 const ServerFieldType input_type = EMAIL_ADDRESS; 1692 base::string16 name = full_profile.GetRawInfo(input_type); 1693 view->SetTextContentsOfInput(input_type, name.substr(0, name.size() / 2)); 1694 view->ActivateInput(input_type); 1695 ASSERT_EQ(input_type, controller()->popup_input_type()); 1696 controller()->DidAcceptSuggestion(base::string16(), 0); 1697 1698 EXPECT_EQ(ASCIIToUTF16("Germany"), 1699 view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY)); 1700 EXPECT_EQ(ASCIIToUTF16("United States"), 1701 view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY)); 1702} 1703 1704IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, 1705 FillingFormPreservesChangedCountry) { 1706 AutofillProfile full_profile(test::GetFullProfile()); 1707 full_profile.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("DE")); 1708 controller()->GetTestingManager()->AddTestingProfile(&full_profile); 1709 1710 // Select "Add new shipping address...". 1711 controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(1); 1712 1713 scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); 1714 view->SetTextContentsOfInput(ADDRESS_BILLING_COUNTRY, ASCIIToUTF16("France")); 1715 view->ActivateInput(ADDRESS_BILLING_COUNTRY); 1716 view->SetTextContentsOfInput(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("Belarus")); 1717 view->ActivateInput(ADDRESS_HOME_COUNTRY); 1718 1719 base::string16 name = full_profile.GetRawInfo(NAME_FULL); 1720 view->SetTextContentsOfInput(NAME_FULL, name.substr(0, name.size() / 2)); 1721 view->ActivateInput(NAME_FULL); 1722 ASSERT_EQ(NAME_FULL, controller()->popup_input_type()); 1723 controller()->DidAcceptSuggestion(base::string16(), 0); 1724 1725 EXPECT_EQ(ASCIIToUTF16("France"), 1726 view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY)); 1727 EXPECT_EQ(ASCIIToUTF16("Belarus"), 1728 view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY)); 1729} 1730 1731IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, RulesLoaded) { 1732 // Select "Add new shipping address...". 1733 controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(1); 1734 controller()->set_use_validation(true); 1735 1736 EXPECT_CALL(*controller()->GetMockValidator(), 1737 ValidateAddress(CountryCodeMatcher("DE"), _, _)).Times(2). 1738 WillOnce(Return(AddressValidator::RULES_NOT_READY)); 1739 1740 // Validation should occur on country change and see the rules haven't loaded. 1741 scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); 1742 view->SetTextContentsOfInput(ADDRESS_HOME_ZIP, ASCIIToUTF16("123")); 1743 view->SetTextContentsOfInput(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("Germany")); 1744 view->ActivateInput(ADDRESS_HOME_COUNTRY); 1745 1746 // Different country loaded, validation should not occur. 1747 controller()->OnAddressValidationRulesLoaded("FR", true); 1748 1749 // Relevant country loaded, validation should occur. 1750 controller()->OnAddressValidationRulesLoaded("DE", true); 1751 1752 // Relevant country loaded but revalidation already happened, no further 1753 // validation should occur. 1754 controller()->OnAddressValidationRulesLoaded("DE", false); 1755 1756 // Cancelling the dialog causes additional validation to see if the user 1757 // cancelled with invalid fields, so verify and clear here. 1758 testing::Mock::VerifyAndClearExpectations(controller()->GetMockValidator()); 1759} 1760 1761IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, 1762 TransactionAmount) { 1763 std::string html( 1764 "<input type='number' step='0.01'" 1765 " autocomplete='transaction-amount' value='24'>" 1766 "<input autocomplete='transaction-currency' value='USD'>" 1767 "<input autocomplete='cc-csc'>"); 1768 AutofillDialogControllerImpl* controller = SetUpHtmlAndInvoke(html); 1769 ASSERT_TRUE(controller); 1770 1771 EXPECT_EQ(ASCIIToUTF16("24"), controller->transaction_amount_); 1772 EXPECT_EQ(ASCIIToUTF16("USD"), controller->transaction_currency_); 1773} 1774 1775} // namespace autofill 1776