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