- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / autofill / autofill_dialog_controller_browsertest.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/bind.h"
6 #include "base/command_line.h"
7 #include "base/memory/ref_counted.h"
8 #include "base/memory/weak_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/time/time.h"
13 #include "chrome/browser/autofill/personal_data_manager_factory.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/ui/autofill/account_chooser_model.h"
16 #include "chrome/browser/ui/autofill/autofill_dialog_controller_impl.h"
17 #include "chrome/browser/ui/autofill/autofill_dialog_view.h"
18 #include "chrome/browser/ui/autofill/data_model_wrapper.h"
19 #include "chrome/browser/ui/autofill/tab_autofill_manager_delegate.h"
20 #include "chrome/browser/ui/autofill/test_generated_credit_card_bubble_controller.h"
21 #include "chrome/browser/ui/autofill/testable_autofill_dialog_view.h"
22 #include "chrome/browser/ui/browser.h"
23 #include "chrome/browser/ui/tabs/tab_strip_model.h"
24 #include "chrome/common/pref_names.h"
25 #include "chrome/test/base/in_process_browser_test.h"
26 #include "chrome/test/base/ui_test_utils.h"
27 #include "components/autofill/content/browser/risk/proto/fingerprint.pb.h"
28 #include "components/autofill/content/browser/wallet/mock_wallet_client.h"
29 #include "components/autofill/content/browser/wallet/wallet_test_util.h"
30 #include "components/autofill/core/browser/autofill_common_test.h"
31 #include "components/autofill/core/browser/autofill_metrics.h"
32 #include "components/autofill/core/browser/test_personal_data_manager.h"
33 #include "components/autofill/core/browser/validation.h"
34 #include "components/autofill/core/common/autofill_switches.h"
35 #include "components/autofill/core/common/form_data.h"
36 #include "components/autofill/core/common/form_field_data.h"
37 #include "content/public/browser/browser_thread.h"
38 #include "content/public/browser/notification_service.h"
39 #include "content/public/browser/web_contents.h"
40 #include "content/public/browser/web_contents_delegate.h"
41 #include "content/public/common/url_constants.h"
42 #include "content/public/test/browser_test_utils.h"
43 #include "content/public/test/test_utils.h"
44 #include "testing/gmock/include/gmock/gmock.h"
45 #include "testing/gtest/include/gtest/gtest.h"
46 #include "third_party/WebKit/public/web/WebInputEvent.h"
47 #include "url/gurl.h"
48
49 namespace autofill {
50
51 namespace {
52
53 using testing::_;
54
55 void MockCallback(const FormStructure*) {}
56
57 class MockAutofillMetrics : public AutofillMetrics {
58  public:
59   MockAutofillMetrics()
60       : dialog_dismissal_action_(
61             static_cast<AutofillMetrics::DialogDismissalAction>(-1)) {}
62   virtual ~MockAutofillMetrics() {}
63
64   virtual void LogDialogUiDuration(
65       const base::TimeDelta& duration,
66       DialogDismissalAction dismissal_action) const OVERRIDE {
67     // Ignore constness for testing.
68     MockAutofillMetrics* mutable_this = const_cast<MockAutofillMetrics*>(this);
69     mutable_this->dialog_dismissal_action_ = dismissal_action;
70   }
71
72   AutofillMetrics::DialogDismissalAction dialog_dismissal_action() const {
73     return dialog_dismissal_action_;
74   }
75
76   MOCK_CONST_METHOD1(LogDialogDismissalState,
77                      void(DialogDismissalState state));
78
79  private:
80   AutofillMetrics::DialogDismissalAction dialog_dismissal_action_;
81
82   DISALLOW_COPY_AND_ASSIGN(MockAutofillMetrics);
83 };
84
85 class TestAutofillDialogController : public AutofillDialogControllerImpl {
86  public:
87   TestAutofillDialogController(
88       content::WebContents* contents,
89       const FormData& form_data,
90       const AutofillMetrics& metric_logger,
91       scoped_refptr<content::MessageLoopRunner> runner)
92       : AutofillDialogControllerImpl(contents,
93                                      form_data,
94                                      form_data.origin,
95                                      base::Bind(&MockCallback)),
96         metric_logger_(metric_logger),
97         mock_wallet_client_(
98             Profile::FromBrowserContext(contents->GetBrowserContext())->
99                 GetRequestContext(), this, form_data.origin),
100         message_loop_runner_(runner),
101         use_validation_(false),
102         weak_ptr_factory_(this) {}
103
104   virtual ~TestAutofillDialogController() {}
105
106   virtual GURL SignInUrl() const OVERRIDE {
107     return GURL(content::kAboutBlankURL);
108   }
109
110   virtual void ViewClosed() OVERRIDE {
111     message_loop_runner_->Quit();
112     AutofillDialogControllerImpl::ViewClosed();
113   }
114
115   virtual string16 InputValidityMessage(
116       DialogSection section,
117       ServerFieldType type,
118       const string16& value) OVERRIDE {
119     if (!use_validation_)
120       return string16();
121     return AutofillDialogControllerImpl::InputValidityMessage(
122         section, type, value);
123   }
124
125   virtual ValidityMessages InputsAreValid(
126       DialogSection section,
127       const DetailOutputMap& inputs) OVERRIDE {
128     if (!use_validation_)
129       return ValidityMessages();
130     return AutofillDialogControllerImpl::InputsAreValid(section, inputs);
131   }
132
133   // Saving to Chrome is tested in AutofillDialogControllerImpl unit tests.
134   // TODO(estade): test that the view defaults to saving to Chrome.
135   virtual bool ShouldOfferToSaveInChrome() const OVERRIDE {
136     return false;
137   }
138
139   void ForceFinishSubmit() {
140     DoFinishSubmit();
141   }
142
143   // Increase visibility for testing.
144   using AutofillDialogControllerImpl::view;
145   using AutofillDialogControllerImpl::input_showing_popup;
146
147   MOCK_METHOD0(LoadRiskFingerprintData, void());
148
149   virtual std::vector<DialogNotification> CurrentNotifications() OVERRIDE {
150     return notifications_;
151   }
152
153   void set_notifications(const std::vector<DialogNotification>& notifications) {
154     notifications_ = notifications;
155   }
156
157   TestPersonalDataManager* GetTestingManager() {
158     return &test_manager_;
159   }
160
161   using AutofillDialogControllerImpl::IsEditingExistingData;
162   using AutofillDialogControllerImpl::IsManuallyEditingSection;
163   using AutofillDialogControllerImpl::IsSubmitPausedOn;
164   using AutofillDialogControllerImpl::OnDidLoadRiskFingerprintData;
165   using AutofillDialogControllerImpl::AccountChooserModelForTesting;
166
167   void set_use_validation(bool use_validation) {
168     use_validation_ = use_validation;
169   }
170
171   base::WeakPtr<TestAutofillDialogController> AsWeakPtr() {
172     return weak_ptr_factory_.GetWeakPtr();
173   }
174
175   wallet::MockWalletClient* GetTestingWalletClient() {
176     return &mock_wallet_client_;
177   }
178
179  protected:
180   virtual PersonalDataManager* GetManager() OVERRIDE {
181     return &test_manager_;
182   }
183
184   virtual wallet::WalletClient* GetWalletClient() OVERRIDE {
185     return &mock_wallet_client_;
186   }
187
188   virtual bool IsSignInContinueUrl(const GURL& url) const OVERRIDE {
189     return true;
190   }
191
192  private:
193   // To specify our own metric logger.
194   virtual const AutofillMetrics& GetMetricLogger() const OVERRIDE {
195     return metric_logger_;
196   }
197
198   const AutofillMetrics& metric_logger_;
199   TestPersonalDataManager test_manager_;
200   testing::NiceMock<wallet::MockWalletClient> mock_wallet_client_;
201   scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
202   bool use_validation_;
203
204   // A list of notifications to show in the notification area of the dialog.
205   // This is used to control what |CurrentNotifications()| returns for testing.
206   std::vector<DialogNotification> notifications_;
207
208   // Allows generation of WeakPtrs, so controller liveness can be tested.
209   base::WeakPtrFactory<TestAutofillDialogController> weak_ptr_factory_;
210
211   DISALLOW_COPY_AND_ASSIGN(TestAutofillDialogController);
212 };
213
214 }  // namespace
215
216 class AutofillDialogControllerTest : public InProcessBrowserTest {
217  public:
218   AutofillDialogControllerTest() {}
219   virtual ~AutofillDialogControllerTest() {}
220
221   virtual void SetUpOnMainThread() OVERRIDE {
222     autofill::test::DisableSystemServices(browser()->profile());
223     InitializeController();
224   }
225
226   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
227 #if defined(OS_MACOSX)
228     // OSX support for requestAutocomplete is still hidden behind a switch.
229     // Pending resolution of http://crbug.com/157274
230     CommandLine::ForCurrentProcess()->AppendSwitch(
231         switches::kEnableInteractiveAutocomplete);
232 #endif
233   }
234
235   void InitializeController() {
236     FormData form;
237     form.name = ASCIIToUTF16("TestForm");
238     form.method = ASCIIToUTF16("POST");
239     form.origin = GURL("http://example.com/form.html");
240     form.action = GURL("http://example.com/submit.html");
241     form.user_submitted = true;
242
243     FormFieldData field;
244     field.autocomplete_attribute = "shipping tel";
245     form.fields.push_back(field);
246
247     test_generated_bubble_controller_ =
248         new testing::NiceMock<TestGeneratedCreditCardBubbleController>(
249             GetActiveWebContents());
250     ASSERT_TRUE(test_generated_bubble_controller_->IsInstalled());
251
252     message_loop_runner_ = new content::MessageLoopRunner;
253     controller_ = new TestAutofillDialogController(
254         GetActiveWebContents(),
255         form,
256         metric_logger_,
257         message_loop_runner_);
258     controller_->Show();
259   }
260
261   content::WebContents* GetActiveWebContents() {
262     return browser()->tab_strip_model()->GetActiveWebContents();
263   }
264
265   const MockAutofillMetrics& metric_logger() { return metric_logger_; }
266   TestAutofillDialogController* controller() { return controller_; }
267
268   void RunMessageLoop() {
269     message_loop_runner_->Run();
270   }
271
272   // Loads an HTML page in |GetActiveWebContents()| with markup as follows:
273   // <form>|form_inner_html|</form>. After loading, emulates a click event on
274   // the page as requestAutocomplete() must be in response to a user gesture.
275   // Returns the |AutofillDialogControllerImpl| created by this invocation.
276   AutofillDialogControllerImpl* SetUpHtmlAndInvoke(
277       const std::string& form_inner_html) {
278     content::WebContents* contents = GetActiveWebContents();
279     TabAutofillManagerDelegate* delegate =
280         TabAutofillManagerDelegate::FromWebContents(contents);
281     DCHECK(!delegate->GetDialogControllerForTesting());
282
283     ui_test_utils::NavigateToURL(
284         browser(), GURL(std::string("data:text/html,") +
285         "<!doctype html>"
286         "<html>"
287           "<body>"
288             "<form>" + form_inner_html + "</form>"
289             "<script>"
290               "function send(msg) {"
291                 "domAutomationController.setAutomationId(0);"
292                 "domAutomationController.send(msg);"
293               "}"
294               "document.forms[0].onautocompleteerror = function(e) {"
295                 "send('error: ' + e.reason);"
296               "};"
297               "document.forms[0].onautocomplete = function() {"
298                 "send('success');"
299               "};"
300               "window.onclick = function() {"
301                 "document.forms[0].requestAutocomplete();"
302                 "send('clicked');"
303               "};"
304               "function getValueForFieldOfType(type) {"
305               "  var fields = document.getElementsByTagName('input');"
306               "  for (var i = 0; i < fields.length; i++) {"
307               "    if (fields[i].autocomplete == type) {"
308               "      send(fields[i].value);"
309               "      return;"
310               "    }"
311               "  }"
312               "  send('');"
313               "};"
314             "</script>"
315           "</body>"
316         "</html>"));
317     content::WaitForLoadStop(contents);
318
319     dom_message_queue_.reset(new content::DOMMessageQueue);
320
321     // Triggers the onclick handler which invokes requestAutocomplete().
322     content::SimulateMouseClick(contents, 0, WebKit::WebMouseEvent::ButtonLeft);
323     ExpectDomMessage("clicked");
324
325     AutofillDialogControllerImpl* controller =
326         static_cast<AutofillDialogControllerImpl*>(
327             delegate->GetDialogControllerForTesting());
328     DCHECK(controller);
329     return controller;
330   }
331
332   // Wait for a message from the DOM automation controller (from JS in the
333   // page). Requires |SetUpHtmlAndInvoke()| be called first.
334   void ExpectDomMessage(const std::string& expected) {
335     std::string message;
336     ASSERT_TRUE(dom_message_queue_->WaitForMessage(&message));
337     dom_message_queue_->ClearQueue();
338     EXPECT_EQ("\"" + expected + "\"", message);
339   }
340
341   // Returns the value filled into the first field with autocomplete attribute
342   // equal to |autocomplete_type|, or an empty string if there is no such field.
343   std::string GetValueForHTMLFieldOfType(const std::string& autocomplete_type) {
344     content::RenderViewHost* render_view_host =
345         browser()->tab_strip_model()->GetActiveWebContents()->
346         GetRenderViewHost();
347     std::string script = "getValueForFieldOfType('" + autocomplete_type + "');";
348     std::string result;
349     EXPECT_TRUE(content::ExecuteScriptAndExtractString(render_view_host, script,
350                                                        &result));
351     return result;
352   }
353
354   void AddCreditcardToProfile(Profile* profile, const CreditCard& card) {
355     PersonalDataManagerFactory::GetForProfile(profile)->AddCreditCard(card);
356     WaitForWebDB();
357   }
358
359   void AddAutofillProfileToProfile(Profile* profile,
360                                    const AutofillProfile& autofill_profile) {
361     PersonalDataManagerFactory::GetForProfile(profile)->AddProfile(
362         autofill_profile);
363     WaitForWebDB();
364   }
365
366   TestGeneratedCreditCardBubbleController* test_generated_bubble_controller() {
367     return test_generated_bubble_controller_;
368   }
369
370  private:
371   void WaitForWebDB() {
372     content::RunAllPendingInMessageLoop(content::BrowserThread::DB);
373   }
374
375   testing::NiceMock<MockAutofillMetrics> metric_logger_;
376   TestAutofillDialogController* controller_;  // Weak reference.
377   scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
378   scoped_ptr<content::DOMMessageQueue> dom_message_queue_;
379
380   // Weak; owned by the active web contents.
381   TestGeneratedCreditCardBubbleController* test_generated_bubble_controller_;
382
383   DISALLOW_COPY_AND_ASSIGN(AutofillDialogControllerTest);
384 };
385
386 #if defined(TOOLKIT_VIEWS) || defined(OS_MACOSX)
387 // Submit the form data.
388 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, Submit) {
389   controller()->GetTestableView()->SubmitForTesting();
390
391   RunMessageLoop();
392
393   EXPECT_EQ(AutofillMetrics::DIALOG_ACCEPTED,
394             metric_logger().dialog_dismissal_action());
395 }
396
397 // Cancel out of the dialog.
398 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, Cancel) {
399   controller()->GetTestableView()->CancelForTesting();
400
401   RunMessageLoop();
402
403   EXPECT_EQ(AutofillMetrics::DIALOG_CANCELED,
404             metric_logger().dialog_dismissal_action());
405 }
406
407 // Take some other action that dismisses the dialog.
408 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, Hide) {
409   controller()->Hide();
410
411   RunMessageLoop();
412
413   EXPECT_EQ(AutofillMetrics::DIALOG_CANCELED,
414             metric_logger().dialog_dismissal_action());
415 }
416
417 // Ensure that Hide() will only destroy the controller object after the
418 // message loop has run. Otherwise, there may be read-after-free issues
419 // during some tests.
420 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, DeferredDestruction) {
421   base::WeakPtr<TestAutofillDialogController> weak_ptr =
422       controller()->AsWeakPtr();
423   EXPECT_TRUE(weak_ptr.get());
424
425   controller()->Hide();
426   EXPECT_TRUE(weak_ptr.get());
427
428   RunMessageLoop();
429   EXPECT_FALSE(weak_ptr.get());
430 }
431
432 // Ensure that the expected metric is logged when the dialog is closed during
433 // signin.
434 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, CloseDuringSignin) {
435   controller()->SignInLinkClicked();
436
437   EXPECT_CALL(metric_logger(),
438               LogDialogDismissalState(
439                   AutofillMetrics::DIALOG_CANCELED_DURING_SIGNIN));
440   controller()->GetTestableView()->CancelForTesting();
441
442   RunMessageLoop();
443
444   EXPECT_EQ(AutofillMetrics::DIALOG_CANCELED,
445             metric_logger().dialog_dismissal_action());
446 }
447
448 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, FillInputFromAutofill) {
449   AutofillProfile full_profile(test::GetFullProfile());
450   controller()->GetTestingManager()->AddTestingProfile(&full_profile);
451
452   const DetailInputs& inputs =
453       controller()->RequestedFieldsForSection(SECTION_SHIPPING);
454   const DetailInput& triggering_input = inputs[0];
455   string16 value = full_profile.GetRawInfo(triggering_input.type);
456   TestableAutofillDialogView* view = controller()->GetTestableView();
457   view->SetTextContentsOfInput(triggering_input,
458                                value.substr(0, value.size() / 2));
459   view->ActivateInput(triggering_input);
460
461   ASSERT_EQ(&triggering_input, controller()->input_showing_popup());
462   controller()->DidAcceptSuggestion(string16(), 0);
463
464   // All inputs should be filled.
465   AutofillProfileWrapper wrapper(&full_profile);
466   for (size_t i = 0; i < inputs.size(); ++i) {
467     EXPECT_EQ(wrapper.GetInfo(AutofillType(inputs[i].type)),
468               view->GetTextContentsOfInput(inputs[i]));
469   }
470
471   // Now simulate some user edits and try again.
472   std::vector<string16> expectations;
473   for (size_t i = 0; i < inputs.size(); ++i) {
474     string16 users_input = i % 2 == 0 ? string16() : ASCIIToUTF16("dummy");
475     view->SetTextContentsOfInput(inputs[i], users_input);
476     // Empty inputs should be filled, others should be left alone.
477     string16 expectation =
478         &inputs[i] == &triggering_input || users_input.empty() ?
479         wrapper.GetInfo(AutofillType(inputs[i].type)) :
480         users_input;
481     expectations.push_back(expectation);
482   }
483
484   view->SetTextContentsOfInput(triggering_input,
485                                value.substr(0, value.size() / 2));
486   view->ActivateInput(triggering_input);
487   ASSERT_EQ(&triggering_input, controller()->input_showing_popup());
488   controller()->DidAcceptSuggestion(string16(), 0);
489
490   for (size_t i = 0; i < inputs.size(); ++i) {
491     EXPECT_EQ(expectations[i], view->GetTextContentsOfInput(inputs[i]));
492   }
493 }
494
495 // 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);
503
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);
512
513   ASSERT_EQ(&triggering_input, controller()->input_showing_popup());
514   controller()->DidAcceptSuggestion(string16(), 0);
515
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]));
524   }
525
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)) :
535         users_input;
536     if (AutofillType(inputs[i].type).GetStorableType() == ADDRESS_HOME_COUNTRY)
537       expectation = ASCIIToUTF16("United States");
538
539     expectations.push_back(expectation);
540   }
541
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   for (size_t i = 0; i < inputs.size(); ++i) {
549     EXPECT_EQ(expectations[i], view->GetTextContentsOfInput(inputs[i]));
550   }
551 }
552
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());
558
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);
569
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);
576
577   ASSERT_EQ(&triggering_input, controller()->input_showing_popup());
578
579   // Choose the variant suggestion.
580   controller()->DidAcceptSuggestion(string16(), 1);
581
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]));
588   }
589
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)));
594 }
595
596 // Tests that changing the value of a CC expiration date combobox works as
597 // expected when Autofill is used to fill text inputs.
598 //
599 // Flaky on Win7, WinXP, and Win Aura.  http://crbug.com/270314.
600 #if defined(OS_WIN)
601 #define MAYBE_FillComboboxFromAutofill DISABLED_FillComboboxFromAutofill
602 #else
603 #define MAYBE_FillComboboxFromAutofill FillComboboxFromAutofill
604 #endif
605 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
606                        MAYBE_FillComboboxFromAutofill) {
607   CreditCard card1;
608   test::SetCreditCardInfo(&card1, "JJ Smith", "4111111111111111", "12", "2018");
609   controller()->GetTestingManager()->AddTestingCreditCard(&card1);
610   CreditCard card2;
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);
615
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);
624
625   ASSERT_EQ(&triggering_input, controller()->input_showing_popup());
626   controller()->DidAcceptSuggestion(string16(), 0);
627
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]));
633   }
634
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);
643
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());
654     } else {
655       EXPECT_EQ(wrapper1.GetInfo(AutofillType(input.type)),
656                 view->GetTextContentsOfInput(input));
657     }
658   }
659
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);
668
669   ASSERT_EQ(&billing_triggering_input, controller()->input_showing_popup());
670   controller()->DidAcceptSuggestion(string16(), 0);
671
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());
681     } else {
682       EXPECT_EQ(wrapper1.GetInfo(AutofillType(input.type)),
683                 view->GetTextContentsOfInput(input));
684     }
685   }
686 }
687
688 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, ShouldShowErrorBubble) {
689   EXPECT_TRUE(controller()->ShouldShowErrorBubble());
690
691   CreditCard card(test::GetCreditCard());
692   ASSERT_FALSE(card.IsVerified());
693   controller()->GetTestingManager()->AddTestingCreditCard(&card);
694
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);
699
700   TestableAutofillDialogView* view = controller()->GetTestableView();
701   view->SetTextContentsOfInput(
702       cc_number_input,
703       card.GetRawInfo(CREDIT_CARD_NUMBER).substr(0, 1));
704
705   view->ActivateInput(cc_number_input);
706   EXPECT_FALSE(controller()->ShouldShowErrorBubble());
707
708   controller()->FocusMoved();
709   EXPECT_TRUE(controller()->ShouldShowErrorBubble());
710 }
711
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);
718
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());
723   ASSERT_FALSE(
724       autofill::IsValidCreditCardExpirationDate(
725           expired_card.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR),
726           expired_card.GetRawInfo(CREDIT_CARD_EXP_MONTH),
727           base::Time::Now()));
728   controller()->GetTestingManager()->AddTestingCreditCard(&expired_card);
729
730   ui::MenuModel* model = controller()->MenuModelForSection(SECTION_CC);
731   ASSERT_EQ(4, model->GetItemCount());
732
733   ASSERT_TRUE(model->IsItemCheckedAt(0));
734   EXPECT_FALSE(controller()->IsEditingExistingData(SECTION_CC));
735
736   model->ActivatedAt(1);
737   ASSERT_TRUE(model->IsItemCheckedAt(1));
738   EXPECT_TRUE(controller()->IsEditingExistingData(SECTION_CC));
739 }
740
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);
746
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();
759
760   EXPECT_EQ(no_notification_size.width(),
761             controller()->GetTestableView()->GetSize().width());
762 }
763
764 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AutocompleteEvent) {
765   AutofillDialogControllerImpl* controller =
766       SetUpHtmlAndInvoke("<input autocomplete='cc-name'>");
767
768   AddCreditcardToProfile(controller->profile(), test::GetVerifiedCreditCard());
769   AddAutofillProfileToProfile(controller->profile(),
770                               test::GetVerifiedProfile());
771
772   TestableAutofillDialogView* view = controller->GetTestableView();
773   view->SetTextContentsOfSuggestionInput(SECTION_CC, ASCIIToUTF16("123"));
774   view->SubmitForTesting();
775   ExpectDomMessage("success");
776 }
777
778 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
779                        AutocompleteErrorEventReasonInvalid) {
780   AutofillDialogControllerImpl* controller =
781       SetUpHtmlAndInvoke("<input autocomplete='cc-name' pattern='.*zebra.*'>");
782
783   const CreditCard& credit_card = test::GetVerifiedCreditCard();
784   ASSERT_TRUE(
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());
790
791   TestableAutofillDialogView* view = controller->GetTestableView();
792   view->SetTextContentsOfSuggestionInput(SECTION_CC, ASCIIToUTF16("123"));
793   view->SubmitForTesting();
794   ExpectDomMessage("error: invalid");
795 }
796
797 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
798                        AutocompleteErrorEventReasonCancel) {
799   SetUpHtmlAndInvoke("<input autocomplete='cc-name'>")->GetTestableView()->
800       CancelForTesting();
801   ExpectDomMessage("error: cancel");
802 }
803
804 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, NoCvcSegfault) {
805   controller()->set_use_validation(true);
806
807   CreditCard credit_card(test::GetVerifiedCreditCard());
808   controller()->GetTestingManager()->AddTestingCreditCard(&credit_card);
809   EXPECT_FALSE(controller()->IsEditingExistingData(SECTION_CC));
810
811   ASSERT_NO_FATAL_FAILURE(
812       controller()->GetTestableView()->SubmitForTesting());
813 }
814
815 // Flaky on Win7, WinXP, and Win Aura.  http://crbug.com/270314.
816 #if defined(OS_WIN)
817 #define MAYBE_PreservedSections DISABLED_PreservedSections
818 #else
819 #define MAYBE_PreservedSections PreservedSections
820 #endif
821 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, MAYBE_PreservedSections) {
822   controller()->set_use_validation(true);
823
824   // Set up some Autofill state.
825   CreditCard credit_card(test::GetVerifiedCreditCard());
826   controller()->GetTestingManager()->AddTestingCreditCard(&credit_card);
827
828   AutofillProfile profile(test::GetVerifiedProfile());
829   controller()->GetTestingManager()->AddTestingProfile(&profile);
830
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));
835
836   EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_CC));
837   EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_BILLING));
838   EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_SHIPPING));
839
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));
847
848   ui::MenuModel* account_chooser = controller()->MenuModelForAccountChooser();
849   ASSERT_TRUE(account_chooser->IsItemCheckedAt(0));
850
851   // Check that the view's in the state we expect before starting to simulate
852   // user input.
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));
857
858   EXPECT_TRUE(controller()->IsManuallyEditingSection(SECTION_CC_BILLING));
859
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"));
866
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);
871
872   EXPECT_TRUE(controller()->IsManuallyEditingSection(SECTION_SHIPPING));
873
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"));
879
880   // Switch to using Autofill.
881   account_chooser->ActivatedAt(1);
882
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));
889
890   EXPECT_TRUE(controller()->IsManuallyEditingSection(SECTION_CC));
891   EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_BILLING));
892   EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_SHIPPING));
893
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));
899
900   EXPECT_NE(ASCIIToUTF16("shipping name"),
901             view->GetTextContentsOfInput(shipping_zip));
902 }
903 #endif  // defined(TOOLKIT_VIEWS) || defined(OS_MACOSX)
904
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());
910
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());
915
916   base::string16 last_four =
917       wallet_items->instruments()[0]->TypeAndLastFourDigits();
918   controller()->OnDidGetWalletItems(wallet_items.Pass());
919
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());
925
926   EXPECT_CALL(*controller()->GetTestingWalletClient(), GetFullWallet(_));
927   scoped_ptr<risk::Fingerprint> fingerprint(new risk::Fingerprint());
928   fingerprint->mutable_machine_characteristics()->mutable_screen_size()->
929       set_width(1024);
930   controller()->OnDidLoadRiskFingerprintData(fingerprint.Pass());
931
932   controller()->OnDidGetFullWallet(
933       wallet::GetTestFullWalletWithRequiredActions(
934           std::vector<wallet::RequiredAction>(1, wallet::VERIFY_CVV)));
935
936   ASSERT_TRUE(controller()->IsSubmitPausedOn(wallet::VERIFY_CVV));
937
938   std::string fake_cvc("123");
939   test_view->SetTextContentsOfSuggestionInput(SECTION_CC_BILLING,
940                                               ASCIIToUTF16(fake_cvc));
941
942   EXPECT_FALSE(test_view->IsShowingOverlay());
943   EXPECT_CALL(*controller()->GetTestingWalletClient(),
944               AuthenticateInstrument(_, fake_cvc));
945   controller()->OnAccept();
946   EXPECT_TRUE(test_view->IsShowingOverlay());
947
948   EXPECT_CALL(*controller()->GetTestingWalletClient(), GetFullWallet(_));
949   controller()->OnDidAuthenticateInstrument(true);
950   controller()->OnDidGetFullWallet(wallet::GetTestFullWallet());
951   controller()->ForceFinishSubmit();
952
953   RunMessageLoop();
954
955   EXPECT_EQ(1, test_generated_bubble_controller()->bubbles_shown());
956   EXPECT_EQ(last_four, test_generated_bubble_controller()->backing_card_name());
957 }
958
959 // See http://crbug.com/314627
960 #if defined(OS_WIN)
961 #define MAYBE_SignInNoCrash DISABLED_SignInNoCrash
962 #else
963 #define MAYBE_SignInNoCrash SignInNoCrash
964 #endif
965
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,
972       true);
973
974   InitializeController();
975
976   const AccountChooserModel& account_chooser_model =
977       controller()->AccountChooserModelForTesting();
978   EXPECT_FALSE(account_chooser_model.WalletIsSelected());
979
980   ui_test_utils::UrlLoadObserver observer(
981       controller()->SignInUrl(),
982       content::NotificationService::AllSources());
983
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));
990
991   TestableAutofillDialogView* view = controller()->GetTestableView();
992   EXPECT_TRUE(view->GetSignInWebContents());
993   EXPECT_TRUE(controller()->ShouldShowSignInWebView());
994   observer.Wait();
995
996   // Wallet should now be selected and Chrome shouldn't have crashed.
997   EXPECT_TRUE(account_chooser_model.WalletIsSelected());
998 }
999
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'>");
1005
1006   AddCreditcardToProfile(controller->profile(), test::GetVerifiedCreditCard());
1007   AddAutofillProfileToProfile(controller->profile(),
1008                               test::GetVerifiedProfile());
1009
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"));
1015 }
1016
1017 }  // namespace autofill