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