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.
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"
55 void MockCallback(const FormStructure*) {}
57 class MockAutofillMetrics : public AutofillMetrics {
60 : dialog_dismissal_action_(
61 static_cast<AutofillMetrics::DialogDismissalAction>(-1)) {}
62 virtual ~MockAutofillMetrics() {}
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;
72 AutofillMetrics::DialogDismissalAction dialog_dismissal_action() const {
73 return dialog_dismissal_action_;
76 MOCK_CONST_METHOD1(LogDialogDismissalState,
77 void(DialogDismissalState state));
80 AutofillMetrics::DialogDismissalAction dialog_dismissal_action_;
82 DISALLOW_COPY_AND_ASSIGN(MockAutofillMetrics);
85 class TestAutofillDialogController : public AutofillDialogControllerImpl {
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,
95 base::Bind(&MockCallback)),
96 metric_logger_(metric_logger),
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) {}
104 virtual ~TestAutofillDialogController() {}
106 virtual GURL SignInUrl() const OVERRIDE {
107 return GURL(content::kAboutBlankURL);
110 virtual void ViewClosed() OVERRIDE {
111 message_loop_runner_->Quit();
112 AutofillDialogControllerImpl::ViewClosed();
115 virtual string16 InputValidityMessage(
116 DialogSection section,
117 ServerFieldType type,
118 const string16& value) OVERRIDE {
119 if (!use_validation_)
121 return AutofillDialogControllerImpl::InputValidityMessage(
122 section, type, value);
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);
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 {
139 void ForceFinishSubmit() {
143 // Increase visibility for testing.
144 using AutofillDialogControllerImpl::view;
145 using AutofillDialogControllerImpl::input_showing_popup;
147 MOCK_METHOD0(LoadRiskFingerprintData, void());
149 virtual std::vector<DialogNotification> CurrentNotifications() OVERRIDE {
150 return notifications_;
153 void set_notifications(const std::vector<DialogNotification>& notifications) {
154 notifications_ = notifications;
157 TestPersonalDataManager* GetTestingManager() {
158 return &test_manager_;
161 using AutofillDialogControllerImpl::IsEditingExistingData;
162 using AutofillDialogControllerImpl::IsManuallyEditingSection;
163 using AutofillDialogControllerImpl::IsSubmitPausedOn;
164 using AutofillDialogControllerImpl::OnDidLoadRiskFingerprintData;
165 using AutofillDialogControllerImpl::AccountChooserModelForTesting;
167 void set_use_validation(bool use_validation) {
168 use_validation_ = use_validation;
171 base::WeakPtr<TestAutofillDialogController> AsWeakPtr() {
172 return weak_ptr_factory_.GetWeakPtr();
175 wallet::MockWalletClient* GetTestingWalletClient() {
176 return &mock_wallet_client_;
180 virtual PersonalDataManager* GetManager() OVERRIDE {
181 return &test_manager_;
184 virtual wallet::WalletClient* GetWalletClient() OVERRIDE {
185 return &mock_wallet_client_;
188 virtual bool IsSignInContinueUrl(const GURL& url) const OVERRIDE {
193 // To specify our own metric logger.
194 virtual const AutofillMetrics& GetMetricLogger() const OVERRIDE {
195 return metric_logger_;
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_;
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_;
208 // Allows generation of WeakPtrs, so controller liveness can be tested.
209 base::WeakPtrFactory<TestAutofillDialogController> weak_ptr_factory_;
211 DISALLOW_COPY_AND_ASSIGN(TestAutofillDialogController);
216 class AutofillDialogControllerTest : public InProcessBrowserTest {
218 AutofillDialogControllerTest() {}
219 virtual ~AutofillDialogControllerTest() {}
221 virtual void SetUpOnMainThread() OVERRIDE {
222 autofill::test::DisableSystemServices(browser()->profile());
223 InitializeController();
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);
235 void InitializeController() {
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;
244 field.autocomplete_attribute = "shipping tel";
245 form.fields.push_back(field);
247 test_generated_bubble_controller_ =
248 new testing::NiceMock<TestGeneratedCreditCardBubbleController>(
249 GetActiveWebContents());
250 ASSERT_TRUE(test_generated_bubble_controller_->IsInstalled());
252 message_loop_runner_ = new content::MessageLoopRunner;
253 controller_ = new TestAutofillDialogController(
254 GetActiveWebContents(),
257 message_loop_runner_);
261 content::WebContents* GetActiveWebContents() {
262 return browser()->tab_strip_model()->GetActiveWebContents();
265 const MockAutofillMetrics& metric_logger() { return metric_logger_; }
266 TestAutofillDialogController* controller() { return controller_; }
268 void RunMessageLoop() {
269 message_loop_runner_->Run();
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());
283 ui_test_utils::NavigateToURL(
284 browser(), GURL(std::string("data:text/html,") +
288 "<form>" + form_inner_html + "</form>"
290 "function send(msg) {"
291 "domAutomationController.setAutomationId(0);"
292 "domAutomationController.send(msg);"
294 "document.forms[0].onautocompleteerror = function(e) {"
295 "send('error: ' + e.reason);"
297 "document.forms[0].onautocomplete = function() {"
300 "window.onclick = function() {"
301 "document.forms[0].requestAutocomplete();"
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);"
317 content::WaitForLoadStop(contents);
319 dom_message_queue_.reset(new content::DOMMessageQueue);
321 // Triggers the onclick handler which invokes requestAutocomplete().
322 content::SimulateMouseClick(contents, 0, WebKit::WebMouseEvent::ButtonLeft);
323 ExpectDomMessage("clicked");
325 AutofillDialogControllerImpl* controller =
326 static_cast<AutofillDialogControllerImpl*>(
327 delegate->GetDialogControllerForTesting());
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) {
336 ASSERT_TRUE(dom_message_queue_->WaitForMessage(&message));
337 dom_message_queue_->ClearQueue();
338 EXPECT_EQ("\"" + expected + "\"", message);
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()->
347 std::string script = "getValueForFieldOfType('" + autocomplete_type + "');";
349 EXPECT_TRUE(content::ExecuteScriptAndExtractString(render_view_host, script,
354 void AddCreditcardToProfile(Profile* profile, const CreditCard& card) {
355 PersonalDataManagerFactory::GetForProfile(profile)->AddCreditCard(card);
359 void AddAutofillProfileToProfile(Profile* profile,
360 const AutofillProfile& autofill_profile) {
361 PersonalDataManagerFactory::GetForProfile(profile)->AddProfile(
366 TestGeneratedCreditCardBubbleController* test_generated_bubble_controller() {
367 return test_generated_bubble_controller_;
371 void WaitForWebDB() {
372 content::RunAllPendingInMessageLoop(content::BrowserThread::DB);
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_;
380 // Weak; owned by the active web contents.
381 TestGeneratedCreditCardBubbleController* test_generated_bubble_controller_;
383 DISALLOW_COPY_AND_ASSIGN(AutofillDialogControllerTest);
386 #if defined(TOOLKIT_VIEWS) || defined(OS_MACOSX)
387 // Submit the form data.
388 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, Submit) {
389 controller()->GetTestableView()->SubmitForTesting();
393 EXPECT_EQ(AutofillMetrics::DIALOG_ACCEPTED,
394 metric_logger().dialog_dismissal_action());
397 // Cancel out of the dialog.
398 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, Cancel) {
399 controller()->GetTestableView()->CancelForTesting();
403 EXPECT_EQ(AutofillMetrics::DIALOG_CANCELED,
404 metric_logger().dialog_dismissal_action());
407 // Take some other action that dismisses the dialog.
408 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, Hide) {
409 controller()->Hide();
413 EXPECT_EQ(AutofillMetrics::DIALOG_CANCELED,
414 metric_logger().dialog_dismissal_action());
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.
420 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, DeferredDestruction) {
421 base::WeakPtr<TestAutofillDialogController> weak_ptr =
422 controller()->AsWeakPtr();
423 EXPECT_TRUE(weak_ptr.get());
425 controller()->Hide();
426 EXPECT_TRUE(weak_ptr.get());
429 EXPECT_FALSE(weak_ptr.get());
432 // Ensure that the expected metric is logged when the dialog is closed during
434 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, CloseDuringSignin) {
435 controller()->SignInLinkClicked();
437 EXPECT_CALL(metric_logger(),
438 LogDialogDismissalState(
439 AutofillMetrics::DIALOG_CANCELED_DURING_SIGNIN));
440 controller()->GetTestableView()->CancelForTesting();
444 EXPECT_EQ(AutofillMetrics::DIALOG_CANCELED,
445 metric_logger().dialog_dismissal_action());
448 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, FillInputFromAutofill) {
449 AutofillProfile full_profile(test::GetFullProfile());
450 controller()->GetTestingManager()->AddTestingProfile(&full_profile);
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);
461 ASSERT_EQ(&triggering_input, controller()->input_showing_popup());
462 controller()->DidAcceptSuggestion(string16(), 0);
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]));
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)) :
481 expectations.push_back(expectation);
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);
490 for (size_t i = 0; i < inputs.size(); ++i) {
491 EXPECT_EQ(expectations[i], view->GetTextContentsOfInput(inputs[i]));
495 // For now, no matter what, the country must always be US. See
496 // http://crbug.com/247518
497 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
498 FillInputFromForeignProfile) {
499 AutofillProfile full_profile(test::GetFullProfile());
500 full_profile.SetInfo(AutofillType(ADDRESS_HOME_COUNTRY),
501 ASCIIToUTF16("France"), "en-US");
502 controller()->GetTestingManager()->AddTestingProfile(&full_profile);
504 const DetailInputs& inputs =
505 controller()->RequestedFieldsForSection(SECTION_SHIPPING);
506 const DetailInput& triggering_input = inputs[0];
507 string16 value = full_profile.GetRawInfo(triggering_input.type);
508 TestableAutofillDialogView* view = controller()->GetTestableView();
509 view->SetTextContentsOfInput(triggering_input,
510 value.substr(0, value.size() / 2));
511 view->ActivateInput(triggering_input);
513 ASSERT_EQ(&triggering_input, controller()->input_showing_popup());
514 controller()->DidAcceptSuggestion(string16(), 0);
516 // All inputs should be filled.
517 AutofillProfileWrapper wrapper(&full_profile);
518 for (size_t i = 0; i < inputs.size(); ++i) {
519 string16 expectation =
520 AutofillType(inputs[i].type).GetStorableType() == ADDRESS_HOME_COUNTRY ?
521 ASCIIToUTF16("United States") :
522 wrapper.GetInfo(AutofillType(inputs[i].type));
523 EXPECT_EQ(expectation, view->GetTextContentsOfInput(inputs[i]));
526 // Now simulate some user edits and try again.
527 std::vector<string16> expectations;
528 for (size_t i = 0; i < inputs.size(); ++i) {
529 string16 users_input = i % 2 == 0 ? string16() : ASCIIToUTF16("dummy");
530 view->SetTextContentsOfInput(inputs[i], users_input);
531 // Empty inputs should be filled, others should be left alone.
532 string16 expectation =
533 &inputs[i] == &triggering_input || users_input.empty() ?
534 wrapper.GetInfo(AutofillType(inputs[i].type)) :
536 if (AutofillType(inputs[i].type).GetStorableType() == ADDRESS_HOME_COUNTRY)
537 expectation = ASCIIToUTF16("United States");
539 expectations.push_back(expectation);
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);
548 for (size_t i = 0; i < inputs.size(); ++i) {
549 EXPECT_EQ(expectations[i], view->GetTextContentsOfInput(inputs[i]));
553 // This test makes sure that picking a profile variant in the Autofill
554 // popup works as expected.
555 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
556 FillInputFromAutofillVariant) {
557 AutofillProfile full_profile(test::GetFullProfile());
559 // Set up some variant data.
560 std::vector<string16> names;
561 names.push_back(ASCIIToUTF16("John Doe"));
562 names.push_back(ASCIIToUTF16("Jane Doe"));
563 full_profile.SetRawMultiInfo(NAME_FULL, names);
564 std::vector<string16> emails;
565 emails.push_back(ASCIIToUTF16("user@example.com"));
566 emails.push_back(ASCIIToUTF16("admin@example.com"));
567 full_profile.SetRawMultiInfo(EMAIL_ADDRESS, emails);
568 controller()->GetTestingManager()->AddTestingProfile(&full_profile);
570 const DetailInputs& inputs =
571 controller()->RequestedFieldsForSection(SECTION_BILLING);
572 const DetailInput& triggering_input = inputs[0];
573 EXPECT_EQ(NAME_BILLING_FULL, triggering_input.type);
574 TestableAutofillDialogView* view = controller()->GetTestableView();
575 view->ActivateInput(triggering_input);
577 ASSERT_EQ(&triggering_input, controller()->input_showing_popup());
579 // Choose the variant suggestion.
580 controller()->DidAcceptSuggestion(string16(), 1);
582 // All inputs should be filled.
583 AutofillProfileWrapper wrapper(
584 &full_profile, AutofillType(NAME_BILLING_FULL), 1);
585 for (size_t i = 0; i < inputs.size(); ++i) {
586 EXPECT_EQ(wrapper.GetInfo(AutofillType(inputs[i].type)),
587 view->GetTextContentsOfInput(inputs[i]));
590 // Make sure the wrapper applies the variant index to the right group.
591 EXPECT_EQ(names[1], wrapper.GetInfo(AutofillType(NAME_BILLING_FULL)));
592 // Make sure the wrapper doesn't apply the variant index to the wrong group.
593 EXPECT_EQ(emails[0], wrapper.GetInfo(AutofillType(EMAIL_ADDRESS)));
596 // Tests that changing the value of a CC expiration date combobox works as
597 // expected when Autofill is used to fill text inputs.
599 // Flaky on Win7, WinXP, and Win Aura. http://crbug.com/270314.
601 #define MAYBE_FillComboboxFromAutofill DISABLED_FillComboboxFromAutofill
603 #define MAYBE_FillComboboxFromAutofill FillComboboxFromAutofill
605 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
606 MAYBE_FillComboboxFromAutofill) {
608 test::SetCreditCardInfo(&card1, "JJ Smith", "4111111111111111", "12", "2018");
609 controller()->GetTestingManager()->AddTestingCreditCard(&card1);
611 test::SetCreditCardInfo(&card2, "B Bird", "3111111111111111", "11", "2017");
612 controller()->GetTestingManager()->AddTestingCreditCard(&card2);
613 AutofillProfile full_profile(test::GetFullProfile());
614 controller()->GetTestingManager()->AddTestingProfile(&full_profile);
616 const DetailInputs& inputs =
617 controller()->RequestedFieldsForSection(SECTION_CC);
618 const DetailInput& triggering_input = inputs[0];
619 string16 value = card1.GetRawInfo(triggering_input.type);
620 TestableAutofillDialogView* view = controller()->GetTestableView();
621 view->SetTextContentsOfInput(triggering_input,
622 value.substr(0, value.size() / 2));
623 view->ActivateInput(triggering_input);
625 ASSERT_EQ(&triggering_input, controller()->input_showing_popup());
626 controller()->DidAcceptSuggestion(string16(), 0);
628 // All inputs should be filled.
629 AutofillCreditCardWrapper wrapper1(&card1);
630 for (size_t i = 0; i < inputs.size(); ++i) {
631 EXPECT_EQ(wrapper1.GetInfo(AutofillType(inputs[i].type)),
632 view->GetTextContentsOfInput(inputs[i]));
635 // Try again with different data. Only expiration date and the triggering
636 // input should be overwritten.
637 value = card2.GetRawInfo(triggering_input.type);
638 view->SetTextContentsOfInput(triggering_input,
639 value.substr(0, value.size() / 2));
640 view->ActivateInput(triggering_input);
641 ASSERT_EQ(&triggering_input, controller()->input_showing_popup());
642 controller()->DidAcceptSuggestion(string16(), 0);
644 AutofillCreditCardWrapper wrapper2(&card2);
645 for (size_t i = 0; i < inputs.size(); ++i) {
646 const DetailInput& input = inputs[i];
647 if (&input == &triggering_input ||
648 input.type == CREDIT_CARD_EXP_MONTH ||
649 input.type == CREDIT_CARD_EXP_4_DIGIT_YEAR) {
650 EXPECT_EQ(wrapper2.GetInfo(AutofillType(input.type)),
651 view->GetTextContentsOfInput(input));
652 } else if (input.type == CREDIT_CARD_VERIFICATION_CODE) {
653 EXPECT_TRUE(view->GetTextContentsOfInput(input).empty());
655 EXPECT_EQ(wrapper1.GetInfo(AutofillType(input.type)),
656 view->GetTextContentsOfInput(input));
660 // Now fill from a profile. It should not overwrite any CC info.
661 const DetailInputs& billing_inputs =
662 controller()->RequestedFieldsForSection(SECTION_BILLING);
663 const DetailInput& billing_triggering_input = billing_inputs[0];
664 value = full_profile.GetRawInfo(triggering_input.type);
665 view->SetTextContentsOfInput(billing_triggering_input,
666 value.substr(0, value.size() / 2));
667 view->ActivateInput(billing_triggering_input);
669 ASSERT_EQ(&billing_triggering_input, controller()->input_showing_popup());
670 controller()->DidAcceptSuggestion(string16(), 0);
672 for (size_t i = 0; i < inputs.size(); ++i) {
673 const DetailInput& input = inputs[i];
674 if (&input == &triggering_input ||
675 input.type == CREDIT_CARD_EXP_MONTH ||
676 input.type == CREDIT_CARD_EXP_4_DIGIT_YEAR) {
677 EXPECT_EQ(wrapper2.GetInfo(AutofillType(input.type)),
678 view->GetTextContentsOfInput(input));
679 } else if (input.type == CREDIT_CARD_VERIFICATION_CODE) {
680 EXPECT_TRUE(view->GetTextContentsOfInput(input).empty());
682 EXPECT_EQ(wrapper1.GetInfo(AutofillType(input.type)),
683 view->GetTextContentsOfInput(input));
688 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, ShouldShowErrorBubble) {
689 EXPECT_TRUE(controller()->ShouldShowErrorBubble());
691 CreditCard card(test::GetCreditCard());
692 ASSERT_FALSE(card.IsVerified());
693 controller()->GetTestingManager()->AddTestingCreditCard(&card);
695 const DetailInputs& cc_inputs =
696 controller()->RequestedFieldsForSection(SECTION_CC);
697 const DetailInput& cc_number_input = cc_inputs[0];
698 ASSERT_EQ(CREDIT_CARD_NUMBER, cc_number_input.type);
700 TestableAutofillDialogView* view = controller()->GetTestableView();
701 view->SetTextContentsOfInput(
703 card.GetRawInfo(CREDIT_CARD_NUMBER).substr(0, 1));
705 view->ActivateInput(cc_number_input);
706 EXPECT_FALSE(controller()->ShouldShowErrorBubble());
708 controller()->FocusMoved();
709 EXPECT_TRUE(controller()->ShouldShowErrorBubble());
712 // Ensure that expired cards trigger invalid suggestions.
713 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, ExpiredCard) {
714 CreditCard verified_card(test::GetCreditCard());
715 verified_card.set_origin("Chrome settings");
716 ASSERT_TRUE(verified_card.IsVerified());
717 controller()->GetTestingManager()->AddTestingCreditCard(&verified_card);
719 CreditCard expired_card(test::GetCreditCard());
720 expired_card.set_origin("Chrome settings");
721 expired_card.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2007"));
722 ASSERT_TRUE(expired_card.IsVerified());
724 autofill::IsValidCreditCardExpirationDate(
725 expired_card.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR),
726 expired_card.GetRawInfo(CREDIT_CARD_EXP_MONTH),
728 controller()->GetTestingManager()->AddTestingCreditCard(&expired_card);
730 ui::MenuModel* model = controller()->MenuModelForSection(SECTION_CC);
731 ASSERT_EQ(4, model->GetItemCount());
733 ASSERT_TRUE(model->IsItemCheckedAt(0));
734 EXPECT_FALSE(controller()->IsEditingExistingData(SECTION_CC));
736 model->ActivatedAt(1);
737 ASSERT_TRUE(model->IsItemCheckedAt(1));
738 EXPECT_TRUE(controller()->IsEditingExistingData(SECTION_CC));
741 // Notifications with long message text should not make the dialog bigger.
742 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, LongNotifications) {
743 const gfx::Size no_notification_size =
744 controller()->GetTestableView()->GetSize();
745 ASSERT_GT(no_notification_size.width(), 0);
747 std::vector<DialogNotification> notifications;
748 notifications.push_back(
749 DialogNotification(DialogNotification::DEVELOPER_WARNING, ASCIIToUTF16(
750 "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do "
751 "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim "
752 "ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut "
753 "aliquip ex ea commodo consequat. Duis aute irure dolor in "
754 "reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla "
755 "pariatur. Excepteur sint occaecat cupidatat non proident, sunt in "
756 "culpa qui officia deserunt mollit anim id est laborum.")));
757 controller()->set_notifications(notifications);
758 controller()->view()->UpdateNotificationArea();
760 EXPECT_EQ(no_notification_size.width(),
761 controller()->GetTestableView()->GetSize().width());
764 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AutocompleteEvent) {
765 AutofillDialogControllerImpl* controller =
766 SetUpHtmlAndInvoke("<input autocomplete='cc-name'>");
768 AddCreditcardToProfile(controller->profile(), test::GetVerifiedCreditCard());
769 AddAutofillProfileToProfile(controller->profile(),
770 test::GetVerifiedProfile());
772 TestableAutofillDialogView* view = controller->GetTestableView();
773 view->SetTextContentsOfSuggestionInput(SECTION_CC, ASCIIToUTF16("123"));
774 view->SubmitForTesting();
775 ExpectDomMessage("success");
778 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
779 AutocompleteErrorEventReasonInvalid) {
780 AutofillDialogControllerImpl* controller =
781 SetUpHtmlAndInvoke("<input autocomplete='cc-name' pattern='.*zebra.*'>");
783 const CreditCard& credit_card = test::GetVerifiedCreditCard();
785 credit_card.GetRawInfo(CREDIT_CARD_NAME).find(ASCIIToUTF16("zebra")) ==
786 base::string16::npos);
787 AddCreditcardToProfile(controller->profile(), credit_card);
788 AddAutofillProfileToProfile(controller->profile(),
789 test::GetVerifiedProfile());
791 TestableAutofillDialogView* view = controller->GetTestableView();
792 view->SetTextContentsOfSuggestionInput(SECTION_CC, ASCIIToUTF16("123"));
793 view->SubmitForTesting();
794 ExpectDomMessage("error: invalid");
797 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
798 AutocompleteErrorEventReasonCancel) {
799 SetUpHtmlAndInvoke("<input autocomplete='cc-name'>")->GetTestableView()->
801 ExpectDomMessage("error: cancel");
804 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, NoCvcSegfault) {
805 controller()->set_use_validation(true);
807 CreditCard credit_card(test::GetVerifiedCreditCard());
808 controller()->GetTestingManager()->AddTestingCreditCard(&credit_card);
809 EXPECT_FALSE(controller()->IsEditingExistingData(SECTION_CC));
811 ASSERT_NO_FATAL_FAILURE(
812 controller()->GetTestableView()->SubmitForTesting());
815 // Flaky on Win7, WinXP, and Win Aura. http://crbug.com/270314.
817 #define MAYBE_PreservedSections DISABLED_PreservedSections
819 #define MAYBE_PreservedSections PreservedSections
821 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, MAYBE_PreservedSections) {
822 controller()->set_use_validation(true);
824 // Set up some Autofill state.
825 CreditCard credit_card(test::GetVerifiedCreditCard());
826 controller()->GetTestingManager()->AddTestingCreditCard(&credit_card);
828 AutofillProfile profile(test::GetVerifiedProfile());
829 controller()->GetTestingManager()->AddTestingProfile(&profile);
831 EXPECT_TRUE(controller()->SectionIsActive(SECTION_CC));
832 EXPECT_TRUE(controller()->SectionIsActive(SECTION_BILLING));
833 EXPECT_FALSE(controller()->SectionIsActive(SECTION_CC_BILLING));
834 EXPECT_TRUE(controller()->SectionIsActive(SECTION_SHIPPING));
836 EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_CC));
837 EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_BILLING));
838 EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_SHIPPING));
840 // Set up some Wallet state.
841 std::vector<std::string> usernames;
842 usernames.push_back("user@example.com");
843 controller()->OnUserNameFetchSuccess(usernames);
844 controller()->OnDidFetchWalletCookieValue(std::string());
845 controller()->OnDidGetWalletItems(
846 wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED));
848 ui::MenuModel* account_chooser = controller()->MenuModelForAccountChooser();
849 ASSERT_TRUE(account_chooser->IsItemCheckedAt(0));
851 // Check that the view's in the state we expect before starting to simulate
853 EXPECT_FALSE(controller()->SectionIsActive(SECTION_CC));
854 EXPECT_FALSE(controller()->SectionIsActive(SECTION_BILLING));
855 EXPECT_TRUE(controller()->SectionIsActive(SECTION_CC_BILLING));
856 EXPECT_TRUE(controller()->SectionIsActive(SECTION_SHIPPING));
858 EXPECT_TRUE(controller()->IsManuallyEditingSection(SECTION_CC_BILLING));
860 // Create some valid inputted billing data.
861 const DetailInput& cc_number =
862 controller()->RequestedFieldsForSection(SECTION_CC_BILLING)[0];
863 EXPECT_EQ(CREDIT_CARD_NUMBER, cc_number.type);
864 TestableAutofillDialogView* view = controller()->GetTestableView();
865 view->SetTextContentsOfInput(cc_number, ASCIIToUTF16("4111111111111111"));
867 // Select "Add new shipping info..." from suggestions menu.
868 ui::MenuModel* shipping_model =
869 controller()->MenuModelForSection(SECTION_SHIPPING);
870 shipping_model->ActivatedAt(shipping_model->GetItemCount() - 2);
872 EXPECT_TRUE(controller()->IsManuallyEditingSection(SECTION_SHIPPING));
874 // Create some invalid, manually inputted shipping data.
875 const DetailInput& shipping_zip =
876 controller()->RequestedFieldsForSection(SECTION_SHIPPING)[5];
877 ASSERT_EQ(ADDRESS_HOME_ZIP, shipping_zip.type);
878 view->SetTextContentsOfInput(shipping_zip, ASCIIToUTF16("shipping zip"));
880 // Switch to using Autofill.
881 account_chooser->ActivatedAt(1);
883 // Check that appropriate sections are preserved and in manually editing mode
884 // (or disabled, in the case of the combined cc + billing section).
885 EXPECT_TRUE(controller()->SectionIsActive(SECTION_CC));
886 EXPECT_TRUE(controller()->SectionIsActive(SECTION_BILLING));
887 EXPECT_FALSE(controller()->SectionIsActive(SECTION_CC_BILLING));
888 EXPECT_TRUE(controller()->SectionIsActive(SECTION_SHIPPING));
890 EXPECT_TRUE(controller()->IsManuallyEditingSection(SECTION_CC));
891 EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_BILLING));
892 EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_SHIPPING));
894 const DetailInput& new_cc_number =
895 controller()->RequestedFieldsForSection(SECTION_CC).front();
896 EXPECT_EQ(cc_number.type, new_cc_number.type);
897 EXPECT_EQ(ASCIIToUTF16("4111111111111111"),
898 view->GetTextContentsOfInput(new_cc_number));
900 EXPECT_NE(ASCIIToUTF16("shipping name"),
901 view->GetTextContentsOfInput(shipping_zip));
903 #endif // defined(TOOLKIT_VIEWS) || defined(OS_MACOSX)
905 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
906 GeneratedCardLastFourAfterVerifyCvv) {
907 std::vector<std::string> usernames(1, "user@example.com");
908 controller()->OnUserNameFetchSuccess(usernames);
909 controller()->OnDidFetchWalletCookieValue(std::string());
911 scoped_ptr<wallet::WalletItems> wallet_items =
912 wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
913 wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
914 wallet_items->AddAddress(wallet::GetTestShippingAddress());
916 base::string16 last_four =
917 wallet_items->instruments()[0]->TypeAndLastFourDigits();
918 controller()->OnDidGetWalletItems(wallet_items.Pass());
920 TestableAutofillDialogView* test_view = controller()->GetTestableView();
921 EXPECT_FALSE(test_view->IsShowingOverlay());
922 EXPECT_CALL(*controller(), LoadRiskFingerprintData());
923 controller()->OnAccept();
924 EXPECT_TRUE(test_view->IsShowingOverlay());
926 EXPECT_CALL(*controller()->GetTestingWalletClient(), GetFullWallet(_));
927 scoped_ptr<risk::Fingerprint> fingerprint(new risk::Fingerprint());
928 fingerprint->mutable_machine_characteristics()->mutable_screen_size()->
930 controller()->OnDidLoadRiskFingerprintData(fingerprint.Pass());
932 controller()->OnDidGetFullWallet(
933 wallet::GetTestFullWalletWithRequiredActions(
934 std::vector<wallet::RequiredAction>(1, wallet::VERIFY_CVV)));
936 ASSERT_TRUE(controller()->IsSubmitPausedOn(wallet::VERIFY_CVV));
938 std::string fake_cvc("123");
939 test_view->SetTextContentsOfSuggestionInput(SECTION_CC_BILLING,
940 ASCIIToUTF16(fake_cvc));
942 EXPECT_FALSE(test_view->IsShowingOverlay());
943 EXPECT_CALL(*controller()->GetTestingWalletClient(),
944 AuthenticateInstrument(_, fake_cvc));
945 controller()->OnAccept();
946 EXPECT_TRUE(test_view->IsShowingOverlay());
948 EXPECT_CALL(*controller()->GetTestingWalletClient(), GetFullWallet(_));
949 controller()->OnDidAuthenticateInstrument(true);
950 controller()->OnDidGetFullWallet(wallet::GetTestFullWallet());
951 controller()->ForceFinishSubmit();
955 EXPECT_EQ(1, test_generated_bubble_controller()->bubbles_shown());
956 EXPECT_EQ(last_four, test_generated_bubble_controller()->backing_card_name());
959 // See http://crbug.com/314627
961 #define MAYBE_SignInNoCrash DISABLED_SignInNoCrash
963 #define MAYBE_SignInNoCrash SignInNoCrash
966 // Simulates the user successfully signing in to the dialog for the first time.
967 // The controller listens for nav entry commits and should not destroy the web
968 // contents before its post load code runs (which would cause a crash).
969 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, MAYBE_SignInNoCrash) {
970 browser()->profile()->GetPrefs()->SetBoolean(
971 ::prefs::kAutofillDialogPayWithoutWallet,
974 InitializeController();
976 const AccountChooserModel& account_chooser_model =
977 controller()->AccountChooserModelForTesting();
978 EXPECT_FALSE(account_chooser_model.WalletIsSelected());
980 ui_test_utils::UrlLoadObserver observer(
981 controller()->SignInUrl(),
982 content::NotificationService::AllSources());
984 controller()->SignInLinkClicked();
985 std::vector<std::string> usernames(1, "user@example.com");
986 controller()->OnUserNameFetchSuccess(usernames);
987 controller()->OnDidFetchWalletCookieValue(std::string());
988 controller()->OnDidGetWalletItems(
989 wallet::GetTestWalletItemsWithRequiredAction(wallet::GAIA_AUTH));
991 TestableAutofillDialogView* view = controller()->GetTestableView();
992 EXPECT_TRUE(view->GetSignInWebContents());
993 EXPECT_TRUE(controller()->ShouldShowSignInWebView());
996 // Wallet should now be selected and Chrome shouldn't have crashed.
997 EXPECT_TRUE(account_chooser_model.WalletIsSelected());
1000 // Verify that filling a form works correctly, including filling the CVC when
1001 // that is requested separately.
1002 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, FillFormIncludesCVC) {
1003 AutofillDialogControllerImpl* controller =
1004 SetUpHtmlAndInvoke("<input autocomplete='cc-csc'>");
1006 AddCreditcardToProfile(controller->profile(), test::GetVerifiedCreditCard());
1007 AddAutofillProfileToProfile(controller->profile(),
1008 test::GetVerifiedProfile());
1010 TestableAutofillDialogView* view = controller->GetTestableView();
1011 view->SetTextContentsOfSuggestionInput(SECTION_CC, ASCIIToUTF16("123"));
1012 view->SubmitForTesting();
1013 ExpectDomMessage("success");
1014 EXPECT_EQ("123", GetValueForHTMLFieldOfType("cc-csc"));
1017 } // namespace autofill