autofill_dialog_controller_browsertest.cc revision 0f1bc08d4cfcc34181b0b5cbf065c40f687bf740
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/memory/ref_counted.h" 8#include "base/memory/weak_ptr.h" 9#include "base/message_loop/message_loop.h" 10#include "base/prefs/pref_service.h" 11#include "base/strings/utf_string_conversions.h" 12#include "base/time/time.h" 13#include "chrome/browser/autofill/personal_data_manager_factory.h" 14#include "chrome/browser/profiles/profile.h" 15#include "chrome/browser/ui/autofill/account_chooser_model.h" 16#include "chrome/browser/ui/autofill/autofill_dialog_controller_impl.h" 17#include "chrome/browser/ui/autofill/autofill_dialog_view.h" 18#include "chrome/browser/ui/autofill/data_model_wrapper.h" 19#include "chrome/browser/ui/autofill/tab_autofill_manager_delegate.h" 20#include "chrome/browser/ui/autofill/test_generated_credit_card_bubble_controller.h" 21#include "chrome/browser/ui/autofill/testable_autofill_dialog_view.h" 22#include "chrome/browser/ui/browser.h" 23#include "chrome/browser/ui/tabs/tab_strip_model.h" 24#include "chrome/common/pref_names.h" 25#include "chrome/test/base/in_process_browser_test.h" 26#include "chrome/test/base/ui_test_utils.h" 27#include "components/autofill/content/browser/risk/proto/fingerprint.pb.h" 28#include "components/autofill/content/browser/wallet/mock_wallet_client.h" 29#include "components/autofill/content/browser/wallet/wallet_test_util.h" 30#include "components/autofill/core/browser/autofill_common_test.h" 31#include "components/autofill/core/browser/autofill_metrics.h" 32#include "components/autofill/core/browser/test_personal_data_manager.h" 33#include "components/autofill/core/browser/validation.h" 34#include "components/autofill/core/common/autofill_switches.h" 35#include "components/autofill/core/common/form_data.h" 36#include "components/autofill/core/common/form_field_data.h" 37#include "content/public/browser/browser_thread.h" 38#include "content/public/browser/notification_service.h" 39#include "content/public/browser/web_contents.h" 40#include "content/public/browser/web_contents_delegate.h" 41#include "content/public/common/url_constants.h" 42#include "content/public/test/browser_test_utils.h" 43#include "content/public/test/test_utils.h" 44#include "testing/gmock/include/gmock/gmock.h" 45#include "testing/gtest/include/gtest/gtest.h" 46#include "third_party/WebKit/public/web/WebInputEvent.h" 47#include "url/gurl.h" 48 49namespace autofill { 50 51namespace { 52 53using testing::_; 54 55void MockCallback(const FormStructure*) {} 56 57class MockAutofillMetrics : public AutofillMetrics { 58 public: 59 MockAutofillMetrics() 60 : dialog_dismissal_action_( 61 static_cast<AutofillMetrics::DialogDismissalAction>(-1)) {} 62 virtual ~MockAutofillMetrics() {} 63 64 virtual void LogDialogUiDuration( 65 const base::TimeDelta& duration, 66 DialogDismissalAction dismissal_action) const OVERRIDE { 67 // Ignore constness for testing. 68 MockAutofillMetrics* mutable_this = const_cast<MockAutofillMetrics*>(this); 69 mutable_this->dialog_dismissal_action_ = dismissal_action; 70 } 71 72 AutofillMetrics::DialogDismissalAction dialog_dismissal_action() const { 73 return dialog_dismissal_action_; 74 } 75 76 MOCK_CONST_METHOD1(LogDialogDismissalState, 77 void(DialogDismissalState state)); 78 79 private: 80 AutofillMetrics::DialogDismissalAction dialog_dismissal_action_; 81 82 DISALLOW_COPY_AND_ASSIGN(MockAutofillMetrics); 83}; 84 85class TestAutofillDialogController : public AutofillDialogControllerImpl { 86 public: 87 TestAutofillDialogController( 88 content::WebContents* contents, 89 const FormData& form_data, 90 const AutofillMetrics& metric_logger, 91 scoped_refptr<content::MessageLoopRunner> runner) 92 : AutofillDialogControllerImpl(contents, 93 form_data, 94 form_data.origin, 95 base::Bind(&MockCallback)), 96 metric_logger_(metric_logger), 97 mock_wallet_client_( 98 Profile::FromBrowserContext(contents->GetBrowserContext())-> 99 GetRequestContext(), this, form_data.origin), 100 message_loop_runner_(runner), 101 use_validation_(false), 102 weak_ptr_factory_(this) {} 103 104 virtual ~TestAutofillDialogController() {} 105 106 virtual GURL SignInUrl() const OVERRIDE { 107 return GURL(content::kAboutBlankURL); 108 } 109 110 virtual void ViewClosed() OVERRIDE { 111 message_loop_runner_->Quit(); 112 AutofillDialogControllerImpl::ViewClosed(); 113 } 114 115 virtual string16 InputValidityMessage( 116 DialogSection section, 117 ServerFieldType type, 118 const string16& value) OVERRIDE { 119 if (!use_validation_) 120 return string16(); 121 return AutofillDialogControllerImpl::InputValidityMessage( 122 section, type, value); 123 } 124 125 virtual ValidityMessages InputsAreValid( 126 DialogSection section, 127 const DetailOutputMap& inputs) OVERRIDE { 128 if (!use_validation_) 129 return ValidityMessages(); 130 return AutofillDialogControllerImpl::InputsAreValid(section, inputs); 131 } 132 133 // Saving to Chrome is tested in AutofillDialogControllerImpl unit tests. 134 // TODO(estade): test that the view defaults to saving to Chrome. 135 virtual bool ShouldOfferToSaveInChrome() const OVERRIDE { 136 return false; 137 } 138 139 void ForceFinishSubmit() { 140 DoFinishSubmit(); 141 } 142 143 // Increase visibility for testing. 144 using AutofillDialogControllerImpl::view; 145 using AutofillDialogControllerImpl::input_showing_popup; 146 147 MOCK_METHOD0(LoadRiskFingerprintData, void()); 148 149 virtual std::vector<DialogNotification> CurrentNotifications() OVERRIDE { 150 return notifications_; 151 } 152 153 void set_notifications(const std::vector<DialogNotification>& notifications) { 154 notifications_ = notifications; 155 } 156 157 TestPersonalDataManager* GetTestingManager() { 158 return &test_manager_; 159 } 160 161 using AutofillDialogControllerImpl::IsEditingExistingData; 162 using AutofillDialogControllerImpl::IsManuallyEditingSection; 163 using AutofillDialogControllerImpl::IsSubmitPausedOn; 164 using AutofillDialogControllerImpl::OnDidLoadRiskFingerprintData; 165 using AutofillDialogControllerImpl::AccountChooserModelForTesting; 166 167 void set_use_validation(bool use_validation) { 168 use_validation_ = use_validation; 169 } 170 171 base::WeakPtr<TestAutofillDialogController> AsWeakPtr() { 172 return weak_ptr_factory_.GetWeakPtr(); 173 } 174 175 wallet::MockWalletClient* GetTestingWalletClient() { 176 return &mock_wallet_client_; 177 } 178 179 protected: 180 virtual PersonalDataManager* GetManager() OVERRIDE { 181 return &test_manager_; 182 } 183 184 virtual wallet::WalletClient* GetWalletClient() OVERRIDE { 185 return &mock_wallet_client_; 186 } 187 188 virtual bool IsSignInContinueUrl(const GURL& url) const OVERRIDE { 189 return true; 190 } 191 192 private: 193 // To specify our own metric logger. 194 virtual const AutofillMetrics& GetMetricLogger() const OVERRIDE { 195 return metric_logger_; 196 } 197 198 const AutofillMetrics& metric_logger_; 199 TestPersonalDataManager test_manager_; 200 testing::NiceMock<wallet::MockWalletClient> mock_wallet_client_; 201 scoped_refptr<content::MessageLoopRunner> message_loop_runner_; 202 bool use_validation_; 203 204 // A list of notifications to show in the notification area of the dialog. 205 // This is used to control what |CurrentNotifications()| returns for testing. 206 std::vector<DialogNotification> notifications_; 207 208 // Allows generation of WeakPtrs, so controller liveness can be tested. 209 base::WeakPtrFactory<TestAutofillDialogController> weak_ptr_factory_; 210 211 DISALLOW_COPY_AND_ASSIGN(TestAutofillDialogController); 212}; 213 214} // namespace 215 216class AutofillDialogControllerTest : public InProcessBrowserTest { 217 public: 218 AutofillDialogControllerTest() {} 219 virtual ~AutofillDialogControllerTest() {} 220 221 virtual void SetUpOnMainThread() OVERRIDE { 222 autofill::test::DisableSystemServices(browser()->profile()); 223 InitializeController(); 224 } 225 226 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 227#if defined(OS_MACOSX) 228 // OSX support for requestAutocomplete is still hidden behind a switch. 229 // Pending resolution of http://crbug.com/157274 230 CommandLine::ForCurrentProcess()->AppendSwitch( 231 switches::kEnableInteractiveAutocomplete); 232#endif 233 } 234 235 void InitializeController() { 236 FormData form; 237 form.name = ASCIIToUTF16("TestForm"); 238 form.method = ASCIIToUTF16("POST"); 239 form.origin = GURL("http://example.com/form.html"); 240 form.action = GURL("http://example.com/submit.html"); 241 form.user_submitted = true; 242 243 FormFieldData field; 244 field.autocomplete_attribute = "shipping tel"; 245 form.fields.push_back(field); 246 247 test_generated_bubble_controller_ = 248 new testing::NiceMock<TestGeneratedCreditCardBubbleController>( 249 GetActiveWebContents()); 250 ASSERT_TRUE(test_generated_bubble_controller_->IsInstalled()); 251 252 message_loop_runner_ = new content::MessageLoopRunner; 253 controller_ = new TestAutofillDialogController( 254 GetActiveWebContents(), 255 form, 256 metric_logger_, 257 message_loop_runner_); 258 controller_->Show(); 259 } 260 261 content::WebContents* GetActiveWebContents() { 262 return browser()->tab_strip_model()->GetActiveWebContents(); 263 } 264 265 const MockAutofillMetrics& metric_logger() { return metric_logger_; } 266 TestAutofillDialogController* controller() { return controller_; } 267 268 void RunMessageLoop() { 269 message_loop_runner_->Run(); 270 } 271 272 // Loads an HTML page in |GetActiveWebContents()| with markup as follows: 273 // <form>|form_inner_html|</form>. After loading, emulates a click event on 274 // the page as requestAutocomplete() must be in response to a user gesture. 275 // Returns the |AutofillDialogControllerImpl| created by this invocation. 276 AutofillDialogControllerImpl* SetUpHtmlAndInvoke( 277 const std::string& form_inner_html) { 278 content::WebContents* contents = GetActiveWebContents(); 279 TabAutofillManagerDelegate* delegate = 280 TabAutofillManagerDelegate::FromWebContents(contents); 281 DCHECK(!delegate->GetDialogControllerForTesting()); 282 283 ui_test_utils::NavigateToURL( 284 browser(), GURL(std::string("data:text/html,") + 285 "<!doctype html>" 286 "<html>" 287 "<body>" 288 "<form>" + form_inner_html + "</form>" 289 "<script>" 290 "function send(msg) {" 291 "domAutomationController.setAutomationId(0);" 292 "domAutomationController.send(msg);" 293 "}" 294 "document.forms[0].onautocompleteerror = function(e) {" 295 "send('error: ' + e.reason);" 296 "};" 297 "document.forms[0].onautocomplete = function() {" 298 "send('success');" 299 "};" 300 "window.onclick = function() {" 301 "document.forms[0].requestAutocomplete();" 302 "send('clicked');" 303 "};" 304 "function getValueForFieldOfType(type) {" 305 " var fields = document.getElementsByTagName('input');" 306 " for (var i = 0; i < fields.length; i++) {" 307 " if (fields[i].autocomplete == type) {" 308 " send(fields[i].value);" 309 " return;" 310 " }" 311 " }" 312 " send('');" 313 "};" 314 "</script>" 315 "</body>" 316 "</html>")); 317 content::WaitForLoadStop(contents); 318 319 dom_message_queue_.reset(new content::DOMMessageQueue); 320 321 // Triggers the onclick handler which invokes requestAutocomplete(). 322 content::SimulateMouseClick(contents, 0, WebKit::WebMouseEvent::ButtonLeft); 323 ExpectDomMessage("clicked"); 324 325 AutofillDialogControllerImpl* controller = 326 static_cast<AutofillDialogControllerImpl*>( 327 delegate->GetDialogControllerForTesting()); 328 DCHECK(controller); 329 return controller; 330 } 331 332 // Wait for a message from the DOM automation controller (from JS in the 333 // page). Requires |SetUpHtmlAndInvoke()| be called first. 334 void ExpectDomMessage(const std::string& expected) { 335 std::string message; 336 ASSERT_TRUE(dom_message_queue_->WaitForMessage(&message)); 337 dom_message_queue_->ClearQueue(); 338 EXPECT_EQ("\"" + expected + "\"", message); 339 } 340 341 // Returns the value filled into the first field with autocomplete attribute 342 // equal to |autocomplete_type|, or an empty string if there is no such field. 343 std::string GetValueForHTMLFieldOfType(const std::string& autocomplete_type) { 344 content::RenderViewHost* render_view_host = 345 browser()->tab_strip_model()->GetActiveWebContents()-> 346 GetRenderViewHost(); 347 std::string script = "getValueForFieldOfType('" + autocomplete_type + "');"; 348 std::string result; 349 EXPECT_TRUE(content::ExecuteScriptAndExtractString(render_view_host, script, 350 &result)); 351 return result; 352 } 353 354 void AddCreditcardToProfile(Profile* profile, const CreditCard& card) { 355 PersonalDataManagerFactory::GetForProfile(profile)->AddCreditCard(card); 356 WaitForWebDB(); 357 } 358 359 void AddAutofillProfileToProfile(Profile* profile, 360 const AutofillProfile& autofill_profile) { 361 PersonalDataManagerFactory::GetForProfile(profile)->AddProfile( 362 autofill_profile); 363 WaitForWebDB(); 364 } 365 366 TestGeneratedCreditCardBubbleController* test_generated_bubble_controller() { 367 return test_generated_bubble_controller_; 368 } 369 370 private: 371 void WaitForWebDB() { 372 content::RunAllPendingInMessageLoop(content::BrowserThread::DB); 373 } 374 375 testing::NiceMock<MockAutofillMetrics> metric_logger_; 376 TestAutofillDialogController* controller_; // Weak reference. 377 scoped_refptr<content::MessageLoopRunner> message_loop_runner_; 378 scoped_ptr<content::DOMMessageQueue> dom_message_queue_; 379 380 // Weak; owned by the active web contents. 381 TestGeneratedCreditCardBubbleController* test_generated_bubble_controller_; 382 383 DISALLOW_COPY_AND_ASSIGN(AutofillDialogControllerTest); 384}; 385 386#if defined(TOOLKIT_VIEWS) || defined(OS_MACOSX) 387// Submit the form data. 388IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, Submit) { 389 controller()->GetTestableView()->SubmitForTesting(); 390 391 RunMessageLoop(); 392 393 EXPECT_EQ(AutofillMetrics::DIALOG_ACCEPTED, 394 metric_logger().dialog_dismissal_action()); 395} 396 397// Cancel out of the dialog. 398IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, Cancel) { 399 controller()->GetTestableView()->CancelForTesting(); 400 401 RunMessageLoop(); 402 403 EXPECT_EQ(AutofillMetrics::DIALOG_CANCELED, 404 metric_logger().dialog_dismissal_action()); 405} 406 407// Take some other action that dismisses the dialog. 408IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, Hide) { 409 controller()->Hide(); 410 411 RunMessageLoop(); 412 413 EXPECT_EQ(AutofillMetrics::DIALOG_CANCELED, 414 metric_logger().dialog_dismissal_action()); 415} 416 417// Ensure that Hide() will only destroy the controller object after the 418// message loop has run. Otherwise, there may be read-after-free issues 419// during some tests. 420IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, DeferredDestruction) { 421 base::WeakPtr<TestAutofillDialogController> weak_ptr = 422 controller()->AsWeakPtr(); 423 EXPECT_TRUE(weak_ptr.get()); 424 425 controller()->Hide(); 426 EXPECT_TRUE(weak_ptr.get()); 427 428 RunMessageLoop(); 429 EXPECT_FALSE(weak_ptr.get()); 430} 431 432// Ensure that the expected metric is logged when the dialog is closed during 433// signin. 434IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, CloseDuringSignin) { 435 controller()->SignInLinkClicked(); 436 437 EXPECT_CALL(metric_logger(), 438 LogDialogDismissalState( 439 AutofillMetrics::DIALOG_CANCELED_DURING_SIGNIN)); 440 controller()->GetTestableView()->CancelForTesting(); 441 442 RunMessageLoop(); 443 444 EXPECT_EQ(AutofillMetrics::DIALOG_CANCELED, 445 metric_logger().dialog_dismissal_action()); 446} 447 448IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, FillInputFromAutofill) { 449 AutofillProfile full_profile(test::GetFullProfile()); 450 controller()->GetTestingManager()->AddTestingProfile(&full_profile); 451 452 const DetailInputs& inputs = 453 controller()->RequestedFieldsForSection(SECTION_SHIPPING); 454 const DetailInput& triggering_input = inputs[0]; 455 string16 value = full_profile.GetRawInfo(triggering_input.type); 456 TestableAutofillDialogView* view = controller()->GetTestableView(); 457 view->SetTextContentsOfInput(triggering_input, 458 value.substr(0, value.size() / 2)); 459 view->ActivateInput(triggering_input); 460 461 ASSERT_EQ(&triggering_input, controller()->input_showing_popup()); 462 controller()->DidAcceptSuggestion(string16(), 0); 463 464 // All inputs should be filled. 465 AutofillProfileWrapper wrapper(&full_profile); 466 for (size_t i = 0; i < inputs.size(); ++i) { 467 EXPECT_EQ(wrapper.GetInfo(AutofillType(inputs[i].type)), 468 view->GetTextContentsOfInput(inputs[i])); 469 } 470 471 // Now simulate some user edits and try again. 472 std::vector<string16> expectations; 473 for (size_t i = 0; i < inputs.size(); ++i) { 474 string16 users_input = i % 2 == 0 ? string16() : ASCIIToUTF16("dummy"); 475 view->SetTextContentsOfInput(inputs[i], users_input); 476 // Empty inputs should be filled, others should be left alone. 477 string16 expectation = 478 &inputs[i] == &triggering_input || users_input.empty() ? 479 wrapper.GetInfo(AutofillType(inputs[i].type)) : 480 users_input; 481 expectations.push_back(expectation); 482 } 483 484 view->SetTextContentsOfInput(triggering_input, 485 value.substr(0, value.size() / 2)); 486 view->ActivateInput(triggering_input); 487 ASSERT_EQ(&triggering_input, controller()->input_showing_popup()); 488 controller()->DidAcceptSuggestion(string16(), 0); 489 490 for (size_t i = 0; i < inputs.size(); ++i) { 491 EXPECT_EQ(expectations[i], view->GetTextContentsOfInput(inputs[i])); 492 } 493} 494 495// This test makes sure that picking a profile variant in the Autofill 496// popup works as expected. 497IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, 498 FillInputFromAutofillVariant) { 499 AutofillProfile full_profile(test::GetFullProfile()); 500 501 // Set up some variant data. 502 std::vector<string16> names; 503 names.push_back(ASCIIToUTF16("John Doe")); 504 names.push_back(ASCIIToUTF16("Jane Doe")); 505 full_profile.SetRawMultiInfo(NAME_FULL, names); 506 std::vector<string16> emails; 507 emails.push_back(ASCIIToUTF16("user@example.com")); 508 emails.push_back(ASCIIToUTF16("admin@example.com")); 509 full_profile.SetRawMultiInfo(EMAIL_ADDRESS, emails); 510 controller()->GetTestingManager()->AddTestingProfile(&full_profile); 511 512 const DetailInputs& inputs = 513 controller()->RequestedFieldsForSection(SECTION_BILLING); 514 const DetailInput& triggering_input = inputs[0]; 515 EXPECT_EQ(NAME_BILLING_FULL, triggering_input.type); 516 TestableAutofillDialogView* view = controller()->GetTestableView(); 517 view->ActivateInput(triggering_input); 518 519 ASSERT_EQ(&triggering_input, controller()->input_showing_popup()); 520 521 // Choose the variant suggestion. 522 controller()->DidAcceptSuggestion(string16(), 1); 523 524 // All inputs should be filled. 525 AutofillProfileWrapper wrapper( 526 &full_profile, AutofillType(NAME_BILLING_FULL), 1); 527 for (size_t i = 0; i < inputs.size(); ++i) { 528 EXPECT_EQ(wrapper.GetInfo(AutofillType(inputs[i].type)), 529 view->GetTextContentsOfInput(inputs[i])); 530 } 531 532 // Make sure the wrapper applies the variant index to the right group. 533 EXPECT_EQ(names[1], wrapper.GetInfo(AutofillType(NAME_BILLING_FULL))); 534 // Make sure the wrapper doesn't apply the variant index to the wrong group. 535 EXPECT_EQ(emails[0], wrapper.GetInfo(AutofillType(EMAIL_ADDRESS))); 536} 537 538// Tests that changing the value of a CC expiration date combobox works as 539// expected when Autofill is used to fill text inputs. 540// 541// Flaky on Win7, WinXP, and Win Aura. http://crbug.com/270314. 542#if defined(OS_WIN) 543#define MAYBE_FillComboboxFromAutofill DISABLED_FillComboboxFromAutofill 544#else 545#define MAYBE_FillComboboxFromAutofill FillComboboxFromAutofill 546#endif 547IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, 548 MAYBE_FillComboboxFromAutofill) { 549 CreditCard card1; 550 test::SetCreditCardInfo(&card1, "JJ Smith", "4111111111111111", "12", "2018"); 551 controller()->GetTestingManager()->AddTestingCreditCard(&card1); 552 CreditCard card2; 553 test::SetCreditCardInfo(&card2, "B Bird", "3111111111111111", "11", "2017"); 554 controller()->GetTestingManager()->AddTestingCreditCard(&card2); 555 AutofillProfile full_profile(test::GetFullProfile()); 556 controller()->GetTestingManager()->AddTestingProfile(&full_profile); 557 558 const DetailInputs& inputs = 559 controller()->RequestedFieldsForSection(SECTION_CC); 560 const DetailInput& triggering_input = inputs[0]; 561 string16 value = card1.GetRawInfo(triggering_input.type); 562 TestableAutofillDialogView* view = controller()->GetTestableView(); 563 view->SetTextContentsOfInput(triggering_input, 564 value.substr(0, value.size() / 2)); 565 view->ActivateInput(triggering_input); 566 567 ASSERT_EQ(&triggering_input, controller()->input_showing_popup()); 568 controller()->DidAcceptSuggestion(string16(), 0); 569 570 // All inputs should be filled. 571 AutofillCreditCardWrapper wrapper1(&card1); 572 for (size_t i = 0; i < inputs.size(); ++i) { 573 EXPECT_EQ(wrapper1.GetInfo(AutofillType(inputs[i].type)), 574 view->GetTextContentsOfInput(inputs[i])); 575 } 576 577 // Try again with different data. Only expiration date and the triggering 578 // input should be overwritten. 579 value = card2.GetRawInfo(triggering_input.type); 580 view->SetTextContentsOfInput(triggering_input, 581 value.substr(0, value.size() / 2)); 582 view->ActivateInput(triggering_input); 583 ASSERT_EQ(&triggering_input, controller()->input_showing_popup()); 584 controller()->DidAcceptSuggestion(string16(), 0); 585 586 AutofillCreditCardWrapper wrapper2(&card2); 587 for (size_t i = 0; i < inputs.size(); ++i) { 588 const DetailInput& input = inputs[i]; 589 if (&input == &triggering_input || 590 input.type == CREDIT_CARD_EXP_MONTH || 591 input.type == CREDIT_CARD_EXP_4_DIGIT_YEAR) { 592 EXPECT_EQ(wrapper2.GetInfo(AutofillType(input.type)), 593 view->GetTextContentsOfInput(input)); 594 } else if (input.type == CREDIT_CARD_VERIFICATION_CODE) { 595 EXPECT_TRUE(view->GetTextContentsOfInput(input).empty()); 596 } else { 597 EXPECT_EQ(wrapper1.GetInfo(AutofillType(input.type)), 598 view->GetTextContentsOfInput(input)); 599 } 600 } 601 602 // Now fill from a profile. It should not overwrite any CC info. 603 const DetailInputs& billing_inputs = 604 controller()->RequestedFieldsForSection(SECTION_BILLING); 605 const DetailInput& billing_triggering_input = billing_inputs[0]; 606 value = full_profile.GetRawInfo(triggering_input.type); 607 view->SetTextContentsOfInput(billing_triggering_input, 608 value.substr(0, value.size() / 2)); 609 view->ActivateInput(billing_triggering_input); 610 611 ASSERT_EQ(&billing_triggering_input, controller()->input_showing_popup()); 612 controller()->DidAcceptSuggestion(string16(), 0); 613 614 for (size_t i = 0; i < inputs.size(); ++i) { 615 const DetailInput& input = inputs[i]; 616 if (&input == &triggering_input || 617 input.type == CREDIT_CARD_EXP_MONTH || 618 input.type == CREDIT_CARD_EXP_4_DIGIT_YEAR) { 619 EXPECT_EQ(wrapper2.GetInfo(AutofillType(input.type)), 620 view->GetTextContentsOfInput(input)); 621 } else if (input.type == CREDIT_CARD_VERIFICATION_CODE) { 622 EXPECT_TRUE(view->GetTextContentsOfInput(input).empty()); 623 } else { 624 EXPECT_EQ(wrapper1.GetInfo(AutofillType(input.type)), 625 view->GetTextContentsOfInput(input)); 626 } 627 } 628} 629 630IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, ShouldShowErrorBubble) { 631 EXPECT_TRUE(controller()->ShouldShowErrorBubble()); 632 633 CreditCard card(test::GetCreditCard()); 634 ASSERT_FALSE(card.IsVerified()); 635 controller()->GetTestingManager()->AddTestingCreditCard(&card); 636 637 const DetailInputs& cc_inputs = 638 controller()->RequestedFieldsForSection(SECTION_CC); 639 const DetailInput& cc_number_input = cc_inputs[0]; 640 ASSERT_EQ(CREDIT_CARD_NUMBER, cc_number_input.type); 641 642 TestableAutofillDialogView* view = controller()->GetTestableView(); 643 view->SetTextContentsOfInput( 644 cc_number_input, 645 card.GetRawInfo(CREDIT_CARD_NUMBER).substr(0, 1)); 646 647 view->ActivateInput(cc_number_input); 648 EXPECT_FALSE(controller()->ShouldShowErrorBubble()); 649 650 controller()->FocusMoved(); 651 EXPECT_TRUE(controller()->ShouldShowErrorBubble()); 652} 653 654// Ensure that expired cards trigger invalid suggestions. 655IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, ExpiredCard) { 656 CreditCard verified_card(test::GetCreditCard()); 657 verified_card.set_origin("Chrome settings"); 658 ASSERT_TRUE(verified_card.IsVerified()); 659 controller()->GetTestingManager()->AddTestingCreditCard(&verified_card); 660 661 CreditCard expired_card(test::GetCreditCard()); 662 expired_card.set_origin("Chrome settings"); 663 expired_card.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2007")); 664 ASSERT_TRUE(expired_card.IsVerified()); 665 ASSERT_FALSE( 666 autofill::IsValidCreditCardExpirationDate( 667 expired_card.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR), 668 expired_card.GetRawInfo(CREDIT_CARD_EXP_MONTH), 669 base::Time::Now())); 670 controller()->GetTestingManager()->AddTestingCreditCard(&expired_card); 671 672 ui::MenuModel* model = controller()->MenuModelForSection(SECTION_CC); 673 ASSERT_EQ(4, model->GetItemCount()); 674 675 ASSERT_TRUE(model->IsItemCheckedAt(0)); 676 EXPECT_FALSE(controller()->IsEditingExistingData(SECTION_CC)); 677 678 model->ActivatedAt(1); 679 ASSERT_TRUE(model->IsItemCheckedAt(1)); 680 EXPECT_TRUE(controller()->IsEditingExistingData(SECTION_CC)); 681} 682 683// Notifications with long message text should not make the dialog bigger. 684IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, LongNotifications) { 685 const gfx::Size no_notification_size = 686 controller()->GetTestableView()->GetSize(); 687 ASSERT_GT(no_notification_size.width(), 0); 688 689 std::vector<DialogNotification> notifications; 690 notifications.push_back( 691 DialogNotification(DialogNotification::DEVELOPER_WARNING, ASCIIToUTF16( 692 "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do " 693 "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim " 694 "ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut " 695 "aliquip ex ea commodo consequat. Duis aute irure dolor in " 696 "reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla " 697 "pariatur. Excepteur sint occaecat cupidatat non proident, sunt in " 698 "culpa qui officia deserunt mollit anim id est laborum."))); 699 controller()->set_notifications(notifications); 700 controller()->view()->UpdateNotificationArea(); 701 702 EXPECT_EQ(no_notification_size.width(), 703 controller()->GetTestableView()->GetSize().width()); 704} 705 706IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AutocompleteEvent) { 707 AutofillDialogControllerImpl* controller = 708 SetUpHtmlAndInvoke("<input autocomplete='cc-name'>"); 709 710 AddCreditcardToProfile(controller->profile(), test::GetVerifiedCreditCard()); 711 AddAutofillProfileToProfile(controller->profile(), 712 test::GetVerifiedProfile()); 713 714 TestableAutofillDialogView* view = controller->GetTestableView(); 715 view->SetTextContentsOfSuggestionInput(SECTION_CC, ASCIIToUTF16("123")); 716 view->SubmitForTesting(); 717 ExpectDomMessage("success"); 718} 719 720IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, 721 AutocompleteErrorEventReasonInvalid) { 722 AutofillDialogControllerImpl* controller = 723 SetUpHtmlAndInvoke("<input autocomplete='cc-name' pattern='.*zebra.*'>"); 724 725 const CreditCard& credit_card = test::GetVerifiedCreditCard(); 726 ASSERT_TRUE( 727 credit_card.GetRawInfo(CREDIT_CARD_NAME).find(ASCIIToUTF16("zebra")) == 728 base::string16::npos); 729 AddCreditcardToProfile(controller->profile(), credit_card); 730 AddAutofillProfileToProfile(controller->profile(), 731 test::GetVerifiedProfile()); 732 733 TestableAutofillDialogView* view = controller->GetTestableView(); 734 view->SetTextContentsOfSuggestionInput(SECTION_CC, ASCIIToUTF16("123")); 735 view->SubmitForTesting(); 736 ExpectDomMessage("error: invalid"); 737} 738 739IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, 740 AutocompleteErrorEventReasonCancel) { 741 SetUpHtmlAndInvoke("<input autocomplete='cc-name'>")->GetTestableView()-> 742 CancelForTesting(); 743 ExpectDomMessage("error: cancel"); 744} 745 746IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, NoCvcSegfault) { 747 controller()->set_use_validation(true); 748 749 CreditCard credit_card(test::GetVerifiedCreditCard()); 750 controller()->GetTestingManager()->AddTestingCreditCard(&credit_card); 751 EXPECT_FALSE(controller()->IsEditingExistingData(SECTION_CC)); 752 753 ASSERT_NO_FATAL_FAILURE( 754 controller()->GetTestableView()->SubmitForTesting()); 755} 756 757// Flaky on Win7, WinXP, and Win Aura. http://crbug.com/270314. 758#if defined(OS_WIN) 759#define MAYBE_PreservedSections DISABLED_PreservedSections 760#else 761#define MAYBE_PreservedSections PreservedSections 762#endif 763IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, MAYBE_PreservedSections) { 764 controller()->set_use_validation(true); 765 766 // Set up some Autofill state. 767 CreditCard credit_card(test::GetVerifiedCreditCard()); 768 controller()->GetTestingManager()->AddTestingCreditCard(&credit_card); 769 770 AutofillProfile profile(test::GetVerifiedProfile()); 771 controller()->GetTestingManager()->AddTestingProfile(&profile); 772 773 EXPECT_TRUE(controller()->SectionIsActive(SECTION_CC)); 774 EXPECT_TRUE(controller()->SectionIsActive(SECTION_BILLING)); 775 EXPECT_FALSE(controller()->SectionIsActive(SECTION_CC_BILLING)); 776 EXPECT_TRUE(controller()->SectionIsActive(SECTION_SHIPPING)); 777 778 EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_CC)); 779 EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_BILLING)); 780 EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_SHIPPING)); 781 782 // Set up some Wallet state. 783 std::vector<std::string> usernames; 784 usernames.push_back("user@example.com"); 785 controller()->OnUserNameFetchSuccess(usernames); 786 controller()->OnDidFetchWalletCookieValue(std::string()); 787 controller()->OnDidGetWalletItems( 788 wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED)); 789 790 ui::MenuModel* account_chooser = controller()->MenuModelForAccountChooser(); 791 ASSERT_TRUE(account_chooser->IsItemCheckedAt(0)); 792 793 // Check that the view's in the state we expect before starting to simulate 794 // user input. 795 EXPECT_FALSE(controller()->SectionIsActive(SECTION_CC)); 796 EXPECT_FALSE(controller()->SectionIsActive(SECTION_BILLING)); 797 EXPECT_TRUE(controller()->SectionIsActive(SECTION_CC_BILLING)); 798 EXPECT_TRUE(controller()->SectionIsActive(SECTION_SHIPPING)); 799 800 EXPECT_TRUE(controller()->IsManuallyEditingSection(SECTION_CC_BILLING)); 801 802 // Create some valid inputted billing data. 803 const DetailInput& cc_number = 804 controller()->RequestedFieldsForSection(SECTION_CC_BILLING)[0]; 805 EXPECT_EQ(CREDIT_CARD_NUMBER, cc_number.type); 806 TestableAutofillDialogView* view = controller()->GetTestableView(); 807 view->SetTextContentsOfInput(cc_number, ASCIIToUTF16("4111111111111111")); 808 809 // Select "Add new shipping info..." from suggestions menu. 810 ui::MenuModel* shipping_model = 811 controller()->MenuModelForSection(SECTION_SHIPPING); 812 shipping_model->ActivatedAt(shipping_model->GetItemCount() - 2); 813 814 EXPECT_TRUE(controller()->IsManuallyEditingSection(SECTION_SHIPPING)); 815 816 // Create some invalid, manually inputted shipping data. 817 const DetailInput& shipping_zip = 818 controller()->RequestedFieldsForSection(SECTION_SHIPPING)[5]; 819 ASSERT_EQ(ADDRESS_HOME_ZIP, shipping_zip.type); 820 view->SetTextContentsOfInput(shipping_zip, ASCIIToUTF16("shipping zip")); 821 822 // Switch to using Autofill. 823 account_chooser->ActivatedAt(1); 824 825 // Check that appropriate sections are preserved and in manually editing mode 826 // (or disabled, in the case of the combined cc + billing section). 827 EXPECT_TRUE(controller()->SectionIsActive(SECTION_CC)); 828 EXPECT_TRUE(controller()->SectionIsActive(SECTION_BILLING)); 829 EXPECT_FALSE(controller()->SectionIsActive(SECTION_CC_BILLING)); 830 EXPECT_TRUE(controller()->SectionIsActive(SECTION_SHIPPING)); 831 832 EXPECT_TRUE(controller()->IsManuallyEditingSection(SECTION_CC)); 833 EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_BILLING)); 834 EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_SHIPPING)); 835 836 const DetailInput& new_cc_number = 837 controller()->RequestedFieldsForSection(SECTION_CC).front(); 838 EXPECT_EQ(cc_number.type, new_cc_number.type); 839 EXPECT_EQ(ASCIIToUTF16("4111111111111111"), 840 view->GetTextContentsOfInput(new_cc_number)); 841 842 EXPECT_NE(ASCIIToUTF16("shipping name"), 843 view->GetTextContentsOfInput(shipping_zip)); 844} 845#endif // defined(TOOLKIT_VIEWS) || defined(OS_MACOSX) 846 847IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, 848 GeneratedCardLastFourAfterVerifyCvv) { 849 std::vector<std::string> usernames(1, "user@example.com"); 850 controller()->OnUserNameFetchSuccess(usernames); 851 controller()->OnDidFetchWalletCookieValue(std::string()); 852 853 scoped_ptr<wallet::WalletItems> wallet_items = 854 wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED); 855 wallet_items->AddInstrument(wallet::GetTestMaskedInstrument()); 856 wallet_items->AddAddress(wallet::GetTestShippingAddress()); 857 858 base::string16 last_four = 859 wallet_items->instruments()[0]->TypeAndLastFourDigits(); 860 controller()->OnDidGetWalletItems(wallet_items.Pass()); 861 862 TestableAutofillDialogView* test_view = controller()->GetTestableView(); 863 EXPECT_FALSE(test_view->IsShowingOverlay()); 864 EXPECT_CALL(*controller(), LoadRiskFingerprintData()); 865 controller()->OnAccept(); 866 EXPECT_TRUE(test_view->IsShowingOverlay()); 867 868 EXPECT_CALL(*controller()->GetTestingWalletClient(), GetFullWallet(_)); 869 scoped_ptr<risk::Fingerprint> fingerprint(new risk::Fingerprint()); 870 fingerprint->mutable_machine_characteristics()->mutable_screen_size()-> 871 set_width(1024); 872 controller()->OnDidLoadRiskFingerprintData(fingerprint.Pass()); 873 874 controller()->OnDidGetFullWallet( 875 wallet::GetTestFullWalletWithRequiredActions( 876 std::vector<wallet::RequiredAction>(1, wallet::VERIFY_CVV))); 877 878 ASSERT_TRUE(controller()->IsSubmitPausedOn(wallet::VERIFY_CVV)); 879 880 std::string fake_cvc("123"); 881 test_view->SetTextContentsOfSuggestionInput(SECTION_CC_BILLING, 882 ASCIIToUTF16(fake_cvc)); 883 884 EXPECT_FALSE(test_view->IsShowingOverlay()); 885 EXPECT_CALL(*controller()->GetTestingWalletClient(), 886 AuthenticateInstrument(_, fake_cvc)); 887 controller()->OnAccept(); 888 EXPECT_TRUE(test_view->IsShowingOverlay()); 889 890 EXPECT_CALL(*controller()->GetTestingWalletClient(), GetFullWallet(_)); 891 controller()->OnDidAuthenticateInstrument(true); 892 controller()->OnDidGetFullWallet(wallet::GetTestFullWallet()); 893 controller()->ForceFinishSubmit(); 894 895 RunMessageLoop(); 896 897 EXPECT_EQ(1, test_generated_bubble_controller()->bubbles_shown()); 898 EXPECT_EQ(last_four, test_generated_bubble_controller()->backing_card_name()); 899} 900 901// See http://crbug.com/314627 902#if defined(OS_WIN) 903#define MAYBE_SignInNoCrash DISABLED_SignInNoCrash 904#else 905#define MAYBE_SignInNoCrash SignInNoCrash 906#endif 907 908// Simulates the user successfully signing in to the dialog for the first time. 909// The controller listens for nav entry commits and should not destroy the web 910// contents before its post load code runs (which would cause a crash). 911IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, MAYBE_SignInNoCrash) { 912 browser()->profile()->GetPrefs()->SetBoolean( 913 ::prefs::kAutofillDialogPayWithoutWallet, 914 true); 915 916 InitializeController(); 917 918 const AccountChooserModel& account_chooser_model = 919 controller()->AccountChooserModelForTesting(); 920 EXPECT_FALSE(account_chooser_model.WalletIsSelected()); 921 922 ui_test_utils::UrlLoadObserver observer( 923 controller()->SignInUrl(), 924 content::NotificationService::AllSources()); 925 926 controller()->SignInLinkClicked(); 927 std::vector<std::string> usernames(1, "user@example.com"); 928 controller()->OnUserNameFetchSuccess(usernames); 929 controller()->OnDidFetchWalletCookieValue(std::string()); 930 controller()->OnDidGetWalletItems( 931 wallet::GetTestWalletItemsWithRequiredAction(wallet::GAIA_AUTH)); 932 933 TestableAutofillDialogView* view = controller()->GetTestableView(); 934 EXPECT_TRUE(view->GetSignInWebContents()); 935 EXPECT_TRUE(controller()->ShouldShowSignInWebView()); 936 observer.Wait(); 937 938 // Wallet should now be selected and Chrome shouldn't have crashed. 939 EXPECT_TRUE(account_chooser_model.WalletIsSelected()); 940} 941 942// Verify that filling a form works correctly, including filling the CVC when 943// that is requested separately. 944IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, FillFormIncludesCVC) { 945 AutofillDialogControllerImpl* controller = 946 SetUpHtmlAndInvoke("<input autocomplete='cc-csc'>"); 947 948 AddCreditcardToProfile(controller->profile(), test::GetVerifiedCreditCard()); 949 AddAutofillProfileToProfile(controller->profile(), 950 test::GetVerifiedProfile()); 951 952 TestableAutofillDialogView* view = controller->GetTestableView(); 953 view->SetTextContentsOfSuggestionInput(SECTION_CC, ASCIIToUTF16("123")); 954 view->SubmitForTesting(); 955 ExpectDomMessage("success"); 956 EXPECT_EQ("123", GetValueForHTMLFieldOfType("cc-csc")); 957} 958 959} // namespace autofill 960