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