autofill_dialog_controller_browsertest.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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/logging.h"
8#include "base/memory/ref_counted.h"
9#include "base/memory/weak_ptr.h"
10#include "base/message_loop/message_loop.h"
11#include "base/prefs/pref_service.h"
12#include "base/strings/utf_string_conversions.h"
13#include "base/time/time.h"
14#include "chrome/browser/autofill/personal_data_manager_factory.h"
15#include "chrome/browser/profiles/profile.h"
16#include "chrome/browser/ui/autofill/account_chooser_model.h"
17#include "chrome/browser/ui/autofill/autofill_dialog_controller_impl.h"
18#include "chrome/browser/ui/autofill/autofill_dialog_i18n_input.h"
19#include "chrome/browser/ui/autofill/autofill_dialog_view.h"
20#include "chrome/browser/ui/autofill/autofill_dialog_view_tester.h"
21#include "chrome/browser/ui/autofill/chrome_autofill_client.h"
22#include "chrome/browser/ui/autofill/data_model_wrapper.h"
23#include "chrome/browser/ui/autofill/mock_address_validator.h"
24#include "chrome/browser/ui/autofill/test_generated_credit_card_bubble_controller.h"
25#include "chrome/browser/ui/browser.h"
26#include "chrome/browser/ui/browser_tabstrip.h"
27#include "chrome/browser/ui/tabs/tab_strip_model.h"
28#include "chrome/common/chrome_switches.h"
29#include "chrome/common/pref_names.h"
30#include "chrome/common/url_constants.h"
31#include "chrome/test/base/in_process_browser_test.h"
32#include "chrome/test/base/ui_test_utils.h"
33#include "components/autofill/content/browser/risk/proto/fingerprint.pb.h"
34#include "components/autofill/content/browser/wallet/gaia_account.h"
35#include "components/autofill/content/browser/wallet/mock_wallet_client.h"
36#include "components/autofill/content/browser/wallet/wallet_service_url.h"
37#include "components/autofill/content/browser/wallet/wallet_test_util.h"
38#include "components/autofill/core/browser/autofill_metrics.h"
39#include "components/autofill/core/browser/autofill_test_utils.h"
40#include "components/autofill/core/browser/test_personal_data_manager.h"
41#include "components/autofill/core/browser/validation.h"
42#include "components/autofill/core/common/autofill_switches.h"
43#include "components/autofill/core/common/form_data.h"
44#include "components/autofill/core/common/form_field_data.h"
45#include "content/public/browser/browser_thread.h"
46#include "content/public/browser/interstitial_page.h"
47#include "content/public/browser/navigation_details.h"
48#include "content/public/browser/navigation_entry.h"
49#include "content/public/browser/notification_service.h"
50#include "content/public/browser/notification_types.h"
51#include "content/public/browser/page_navigator.h"
52#include "content/public/browser/web_contents.h"
53#include "content/public/browser/web_contents_delegate.h"
54#include "content/public/common/content_switches.h"
55#include "content/public/common/page_transition_types.h"
56#include "content/public/common/referrer.h"
57#include "content/public/common/url_constants.h"
58#include "content/public/test/browser_test_utils.h"
59#include "content/public/test/test_utils.h"
60#include "google_apis/gaia/google_service_auth_error.h"
61#include "net/test/spawned_test_server/spawned_test_server.h"
62#include "testing/gmock/include/gmock/gmock.h"
63#include "testing/gtest/include/gtest/gtest.h"
64#include "third_party/WebKit/public/web/WebInputEvent.h"
65#include "ui/base/window_open_disposition.h"
66#include "url/gurl.h"
67
68#if defined(OS_WIN)
69#include "base/win/windows_version.h"
70#elif defined(OS_MACOSX)
71#include "base/mac/mac_util.h"
72#include "base/mac/scoped_nsautorelease_pool.h"
73#include "chrome/browser/ui/cocoa/run_loop_testing.h"
74#endif
75
76using base::ASCIIToUTF16;
77
78namespace autofill {
79
80namespace {
81
82using testing::Return;
83using testing::_;
84using ::i18n::addressinput::AddressValidator;
85
86void MockCallback(AutofillClient::RequestAutocompleteResult,
87                  const base::string16& message,
88                  const FormStructure*) {
89}
90
91class MockAutofillMetrics : public AutofillMetrics {
92 public:
93  MockAutofillMetrics()
94      : dialog_dismissal_action_(static_cast<DialogDismissalAction>(-1)) {}
95  virtual ~MockAutofillMetrics() {}
96
97  virtual void LogDialogUiDuration(
98      const base::TimeDelta& duration,
99      DialogDismissalAction dismissal_action) const OVERRIDE {
100    // Ignore constness for testing.
101    MockAutofillMetrics* mutable_this = const_cast<MockAutofillMetrics*>(this);
102    mutable_this->dialog_dismissal_action_ = dismissal_action;
103  }
104
105  AutofillMetrics::DialogDismissalAction dialog_dismissal_action() const {
106    return dialog_dismissal_action_;
107  }
108
109  MOCK_CONST_METHOD1(LogDialogDismissalState,
110                     void(DialogDismissalState state));
111
112 private:
113  DialogDismissalAction dialog_dismissal_action_;
114
115  DISALLOW_COPY_AND_ASSIGN(MockAutofillMetrics);
116};
117
118class TestAutofillDialogController : public AutofillDialogControllerImpl {
119 public:
120  TestAutofillDialogController(
121      content::WebContents* contents,
122      const FormData& form_data,
123      const AutofillMetrics& metric_logger,
124      scoped_refptr<content::MessageLoopRunner> runner)
125      : AutofillDialogControllerImpl(contents,
126                                     form_data,
127                                     form_data.origin,
128                                     base::Bind(&MockCallback)),
129        metric_logger_(metric_logger),
130        mock_wallet_client_(
131            Profile::FromBrowserContext(contents->GetBrowserContext())->
132                GetRequestContext(), this, form_data.origin),
133        message_loop_runner_(runner),
134        use_validation_(false),
135        weak_ptr_factory_(this),
136        sign_in_user_index_(0U) {
137    test_manager_.Init(
138        NULL,
139        Profile::FromBrowserContext(contents->GetBrowserContext())->GetPrefs(),
140        false);
141  }
142
143  virtual ~TestAutofillDialogController() {}
144
145  virtual GURL SignInUrl() const OVERRIDE {
146    return GURL(chrome::kChromeUIVersionURL);
147  }
148
149  virtual void ViewClosed() OVERRIDE {
150    message_loop_runner_->Quit();
151    AutofillDialogControllerImpl::ViewClosed();
152  }
153
154  virtual base::string16 InputValidityMessage(
155      DialogSection section,
156      ServerFieldType type,
157      const base::string16& value) OVERRIDE {
158    if (!use_validation_)
159      return base::string16();
160    return AutofillDialogControllerImpl::InputValidityMessage(
161        section, type, value);
162  }
163
164  virtual ValidityMessages InputsAreValid(
165      DialogSection section,
166      const FieldValueMap& inputs) OVERRIDE {
167    if (!use_validation_)
168      return ValidityMessages();
169    return AutofillDialogControllerImpl::InputsAreValid(section, inputs);
170  }
171
172  // Saving to Chrome is tested in AutofillDialogControllerImpl unit tests.
173  // TODO(estade): test that the view defaults to saving to Chrome.
174  virtual bool ShouldOfferToSaveInChrome() const OVERRIDE {
175    return true;
176  }
177
178  void ForceFinishSubmit() {
179    DoFinishSubmit();
180  }
181
182  // Increase visibility for testing.
183  using AutofillDialogControllerImpl::view;
184  using AutofillDialogControllerImpl::popup_input_type;
185
186  MOCK_METHOD0(LoadRiskFingerprintData, void());
187
188  virtual std::vector<DialogNotification> CurrentNotifications() OVERRIDE {
189    return notifications_;
190  }
191
192  void set_notifications(const std::vector<DialogNotification>& notifications) {
193    notifications_ = notifications;
194  }
195
196  TestPersonalDataManager* GetTestingManager() {
197    return &test_manager_;
198  }
199
200  MockAddressValidator* GetMockValidator() {
201    return &mock_validator_;
202  }
203
204  using AutofillDialogControllerImpl::IsEditingExistingData;
205  using AutofillDialogControllerImpl::IsManuallyEditingSection;
206  using AutofillDialogControllerImpl::IsPayingWithWallet;
207  using AutofillDialogControllerImpl::IsSubmitPausedOn;
208  using AutofillDialogControllerImpl::OnDidLoadRiskFingerprintData;
209  using AutofillDialogControllerImpl::AccountChooserModelForTesting;
210  using AutofillDialogControllerImpl::
211      ClearLastWalletItemsFetchTimestampForTesting;
212
213  void set_use_validation(bool use_validation) {
214    use_validation_ = use_validation;
215  }
216
217  base::WeakPtr<TestAutofillDialogController> AsWeakPtr() {
218    return weak_ptr_factory_.GetWeakPtr();
219  }
220
221  wallet::MockWalletClient* GetTestingWalletClient() {
222    return &mock_wallet_client_;
223  }
224
225  void set_sign_in_user_index(size_t sign_in_user_index) {
226    sign_in_user_index_ = sign_in_user_index;
227  }
228
229 protected:
230  virtual PersonalDataManager* GetManager() const OVERRIDE {
231    return &const_cast<TestAutofillDialogController*>(this)->test_manager_;
232  }
233
234  virtual AddressValidator* GetValidator() OVERRIDE {
235    return &mock_validator_;
236  }
237
238  virtual wallet::WalletClient* GetWalletClient() OVERRIDE {
239    return &mock_wallet_client_;
240  }
241
242  virtual bool IsSignInContinueUrl(const GURL& url, size_t* user_index) const
243      OVERRIDE {
244    *user_index = sign_in_user_index_;
245    return url == wallet::GetSignInContinueUrl();
246  }
247
248 private:
249  // To specify our own metric logger.
250  virtual const AutofillMetrics& GetMetricLogger() const OVERRIDE {
251    return metric_logger_;
252  }
253
254  const AutofillMetrics& metric_logger_;
255  TestPersonalDataManager test_manager_;
256  testing::NiceMock<MockAddressValidator> mock_validator_;
257  testing::NiceMock<wallet::MockWalletClient> mock_wallet_client_;
258  scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
259  bool use_validation_;
260
261  // A list of notifications to show in the notification area of the dialog.
262  // This is used to control what |CurrentNotifications()| returns for testing.
263  std::vector<DialogNotification> notifications_;
264
265  // Allows generation of WeakPtrs, so controller liveness can be tested.
266  base::WeakPtrFactory<TestAutofillDialogController> weak_ptr_factory_;
267
268  // The user index that is assigned in IsSignInContinueUrl().
269  size_t sign_in_user_index_;
270
271  DISALLOW_COPY_AND_ASSIGN(TestAutofillDialogController);
272};
273
274// This is a copy of ui_test_utils::UrlLoadObserver, except it observes
275// NAV_ENTRY_COMMITTED instead of LOAD_STOP. This is to match the notification
276// that AutofillDialogControllerImpl observes. Since NAV_ENTRY_COMMITTED comes
277// before LOAD_STOP, and the controller deletes the web contents after receiving
278// the former, we will sometimes fail to observe a LOAD_STOP.
279// TODO(estade): Should the controller observe LOAD_STOP instead?
280class NavEntryCommittedObserver : public content::WindowedNotificationObserver {
281 public:
282  NavEntryCommittedObserver(const GURL& url,
283                            const content::NotificationSource& source)
284    : WindowedNotificationObserver(content::NOTIFICATION_NAV_ENTRY_COMMITTED,
285                                   source),
286      url_(url) {}
287
288  virtual ~NavEntryCommittedObserver() {}
289
290  // content::NotificationObserver:
291  virtual void Observe(int type,
292                       const content::NotificationSource& source,
293                       const content::NotificationDetails& details) OVERRIDE {
294    content::LoadCommittedDetails* load_details =
295        content::Details<content::LoadCommittedDetails>(details).ptr();
296    if (load_details->entry->GetVirtualURL() != url_)
297      return;
298
299    WindowedNotificationObserver::Observe(type, source, details);
300  }
301
302 private:
303  GURL url_;
304
305  DISALLOW_COPY_AND_ASSIGN(NavEntryCommittedObserver);
306};
307
308}  // namespace
309
310class AutofillDialogControllerTest : public InProcessBrowserTest {
311 public:
312  AutofillDialogControllerTest() : controller_(NULL) {}
313  virtual ~AutofillDialogControllerTest() {}
314
315  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
316    command_line->AppendSwitch(::switches::kReduceSecurityForTesting);
317  }
318
319  virtual void SetUpOnMainThread() OVERRIDE {
320    autofill::test::DisableSystemServices(browser()->profile()->GetPrefs());
321    InitializeController();
322  }
323
324 protected:
325  bool SectionHasField(DialogSection section, ServerFieldType type) {
326    const DetailInputs& fields =
327        controller()->RequestedFieldsForSection(section);
328    for (size_t i = 0; i < fields.size(); ++i) {
329      if (type == fields[i].type)
330        return true;
331    }
332    return false;
333  }
334
335  // A helper function that cycles the MessageLoop, and on Mac, the Cocoa run
336  // loop. It also drains the NSAutoreleasePool.
337  void CycleRunLoops() {
338    content::RunAllPendingInMessageLoop();
339#if defined(OS_MACOSX)
340    chrome::testing::NSRunLoopRunAllPending();
341    AutoreleasePool()->Recycle();
342#endif
343  }
344
345  void InitializeControllerWithoutShowing() {
346    if (controller_)
347      controller_->Hide();
348
349    FormData form;
350    form.name = ASCIIToUTF16("TestForm");
351    form.method = ASCIIToUTF16("POST");
352    form.user_submitted = true;
353
354    FormFieldData field;
355    field.autocomplete_attribute = "shipping tel";
356    form.fields.push_back(field);
357
358    FormFieldData cc;
359    cc.autocomplete_attribute = "cc-number";
360    form.fields.push_back(cc);
361
362    test_generated_bubble_controller_ =
363        new testing::NiceMock<TestGeneratedCreditCardBubbleController>(
364            GetActiveWebContents());
365    ASSERT_TRUE(test_generated_bubble_controller_->IsInstalled());
366
367    message_loop_runner_ = new content::MessageLoopRunner;
368    controller_ = new TestAutofillDialogController(
369        GetActiveWebContents(),
370        form,
371        metric_logger_,
372        message_loop_runner_);
373  }
374
375  void InitializeController() {
376    InitializeControllerWithoutShowing();
377    controller_->Show();
378    CycleRunLoops();  // Ensures dialog is fully visible.
379  }
380
381  content::WebContents* GetActiveWebContents() {
382    return browser()->tab_strip_model()->GetActiveWebContents();
383  }
384
385  content::RenderViewHost* GetRenderViewHost() {
386    return GetActiveWebContents()->GetRenderViewHost();
387  }
388
389  scoped_ptr<AutofillDialogViewTester> GetViewTester() {
390    return AutofillDialogViewTester::For(controller()->view()).Pass();
391  }
392
393  const MockAutofillMetrics& metric_logger() { return metric_logger_; }
394  TestAutofillDialogController* controller() { return controller_; }
395
396  void RunMessageLoop() {
397    message_loop_runner_->Run();
398  }
399
400  // Loads an HTML page in |GetActiveWebContents()| with markup as follows:
401  // <form>|form_inner_html|</form>. After loading, emulates a click event on
402  // the page as requestAutocomplete() must be in response to a user gesture.
403  // Returns the |AutofillDialogControllerImpl| created by this invocation.
404  AutofillDialogControllerImpl* SetUpHtmlAndInvoke(
405      const std::string& form_inner_html) {
406    content::WebContents* contents = GetActiveWebContents();
407    ChromeAutofillClient* client =
408        ChromeAutofillClient::FromWebContents(contents);
409    CHECK(!client->GetDialogControllerForTesting());
410
411    ui_test_utils::NavigateToURL(
412        browser(), GURL(std::string("data:text/html,") +
413        "<!doctype html>"
414        "<html>"
415          "<body>"
416            "<form>" + form_inner_html + "</form>"
417            "<script>"
418              "var invalidEvents = [];"
419              "function recordInvalid(e) {"
420                "if (e.type != 'invalid') throw 'only invalid events allowed';"
421                "invalidEvents.push(e);"
422              "}"
423              "function send(msg) {"
424                "domAutomationController.setAutomationId(0);"
425                "domAutomationController.send(msg);"
426              "}"
427              "document.forms[0].onautocompleteerror = function(e) {"
428                "send('error: ' + e.reason);"
429              "};"
430              "document.forms[0].onautocomplete = function() {"
431                "send('success');"
432              "};"
433              "window.onclick = function() {"
434                "var inputs = document.forms[0].querySelectorAll('input');"
435                "for (var i = 0; i < inputs.length; ++i) {"
436                  "inputs[i].oninvalid = recordInvalid;"
437                "}"
438                "document.forms[0].requestAutocomplete();"
439                "send('clicked');"
440              "};"
441              "function loadIframe() {"
442              "  var iframe = document.createElement('iframe');"
443              "  iframe.onload = function() {"
444              "    send('iframe loaded');"
445              "  };"
446              "  iframe.src = 'about:blank';"
447              "  document.body.appendChild(iframe);"
448              "}"
449              "function getValueForFieldOfType(type) {"
450              "  var fields = document.getElementsByTagName('input');"
451              "  for (var i = 0; i < fields.length; i++) {"
452              "    if (fields[i].autocomplete == type) {"
453              "      send(fields[i].value);"
454              "      return;"
455              "    }"
456              "  }"
457              "  send('');"
458              "};"
459            "</script>"
460          "</body>"
461        "</html>"));
462
463    InitiateDialog();
464    AutofillDialogControllerImpl* controller =
465        static_cast<AutofillDialogControllerImpl*>(
466            client->GetDialogControllerForTesting());
467    return controller;
468  }
469
470  // Loads an html page on a provided server, the causes it to launch rAc.
471  // Returns whether rAc succesfully launched.
472  bool RunTestPage(const net::SpawnedTestServer& server) {
473    GURL url = server.GetURL(
474        "files/request_autocomplete/test_page.html");
475    ui_test_utils::NavigateToURL(browser(), url);
476
477    // Pass through the broken SSL interstitial, if any.
478    content::WebContents* contents = GetActiveWebContents();
479    content::InterstitialPage* interstitial_page =
480        contents->GetInterstitialPage();
481    if (interstitial_page) {
482      ui_test_utils::UrlLoadObserver observer(
483          url,
484          content::Source<content::NavigationController>(
485              &contents->GetController()));
486      interstitial_page->Proceed();
487      observer.Wait();
488    }
489
490    InitiateDialog();
491
492    ChromeAutofillClient* client =
493        ChromeAutofillClient::FromWebContents(contents);
494    AutofillDialogControllerImpl* controller =
495        static_cast<AutofillDialogControllerImpl*>(
496            client->GetDialogControllerForTesting());
497    return !!controller;
498  }
499
500  // Wait for a message from the DOM automation controller (from JS in the
501  // page). Requires |SetUpHtmlAndInvoke()| be called first.
502  void ExpectDomMessage(const std::string& expected) {
503    std::string message;
504    ASSERT_TRUE(dom_message_queue_->WaitForMessage(&message));
505    dom_message_queue_->ClearQueue();
506    EXPECT_EQ("\"" + expected + "\"", message);
507  }
508
509  void InitiateDialog() {
510    dom_message_queue_.reset(new content::DOMMessageQueue);
511
512    // Triggers the onclick handler which invokes requestAutocomplete().
513    content::WebContents* contents = GetActiveWebContents();
514    content::SimulateMouseClick(contents, 0, blink::WebMouseEvent::ButtonLeft);
515    ExpectDomMessage("clicked");
516  }
517
518  // Returns the value filled into the first field with autocomplete attribute
519  // equal to |autocomplete_type|, or an empty string if there is no such field.
520  std::string GetValueForHTMLFieldOfType(const std::string& autocomplete_type) {
521    std::string script = "getValueForFieldOfType('" + autocomplete_type + "');";
522    std::string result;
523    EXPECT_TRUE(content::ExecuteScriptAndExtractString(GetRenderViewHost(),
524                                                       script,
525                                                       &result));
526    return result;
527  }
528
529  void AddCreditcardToProfile(Profile* profile, const CreditCard& card) {
530    PersonalDataManagerFactory::GetForProfile(profile)->AddCreditCard(card);
531    WaitForWebDB();
532  }
533
534  void AddAutofillProfileToProfile(Profile* profile,
535                                   const AutofillProfile& autofill_profile) {
536    PersonalDataManagerFactory::GetForProfile(profile)->AddProfile(
537        autofill_profile);
538    WaitForWebDB();
539  }
540
541  TestGeneratedCreditCardBubbleController* test_generated_bubble_controller() {
542    return test_generated_bubble_controller_;
543  }
544
545 private:
546  void WaitForWebDB() {
547    content::RunAllPendingInMessageLoop(content::BrowserThread::DB);
548  }
549
550  testing::NiceMock<MockAutofillMetrics> metric_logger_;
551  TestAutofillDialogController* controller_;  // Weak reference.
552  scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
553  scoped_ptr<content::DOMMessageQueue> dom_message_queue_;
554
555  // Weak; owned by the active web contents.
556  TestGeneratedCreditCardBubbleController* test_generated_bubble_controller_;
557
558  DISALLOW_COPY_AND_ASSIGN(AutofillDialogControllerTest);
559};
560
561// Submit the form data.
562IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, Submit) {
563  GetViewTester()->SubmitForTesting();
564  RunMessageLoop();
565
566  EXPECT_EQ(AutofillMetrics::DIALOG_ACCEPTED,
567            metric_logger().dialog_dismissal_action());
568}
569
570// Cancel out of the dialog.
571IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, Cancel) {
572  EXPECT_CALL(metric_logger(),
573              LogDialogDismissalState(
574                  AutofillMetrics::DIALOG_CANCELED_NO_INVALID_FIELDS));
575
576  GetViewTester()->CancelForTesting();
577  RunMessageLoop();
578
579  EXPECT_EQ(AutofillMetrics::DIALOG_CANCELED,
580            metric_logger().dialog_dismissal_action());
581}
582
583// Take some other action that dismisses the dialog.
584IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, Hide) {
585  EXPECT_CALL(metric_logger(),
586              LogDialogDismissalState(
587                  AutofillMetrics::DIALOG_CANCELED_NO_INVALID_FIELDS));
588  controller()->Hide();
589
590  RunMessageLoop();
591
592  EXPECT_EQ(AutofillMetrics::DIALOG_CANCELED,
593            metric_logger().dialog_dismissal_action());
594}
595
596IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, CancelWithSuggestions) {
597  EXPECT_CALL(metric_logger(),
598              LogDialogDismissalState(
599                  AutofillMetrics::DIALOG_CANCELED_NO_EDITS));
600
601  CreditCard card(test::GetVerifiedCreditCard());
602  controller()->GetTestingManager()->AddTestingCreditCard(&card);
603  AutofillProfile profile(test::GetVerifiedProfile());
604  controller()->GetTestingManager()->AddTestingProfile(&profile);
605
606  EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_CC));
607  EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_BILLING));
608  EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_SHIPPING));
609
610  GetViewTester()->CancelForTesting();
611  RunMessageLoop();
612
613  EXPECT_EQ(AutofillMetrics::DIALOG_CANCELED,
614            metric_logger().dialog_dismissal_action());
615}
616
617IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AcceptWithSuggestions) {
618  EXPECT_CALL(metric_logger(),
619              LogDialogDismissalState(
620                  AutofillMetrics::DIALOG_ACCEPTED_EXISTING_AUTOFILL_DATA));
621
622  CreditCard card(test::GetVerifiedCreditCard());
623  controller()->GetTestingManager()->AddTestingCreditCard(&card);
624  AutofillProfile profile(test::GetVerifiedProfile());
625  controller()->GetTestingManager()->AddTestingProfile(&profile);
626
627  EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_CC));
628  EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_BILLING));
629  EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_SHIPPING));
630
631  GetViewTester()->SubmitForTesting();
632  RunMessageLoop();
633
634  EXPECT_EQ(AutofillMetrics::DIALOG_ACCEPTED,
635            metric_logger().dialog_dismissal_action());
636}
637
638// Ensure that Hide() will only destroy the controller object after the
639// message loop has run. Otherwise, there may be read-after-free issues
640// during some tests.
641IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, DeferredDestruction) {
642  base::WeakPtr<TestAutofillDialogController> weak_ptr =
643      controller()->AsWeakPtr();
644  EXPECT_TRUE(weak_ptr.get());
645
646  controller()->Hide();
647  EXPECT_TRUE(weak_ptr.get());
648
649  RunMessageLoop();
650  EXPECT_FALSE(weak_ptr.get());
651}
652
653// Ensure that the expected metric is logged when the dialog is closed during
654// signin.
655IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, CloseDuringSignin) {
656  controller()->SignInLinkClicked();
657
658  EXPECT_CALL(metric_logger(),
659              LogDialogDismissalState(
660                  AutofillMetrics::DIALOG_CANCELED_DURING_SIGNIN));
661  GetViewTester()->CancelForTesting();
662
663  RunMessageLoop();
664
665  EXPECT_EQ(AutofillMetrics::DIALOG_CANCELED,
666            metric_logger().dialog_dismissal_action());
667}
668
669IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, FillInputFromAutofill) {
670  AutofillProfile full_profile(test::GetFullProfile());
671  const base::string16 formatted_phone(ASCIIToUTF16("+1 (310) 555 1234"));
672  full_profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, formatted_phone);
673  controller()->GetTestingManager()->AddTestingProfile(&full_profile);
674
675  // Select "Add new shipping address...".
676  ui::MenuModel* model = controller()->MenuModelForSection(SECTION_SHIPPING);
677  model->ActivatedAt(model->GetItemCount() - 2);
678  ASSERT_TRUE(controller()->IsManuallyEditingSection(SECTION_SHIPPING));
679
680  const DetailInputs& inputs =
681      controller()->RequestedFieldsForSection(SECTION_SHIPPING);
682  const ServerFieldType triggering_type = inputs[0].type;
683  base::string16 value = full_profile.GetRawInfo(triggering_type);
684  scoped_ptr<AutofillDialogViewTester> view = GetViewTester();
685  view->SetTextContentsOfInput(triggering_type,
686                               value.substr(0, value.size() / 2));
687  view->ActivateInput(triggering_type);
688
689  ASSERT_EQ(triggering_type, controller()->popup_input_type());
690  controller()->DidAcceptSuggestion(base::string16(), 0);
691
692  // All inputs should be filled.
693  AutofillProfileWrapper wrapper(&full_profile);
694  for (size_t i = 0; i < inputs.size(); ++i) {
695    EXPECT_EQ(wrapper.GetInfoForDisplay(AutofillType(inputs[i].type)),
696              view->GetTextContentsOfInput(inputs[i].type));
697
698    // Double check the correct formatting is used for the phone number.
699    if (inputs[i].type == PHONE_HOME_WHOLE_NUMBER)
700      EXPECT_EQ(formatted_phone, view->GetTextContentsOfInput(inputs[i].type));
701  }
702
703  // Now simulate some user edits and try again.
704  std::vector<base::string16> expectations;
705  for (size_t i = 0; i < inputs.size(); ++i) {
706    if (controller()->ComboboxModelForAutofillType(inputs[i].type)) {
707      expectations.push_back(base::string16());
708      continue;
709    }
710    base::string16 users_input = i % 2 == 0 ? base::string16()
711                                            : ASCIIToUTF16("dummy");
712    view->SetTextContentsOfInput(inputs[i].type, users_input);
713    // Empty inputs should be filled, others should be left alone.
714    base::string16 expectation =
715        inputs[i].type == triggering_type || users_input.empty() ?
716        wrapper.GetInfoForDisplay(AutofillType(inputs[i].type)) :
717        users_input;
718    expectations.push_back(expectation);
719  }
720
721  view->SetTextContentsOfInput(triggering_type,
722                               value.substr(0, value.size() / 2));
723  view->ActivateInput(triggering_type);
724  ASSERT_EQ(triggering_type, controller()->popup_input_type());
725  controller()->DidAcceptSuggestion(base::string16(), 0);
726
727  for (size_t i = 0; i < inputs.size(); ++i) {
728    if (controller()->ComboboxModelForAutofillType(inputs[i].type))
729      continue;
730    EXPECT_EQ(expectations[i], view->GetTextContentsOfInput(inputs[i].type));
731  }
732
733  EXPECT_CALL(metric_logger(),
734              LogDialogDismissalState(
735                  AutofillMetrics::DIALOG_ACCEPTED_SAVE_TO_AUTOFILL));
736  view->SubmitForTesting();
737}
738
739// This test makes sure that picking a profile variant in the Autofill
740// popup works as expected.
741IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
742                       FillInputFromAutofillVariant) {
743  AutofillProfile full_profile(test::GetFullProfile());
744
745  // Set up some variant data.
746  std::vector<base::string16> names;
747  names.push_back(ASCIIToUTF16("John Doe"));
748  names.push_back(ASCIIToUTF16("Jane Doe"));
749  full_profile.SetRawMultiInfo(NAME_FULL, names);
750  std::vector<base::string16> emails;
751  emails.push_back(ASCIIToUTF16("user@example.com"));
752  emails.push_back(ASCIIToUTF16("admin@example.com"));
753  full_profile.SetRawMultiInfo(EMAIL_ADDRESS, emails);
754  controller()->GetTestingManager()->AddTestingProfile(&full_profile);
755
756  const DetailInputs& inputs =
757      controller()->RequestedFieldsForSection(SECTION_BILLING);
758  const ServerFieldType triggering_type = inputs[0].type;
759  EXPECT_EQ(NAME_BILLING_FULL, triggering_type);
760  scoped_ptr<AutofillDialogViewTester> view = GetViewTester();
761  view->ActivateInput(triggering_type);
762
763  ASSERT_EQ(triggering_type, controller()->popup_input_type());
764
765  // Choose the variant suggestion.
766  controller()->DidAcceptSuggestion(base::string16(), 1);
767
768  // All inputs should be filled.
769  AutofillProfileWrapper wrapper(
770      &full_profile, AutofillType(NAME_BILLING_FULL), 1);
771  for (size_t i = 0; i < inputs.size(); ++i) {
772    EXPECT_EQ(wrapper.GetInfoForDisplay(AutofillType(inputs[i].type)),
773              view->GetTextContentsOfInput(inputs[i].type));
774  }
775
776  // Make sure the wrapper applies the variant index to the right group.
777  EXPECT_EQ(names[1], wrapper.GetInfo(AutofillType(NAME_BILLING_FULL)));
778  // Make sure the wrapper doesn't apply the variant index to the wrong group.
779  EXPECT_EQ(emails[0], wrapper.GetInfo(AutofillType(EMAIL_ADDRESS)));
780}
781
782// Tests that changing the value of a CC expiration date combobox works as
783// expected when Autofill is used to fill text inputs.
784//
785// Flaky on Win7, WinXP, and Win Aura.  http://crbug.com/270314.
786#if defined(OS_WIN)
787#define MAYBE_FillComboboxFromAutofill DISABLED_FillComboboxFromAutofill
788#else
789#define MAYBE_FillComboboxFromAutofill FillComboboxFromAutofill
790#endif
791IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
792                       MAYBE_FillComboboxFromAutofill) {
793  CreditCard card1;
794  test::SetCreditCardInfo(&card1, "JJ Smith", "4111111111111111", "12", "2018");
795  controller()->GetTestingManager()->AddTestingCreditCard(&card1);
796  CreditCard card2;
797  test::SetCreditCardInfo(&card2, "B Bird", "3111111111111111", "11", "2017");
798  controller()->GetTestingManager()->AddTestingCreditCard(&card2);
799  AutofillProfile full_profile(test::GetFullProfile());
800  controller()->GetTestingManager()->AddTestingProfile(&full_profile);
801
802  const DetailInputs& inputs =
803      controller()->RequestedFieldsForSection(SECTION_CC);
804  const ServerFieldType triggering_type = inputs[0].type;
805  base::string16 value = card1.GetRawInfo(triggering_type);
806  scoped_ptr<AutofillDialogViewTester> view = GetViewTester();
807  view->SetTextContentsOfInput(triggering_type,
808                               value.substr(0, value.size() / 2));
809  view->ActivateInput(triggering_type);
810
811  ASSERT_EQ(triggering_type, controller()->popup_input_type());
812  controller()->DidAcceptSuggestion(base::string16(), 0);
813
814  // All inputs should be filled.
815  AutofillCreditCardWrapper wrapper1(&card1);
816  for (size_t i = 0; i < inputs.size(); ++i) {
817    EXPECT_EQ(wrapper1.GetInfo(AutofillType(inputs[i].type)),
818              view->GetTextContentsOfInput(inputs[i].type));
819  }
820
821  // Try again with different data. Only expiration date and the triggering
822  // input should be overwritten.
823  value = card2.GetRawInfo(triggering_type);
824  view->SetTextContentsOfInput(triggering_type,
825                               value.substr(0, value.size() / 2));
826  view->ActivateInput(triggering_type);
827  ASSERT_EQ(triggering_type, controller()->popup_input_type());
828  controller()->DidAcceptSuggestion(base::string16(), 0);
829
830  AutofillCreditCardWrapper wrapper2(&card2);
831  for (size_t i = 0; i < inputs.size(); ++i) {
832    const ServerFieldType type = inputs[i].type;
833    if (type == triggering_type ||
834        type == CREDIT_CARD_EXP_MONTH ||
835        type == CREDIT_CARD_EXP_4_DIGIT_YEAR) {
836      EXPECT_EQ(wrapper2.GetInfo(AutofillType(type)),
837                view->GetTextContentsOfInput(type));
838    } else if (type == CREDIT_CARD_VERIFICATION_CODE) {
839      EXPECT_TRUE(view->GetTextContentsOfInput(type).empty());
840    } else {
841      EXPECT_EQ(wrapper1.GetInfo(AutofillType(type)),
842                view->GetTextContentsOfInput(type));
843    }
844  }
845
846  // Now fill from a profile. It should not overwrite any CC info.
847  const DetailInputs& billing_inputs =
848      controller()->RequestedFieldsForSection(SECTION_BILLING);
849  const ServerFieldType billing_triggering_type = billing_inputs[0].type;
850  value = full_profile.GetRawInfo(triggering_type);
851  view->SetTextContentsOfInput(billing_triggering_type,
852                               value.substr(0, value.size() / 2));
853  view->ActivateInput(billing_triggering_type);
854
855  ASSERT_EQ(billing_triggering_type, controller()->popup_input_type());
856  controller()->DidAcceptSuggestion(base::string16(), 0);
857
858  for (size_t i = 0; i < inputs.size(); ++i) {
859    const ServerFieldType type = inputs[i].type;
860    if (type == triggering_type ||
861        type == CREDIT_CARD_EXP_MONTH ||
862        type == CREDIT_CARD_EXP_4_DIGIT_YEAR) {
863      EXPECT_EQ(wrapper2.GetInfo(AutofillType(type)),
864                view->GetTextContentsOfInput(type));
865    } else if (type == CREDIT_CARD_VERIFICATION_CODE) {
866      EXPECT_TRUE(view->GetTextContentsOfInput(type).empty());
867    } else {
868      EXPECT_EQ(wrapper1.GetInfo(AutofillType(type)),
869                view->GetTextContentsOfInput(type));
870    }
871  }
872}
873
874IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, ShouldShowErrorBubble) {
875  controller()->set_use_validation(true);
876  EXPECT_TRUE(controller()->ShouldShowErrorBubble());
877
878  CreditCard card(test::GetCreditCard());
879  ASSERT_FALSE(card.IsVerified());
880  controller()->GetTestingManager()->AddTestingCreditCard(&card);
881
882  EXPECT_TRUE(controller()->IsManuallyEditingSection(SECTION_CC));
883  scoped_ptr<AutofillDialogViewTester> view = GetViewTester();
884  view->SetTextContentsOfInput(
885      CREDIT_CARD_NUMBER,
886      card.GetRawInfo(CREDIT_CARD_NUMBER).substr(0, 1));
887
888  view->ActivateInput(CREDIT_CARD_NUMBER);
889  EXPECT_FALSE(controller()->ShouldShowErrorBubble());
890
891  controller()->FocusMoved();
892  EXPECT_TRUE(controller()->ShouldShowErrorBubble());
893
894  EXPECT_CALL(metric_logger(),
895              LogDialogDismissalState(
896                  AutofillMetrics::DIALOG_CANCELED_WITH_INVALID_FIELDS));
897  controller()->Hide();
898}
899
900// Ensure that expired cards trigger invalid suggestions.
901IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, ExpiredCard) {
902  CreditCard verified_card(test::GetCreditCard());
903  verified_card.set_origin("Chrome settings");
904  ASSERT_TRUE(verified_card.IsVerified());
905  controller()->GetTestingManager()->AddTestingCreditCard(&verified_card);
906
907  CreditCard expired_card(test::GetCreditCard());
908  expired_card.set_origin("Chrome settings");
909  expired_card.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2007"));
910  ASSERT_TRUE(expired_card.IsVerified());
911  ASSERT_FALSE(
912      autofill::IsValidCreditCardExpirationDate(
913          expired_card.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR),
914          expired_card.GetRawInfo(CREDIT_CARD_EXP_MONTH),
915          base::Time::Now()));
916  controller()->GetTestingManager()->AddTestingCreditCard(&expired_card);
917
918  ui::MenuModel* model = controller()->MenuModelForSection(SECTION_CC);
919  ASSERT_EQ(4, model->GetItemCount());
920
921  ASSERT_TRUE(model->IsItemCheckedAt(0));
922  EXPECT_FALSE(controller()->IsEditingExistingData(SECTION_CC));
923
924  model->ActivatedAt(1);
925  ASSERT_TRUE(model->IsItemCheckedAt(1));
926  EXPECT_TRUE(controller()->IsEditingExistingData(SECTION_CC));
927}
928
929// Notifications with long message text should not make the dialog bigger.
930IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, LongNotifications) {
931  const gfx::Size no_notification_size = GetViewTester()->GetSize();
932  ASSERT_GT(no_notification_size.width(), 0);
933
934  std::vector<DialogNotification> notifications;
935  notifications.push_back(
936      DialogNotification(DialogNotification::DEVELOPER_WARNING, ASCIIToUTF16(
937          "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do "
938          "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim "
939          "ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut "
940          "aliquip ex ea commodo consequat. Duis aute irure dolor in "
941          "reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla "
942          "pariatur. Excepteur sint occaecat cupidatat non proident, sunt in "
943          "culpa qui officia deserunt mollit anim id est laborum.")));
944  controller()->set_notifications(notifications);
945  controller()->view()->UpdateNotificationArea();
946
947  EXPECT_EQ(no_notification_size.width(),
948            GetViewTester()->GetSize().width());
949}
950
951IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AutocompleteEvent) {
952  AutofillDialogControllerImpl* controller =
953      SetUpHtmlAndInvoke("<input autocomplete='cc-name'>");
954  ASSERT_TRUE(controller);
955
956  AddCreditcardToProfile(controller->profile(), test::GetVerifiedCreditCard());
957  AddAutofillProfileToProfile(controller->profile(),
958                              test::GetVerifiedProfile());
959
960  scoped_ptr<AutofillDialogViewTester> view =
961      AutofillDialogViewTester::For(
962          static_cast<TestAutofillDialogController*>(controller)->view());
963  view->SetTextContentsOfSuggestionInput(SECTION_CC, ASCIIToUTF16("123"));
964  view->SubmitForTesting();
965  ExpectDomMessage("success");
966}
967
968IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
969                       AutocompleteErrorEventReasonInvalid) {
970  AutofillDialogControllerImpl* controller =
971      SetUpHtmlAndInvoke("<input autocomplete='cc-name' pattern='.*zebra.*'>");
972  ASSERT_TRUE(controller);
973
974  const CreditCard& credit_card = test::GetVerifiedCreditCard();
975  ASSERT_TRUE(
976      credit_card.GetRawInfo(CREDIT_CARD_NAME).find(ASCIIToUTF16("zebra")) ==
977          base::string16::npos);
978  AddCreditcardToProfile(controller->profile(), credit_card);
979  AddAutofillProfileToProfile(controller->profile(),
980                              test::GetVerifiedProfile());
981
982  scoped_ptr<AutofillDialogViewTester> view =
983      AutofillDialogViewTester::For(
984          static_cast<TestAutofillDialogController*>(controller)->view());
985  view->SetTextContentsOfSuggestionInput(SECTION_CC, ASCIIToUTF16("123"));
986  view->SubmitForTesting();
987  ExpectDomMessage("error: invalid");
988
989  int invalid_count = -1;
990  ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
991      GetRenderViewHost(), "send(invalidEvents.length);", &invalid_count));
992  EXPECT_EQ(1, invalid_count);
993
994  std::string invalid_type;
995  ASSERT_TRUE(content::ExecuteScriptAndExtractString(
996      GetRenderViewHost(),
997      "send(invalidEvents[0].target.autocomplete);",
998      &invalid_type));
999  EXPECT_EQ("cc-name", invalid_type);
1000}
1001
1002IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
1003                       AutocompleteErrorEventReasonCancel) {
1004  AutofillDialogControllerImpl* controller =
1005      SetUpHtmlAndInvoke("<input autocomplete='cc-name'>");
1006  ASSERT_TRUE(controller);
1007  AutofillDialogViewTester::For(
1008      static_cast<TestAutofillDialogController*>(controller)->view())->
1009          CancelForTesting();
1010  ExpectDomMessage("error: cancel");
1011}
1012
1013// http://crbug.com/318526
1014#if defined(OS_MACOSX)
1015#define MAYBE_ErrorWithFrameNavigation DISABLED_ErrorWithFrameNavigation
1016#else
1017#define MAYBE_ErrorWithFrameNavigation ErrorWithFrameNavigation
1018#endif
1019IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
1020                       MAYBE_ErrorWithFrameNavigation) {
1021  AutofillDialogControllerImpl* controller =
1022      SetUpHtmlAndInvoke("<input autocomplete='cc-name'>");
1023  ASSERT_TRUE(controller);
1024
1025  std::string unused;
1026  ASSERT_TRUE(content::ExecuteScriptAndExtractString(GetRenderViewHost(),
1027                                                     "loadIframe();",
1028                                                     &unused));
1029  ExpectDomMessage("iframe loaded");
1030
1031  AutofillDialogViewTester::For(
1032      static_cast<TestAutofillDialogController*>(controller)->view())->
1033          CancelForTesting();
1034  ExpectDomMessage("error: cancel");
1035}
1036
1037IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, NoCvcSegfault) {
1038  controller()->set_use_validation(true);
1039
1040  CreditCard credit_card(test::GetVerifiedCreditCard());
1041  controller()->GetTestingManager()->AddTestingCreditCard(&credit_card);
1042  EXPECT_FALSE(controller()->IsEditingExistingData(SECTION_CC));
1043
1044  ASSERT_NO_FATAL_FAILURE(GetViewTester()->SubmitForTesting());
1045}
1046
1047// Flaky on Win7, WinXP, and Win Aura.  http://crbug.com/270314.
1048#if defined(OS_WIN)
1049#define MAYBE_PreservedSections DISABLED_PreservedSections
1050#else
1051#define MAYBE_PreservedSections PreservedSections
1052#endif
1053IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, MAYBE_PreservedSections) {
1054  controller()->set_use_validation(true);
1055
1056  scoped_ptr<AutofillDialogViewTester> view = GetViewTester();
1057  view->SetTextContentsOfInput(CREDIT_CARD_NUMBER,
1058                               ASCIIToUTF16("4111111111111111"));
1059
1060  // Create some invalid, manually inputted shipping data.
1061  view->SetTextContentsOfInput(ADDRESS_HOME_ZIP, ASCIIToUTF16("shipping zip"));
1062
1063  // Switch to Wallet by simulating a successful server response.
1064  controller()->OnDidFetchWalletCookieValue(std::string());
1065  controller()->OnDidGetWalletItems(
1066      wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED));
1067  ASSERT_TRUE(controller()->IsPayingWithWallet());
1068
1069  // The valid data should be preserved.
1070  EXPECT_EQ(ASCIIToUTF16("4111111111111111"),
1071            view->GetTextContentsOfInput(CREDIT_CARD_NUMBER));
1072
1073  // The invalid data should be dropped.
1074  EXPECT_TRUE(view->GetTextContentsOfInput(ADDRESS_HOME_ZIP).empty());
1075
1076  // Switch back to Autofill.
1077  ui::MenuModel* account_chooser = controller()->MenuModelForAccountChooser();
1078  account_chooser->ActivatedAt(account_chooser->GetItemCount() - 1);
1079  ASSERT_FALSE(controller()->IsPayingWithWallet());
1080
1081  // The valid data should still be preserved when switched back.
1082  EXPECT_EQ(ASCIIToUTF16("4111111111111111"),
1083            view->GetTextContentsOfInput(CREDIT_CARD_NUMBER));
1084}
1085
1086IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
1087                       GeneratedCardLastFourAfterVerifyCvv) {
1088  controller()->OnDidFetchWalletCookieValue(std::string());
1089
1090  scoped_ptr<wallet::WalletItems> wallet_items =
1091      wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
1092  wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
1093  wallet_items->AddAddress(wallet::GetTestShippingAddress());
1094
1095  base::string16 last_four =
1096      wallet_items->instruments()[0]->TypeAndLastFourDigits();
1097  controller()->OnDidGetWalletItems(wallet_items.Pass());
1098
1099  scoped_ptr<AutofillDialogViewTester> test_view = GetViewTester();
1100  EXPECT_FALSE(test_view->IsShowingOverlay());
1101  EXPECT_CALL(*controller(), LoadRiskFingerprintData());
1102  controller()->OnAccept();
1103  EXPECT_TRUE(test_view->IsShowingOverlay());
1104
1105  EXPECT_CALL(*controller()->GetTestingWalletClient(), GetFullWallet(_));
1106  scoped_ptr<risk::Fingerprint> fingerprint(new risk::Fingerprint());
1107  fingerprint->mutable_machine_characteristics()->mutable_screen_size()->
1108      set_width(1024);
1109  controller()->OnDidLoadRiskFingerprintData(fingerprint.Pass());
1110
1111  controller()->OnDidGetFullWallet(
1112      wallet::GetTestFullWalletWithRequiredActions(
1113          std::vector<wallet::RequiredAction>(1, wallet::VERIFY_CVV)));
1114
1115  ASSERT_TRUE(controller()->IsSubmitPausedOn(wallet::VERIFY_CVV));
1116
1117  std::string fake_cvc("123");
1118  test_view->SetTextContentsOfSuggestionInput(SECTION_CC_BILLING,
1119                                              ASCIIToUTF16(fake_cvc));
1120
1121  EXPECT_FALSE(test_view->IsShowingOverlay());
1122  EXPECT_CALL(*controller()->GetTestingWalletClient(),
1123              AuthenticateInstrument(_, fake_cvc));
1124  controller()->OnAccept();
1125  EXPECT_TRUE(test_view->IsShowingOverlay());
1126
1127  EXPECT_CALL(metric_logger(),
1128              LogDialogDismissalState(
1129                  AutofillMetrics::DIALOG_ACCEPTED_EXISTING_WALLET_DATA));
1130
1131  EXPECT_CALL(*controller()->GetTestingWalletClient(), GetFullWallet(_));
1132  controller()->OnDidAuthenticateInstrument(true);
1133  controller()->OnDidGetFullWallet(wallet::GetTestFullWallet());
1134  controller()->ForceFinishSubmit();
1135
1136  RunMessageLoop();
1137
1138  EXPECT_EQ(1, test_generated_bubble_controller()->bubbles_shown());
1139  EXPECT_EQ(last_four, test_generated_bubble_controller()->backing_card_name());
1140}
1141
1142// Simulates the user signing in to the dialog from the inline web contents.
1143IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, SimulateSuccessfulSignIn) {
1144#if defined(OS_WIN)
1145  // TODO(msw): Fix potential flakiness on Windows XP; http://crbug.com/333641
1146  if (base::win::GetVersion() <= base::win::VERSION_XP)
1147    return;
1148#endif
1149  browser()->profile()->GetPrefs()->SetBoolean(
1150      ::prefs::kAutofillDialogPayWithoutWallet,
1151      true);
1152
1153  InitializeController();
1154
1155  controller()->OnDidFetchWalletCookieValue(std::string());
1156  controller()->OnDidGetWalletItems(
1157      wallet::GetTestWalletItemsWithRequiredAction(wallet::GAIA_AUTH));
1158
1159  NavEntryCommittedObserver sign_in_page_observer(
1160      controller()->SignInUrl(),
1161      content::NotificationService::AllSources());
1162
1163  // Simulate a user clicking "Sign In" (which loads dialog's web contents).
1164  controller()->SignInLinkClicked();
1165  EXPECT_TRUE(controller()->ShouldShowSignInWebView());
1166
1167  scoped_ptr<AutofillDialogViewTester> view = GetViewTester();
1168  content::WebContents* sign_in_contents = view->GetSignInWebContents();
1169  ASSERT_TRUE(sign_in_contents);
1170
1171  sign_in_page_observer.Wait();
1172
1173  NavEntryCommittedObserver continue_page_observer(
1174      wallet::GetSignInContinueUrl(),
1175      content::NotificationService::AllSources());
1176
1177  EXPECT_EQ(sign_in_contents->GetURL(), controller()->SignInUrl());
1178
1179  AccountChooserModel* account_chooser_model =
1180      controller()->AccountChooserModelForTesting();
1181  EXPECT_FALSE(account_chooser_model->WalletIsSelected());
1182
1183  content::OpenURLParams params(wallet::GetSignInContinueUrl(),
1184                                content::Referrer(),
1185                                CURRENT_TAB,
1186                                content::PAGE_TRANSITION_LINK,
1187                                true);
1188
1189  sign_in_contents->GetDelegate()->OpenURLFromTab(sign_in_contents, params);
1190
1191  EXPECT_CALL(*controller()->GetTestingWalletClient(), GetWalletItems());
1192  continue_page_observer.Wait();
1193  content::RunAllPendingInMessageLoop();
1194
1195  EXPECT_FALSE(controller()->ShouldShowSignInWebView());
1196
1197  scoped_ptr<wallet::WalletItems> wallet_items =
1198      wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
1199  wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
1200  controller()->OnDidGetWalletItems(wallet_items.Pass());
1201
1202  // Wallet should now be selected and Chrome shouldn't have crashed (which can
1203  // happen if the WebContents is deleted while proccessing a nav entry commit).
1204  EXPECT_TRUE(account_chooser_model->WalletIsSelected());
1205  EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_CC_BILLING));
1206  EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_SHIPPING));
1207
1208  EXPECT_CALL(metric_logger(),
1209              LogDialogDismissalState(
1210                  AutofillMetrics::DIALOG_ACCEPTED_EXISTING_WALLET_DATA));
1211  view->SubmitForTesting();
1212  controller()->OnDidGetFullWallet(wallet::GetTestFullWallet());
1213  controller()->ForceFinishSubmit();
1214}
1215
1216IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AddAccount) {
1217#if defined(OS_WIN)
1218  // TODO(msw): Fix potential flakiness on Windows XP; http://crbug.com/333641
1219  if (base::win::GetVersion() <= base::win::VERSION_XP)
1220    return;
1221#endif
1222
1223  controller()->OnDidFetchWalletCookieValue(std::string());
1224  std::vector<std::string> usernames;
1225  usernames.push_back("user_0@example.com");
1226  controller()->OnDidGetWalletItems(
1227      wallet::GetTestWalletItemsWithUsers(usernames, 0));
1228
1229  // Switch to Autofill.
1230  AccountChooserModel* account_chooser_model =
1231      controller()->AccountChooserModelForTesting();
1232  account_chooser_model->ActivatedAt(
1233      account_chooser_model->GetItemCount() - 1);
1234
1235  NavEntryCommittedObserver sign_in_page_observer(
1236      controller()->SignInUrl(),
1237      content::NotificationService::AllSources());
1238
1239  // Simulate a user clicking "add account".
1240  account_chooser_model->ActivatedAt(
1241      account_chooser_model->GetItemCount() - 2);
1242  EXPECT_TRUE(controller()->ShouldShowSignInWebView());
1243
1244  scoped_ptr<AutofillDialogViewTester> view = GetViewTester();
1245  content::WebContents* sign_in_contents = view->GetSignInWebContents();
1246  ASSERT_TRUE(sign_in_contents);
1247
1248  sign_in_page_observer.Wait();
1249
1250  NavEntryCommittedObserver continue_page_observer(
1251      wallet::GetSignInContinueUrl(),
1252      content::NotificationService::AllSources());
1253
1254  EXPECT_EQ(sign_in_contents->GetURL(), controller()->SignInUrl());
1255
1256  EXPECT_FALSE(account_chooser_model->WalletIsSelected());
1257
1258  // User signs into new account, account 3.
1259  controller()->set_sign_in_user_index(3U);
1260  content::OpenURLParams params(wallet::GetSignInContinueUrl(),
1261                                content::Referrer(),
1262                                CURRENT_TAB,
1263                                content::PAGE_TRANSITION_LINK,
1264                                true);
1265  sign_in_contents->GetDelegate()->OpenURLFromTab(sign_in_contents, params);
1266
1267  EXPECT_CALL(*controller()->GetTestingWalletClient(), GetWalletItems());
1268  continue_page_observer.Wait();
1269  content::RunAllPendingInMessageLoop();
1270
1271  EXPECT_FALSE(controller()->ShouldShowSignInWebView());
1272  EXPECT_EQ(3U, controller()->GetTestingWalletClient()->user_index());
1273
1274  usernames.push_back("user_1@example.com");
1275  usernames.push_back("user_2@example.com");
1276  usernames.push_back("user_3@example.com");
1277  usernames.push_back("user_4@example.com");
1278  // Curveball: wallet items comes back with user 4 selected.
1279  controller()->OnDidGetWalletItems(
1280      wallet::GetTestWalletItemsWithUsers(usernames, 4U));
1281
1282  EXPECT_TRUE(account_chooser_model->WalletIsSelected());
1283  EXPECT_EQ(4U, account_chooser_model->GetActiveWalletAccountIndex());
1284  EXPECT_EQ(4U, controller()->GetTestingWalletClient()->user_index());
1285}
1286
1287// Verify that filling a form works correctly, including filling the CVC when
1288// that is requested separately.
1289IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
1290                       FillFormIncludesCVC) {
1291  AutofillDialogControllerImpl* controller =
1292      SetUpHtmlAndInvoke("<input autocomplete='cc-csc'>");
1293  ASSERT_TRUE(controller);
1294
1295  AddCreditcardToProfile(controller->profile(), test::GetVerifiedCreditCard());
1296  AddAutofillProfileToProfile(controller->profile(),
1297                              test::GetVerifiedProfile());
1298
1299  scoped_ptr<AutofillDialogViewTester> view =
1300      AutofillDialogViewTester::For(
1301          static_cast<TestAutofillDialogController*>(controller)->view());
1302  view->SetTextContentsOfSuggestionInput(SECTION_CC, ASCIIToUTF16("123"));
1303  view->SubmitForTesting();
1304  ExpectDomMessage("success");
1305  EXPECT_EQ("123", GetValueForHTMLFieldOfType("cc-csc"));
1306}
1307
1308IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AddNewClearsComboboxes) {
1309  // Ensure the input under test is a combobox.
1310  ASSERT_TRUE(
1311      controller()->ComboboxModelForAutofillType(CREDIT_CARD_EXP_MONTH));
1312
1313  // Set up an expired card.
1314  CreditCard card;
1315  test::SetCreditCardInfo(&card, "Roy Demeo", "4111111111111111", "8", "2013");
1316  card.set_origin("Chrome settings");
1317  ASSERT_TRUE(card.IsVerified());
1318
1319  // Add the card and check that there's a menu for that section.
1320  controller()->GetTestingManager()->AddTestingCreditCard(&card);
1321  ASSERT_TRUE(controller()->MenuModelForSection(SECTION_CC));
1322
1323  // Select the invalid, suggested card from the menu.
1324  controller()->MenuModelForSection(SECTION_CC)->ActivatedAt(0);
1325  EXPECT_TRUE(controller()->IsEditingExistingData(SECTION_CC));
1326
1327  // Get the contents of the combobox of the credit card's expiration month.
1328  scoped_ptr<AutofillDialogViewTester> view = GetViewTester();
1329  base::string16 cc_exp_month_text =
1330      view->GetTextContentsOfInput(CREDIT_CARD_EXP_MONTH);
1331
1332  // Select "New X..." from the suggestion menu to clear the section's inputs.
1333  controller()->MenuModelForSection(SECTION_CC)->ActivatedAt(1);
1334  EXPECT_FALSE(controller()->IsEditingExistingData(SECTION_CC));
1335
1336  // Ensure that the credit card expiration month has changed.
1337  EXPECT_NE(cc_exp_month_text,
1338            view->GetTextContentsOfInput(CREDIT_CARD_EXP_MONTH));
1339}
1340
1341IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, TabOpensToJustRight) {
1342  ASSERT_TRUE(browser()->is_type_tabbed());
1343
1344  // Tabs should currently be: / rAc() \.
1345  content::WebContents* dialog_invoker = controller()->GetWebContents();
1346  EXPECT_EQ(dialog_invoker, GetActiveWebContents());
1347
1348  TabStripModel* tab_strip = browser()->tab_strip_model();
1349  ASSERT_EQ(1, tab_strip->count());
1350  EXPECT_EQ(0, tab_strip->GetIndexOfWebContents(dialog_invoker));
1351
1352  // Open a tab to about:blank in the background at the end of the tab strip.
1353  chrome::AddTabAt(browser(), GURL(), -1, false);
1354  // Tabs should now be: / rAc() \/ blank \.
1355  EXPECT_EQ(2, tab_strip->count());
1356  EXPECT_EQ(0, tab_strip->active_index());
1357  EXPECT_EQ(dialog_invoker, GetActiveWebContents());
1358
1359  content::WebContents* blank_tab = tab_strip->GetWebContentsAt(1);
1360
1361  // Simulate clicking "Manage X...".
1362  controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(2);
1363  // Tab should now be: / rAc() \/ manage 1 \/ blank \.
1364  EXPECT_EQ(3, tab_strip->count());
1365  int dialog_index = tab_strip->GetIndexOfWebContents(dialog_invoker);
1366  EXPECT_EQ(0, dialog_index);
1367  EXPECT_EQ(1, tab_strip->active_index());
1368  EXPECT_EQ(2, tab_strip->GetIndexOfWebContents(blank_tab));
1369
1370  content::WebContents* first_manage_tab = tab_strip->GetWebContentsAt(1);
1371
1372  // Re-activate the dialog's tab (like a user would have to).
1373  tab_strip->ActivateTabAt(dialog_index, true);
1374  EXPECT_EQ(dialog_invoker, GetActiveWebContents());
1375
1376  // Simulate clicking "Manage X...".
1377  controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(2);
1378  // Tabs should now be: / rAc() \/ manage 2 \/ manage 1 \/ blank \.
1379  EXPECT_EQ(4, tab_strip->count());
1380  EXPECT_EQ(0, tab_strip->GetIndexOfWebContents(dialog_invoker));
1381  EXPECT_EQ(1, tab_strip->active_index());
1382  EXPECT_EQ(2, tab_strip->GetIndexOfWebContents(first_manage_tab));
1383  EXPECT_EQ(3, tab_strip->GetIndexOfWebContents(blank_tab));
1384}
1385
1386IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
1387                       SignInWebViewOpensLinksInNewTab) {
1388  controller()->OnDidFetchWalletCookieValue(std::string());
1389  controller()->OnDidGetWalletItems(
1390      wallet::GetTestWalletItemsWithRequiredAction(wallet::GAIA_AUTH));
1391
1392  NavEntryCommittedObserver sign_in_page_observer(
1393      controller()->SignInUrl(),
1394      content::NotificationService::AllSources());
1395
1396  controller()->SignInLinkClicked();
1397
1398  content::WebContents* sign_in_contents =
1399      GetViewTester()->GetSignInWebContents();
1400  ASSERT_TRUE(sign_in_contents);
1401
1402  sign_in_page_observer.Wait();
1403
1404  content::OpenURLParams params(GURL("http://google.com"),
1405                                content::Referrer(),
1406                                CURRENT_TAB,
1407                                content::PAGE_TRANSITION_LINK,
1408                                true);
1409  params.user_gesture = true;
1410
1411  int num_tabs = browser()->tab_strip_model()->count();
1412  sign_in_contents->GetDelegate()->OpenURLFromTab(sign_in_contents, params);
1413  EXPECT_EQ(num_tabs + 1, browser()->tab_strip_model()->count());
1414}
1415
1416IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, RefreshOnManageTabClose) {
1417  ASSERT_TRUE(browser()->is_type_tabbed());
1418
1419  // GetWalletItems() is called when controller() is created in SetUp().
1420  EXPECT_CALL(*controller()->GetTestingWalletClient(), GetWalletItems());
1421  controller()->OnDidFetchWalletCookieValue(std::string());
1422  controller()->OnDidGetWalletItems(
1423      wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED));
1424
1425  content::WebContents* dialog_invoker = controller()->GetWebContents();
1426  ChromeAutofillClient::FromWebContents(dialog_invoker)
1427      ->SetDialogControllerForTesting(controller()->AsWeakPtr());
1428
1429  // Open a new tab by selecting "Manage my shipping details..." in Wallet mode.
1430  EXPECT_EQ(1, browser()->tab_strip_model()->count());
1431  controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(2);
1432  EXPECT_EQ(2, browser()->tab_strip_model()->count());
1433  ASSERT_NE(dialog_invoker, GetActiveWebContents());
1434
1435  // Closing the tab opened by "Manage my shipping details..." should refresh
1436  // the dialog.
1437  controller()->ClearLastWalletItemsFetchTimestampForTesting();
1438  EXPECT_CALL(*controller()->GetTestingWalletClient(), GetWalletItems());
1439  GetActiveWebContents()->Close();
1440}
1441
1442// Changes from Wallet to Autofill and verifies that the combined billing/cc
1443// sections are showing (or not) at the correct times.
1444IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
1445                       ChangingDataSourceShowsCorrectSections) {
1446  scoped_ptr<AutofillDialogViewTester> view = GetViewTester();
1447  EXPECT_TRUE(view->IsShowingSection(SECTION_CC));
1448  EXPECT_TRUE(view->IsShowingSection(SECTION_BILLING));
1449  EXPECT_FALSE(view->IsShowingSection(SECTION_CC_BILLING));
1450
1451  // Switch the dialog to paying with Wallet.
1452  controller()->OnDidFetchWalletCookieValue(std::string());
1453  controller()->OnDidGetWalletItems(
1454      wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED));
1455  ASSERT_TRUE(controller()->IsPayingWithWallet());
1456
1457  EXPECT_FALSE(view->IsShowingSection(SECTION_CC));
1458  EXPECT_FALSE(view->IsShowingSection(SECTION_BILLING));
1459  EXPECT_TRUE(view->IsShowingSection(SECTION_CC_BILLING));
1460
1461  // Now switch back to Autofill to ensure this direction works as well.
1462  ui::MenuModel* account_chooser = controller()->MenuModelForAccountChooser();
1463  account_chooser->ActivatedAt(account_chooser->GetItemCount() - 1);
1464
1465  EXPECT_TRUE(view->IsShowingSection(SECTION_CC));
1466  EXPECT_TRUE(view->IsShowingSection(SECTION_BILLING));
1467  EXPECT_FALSE(view->IsShowingSection(SECTION_CC_BILLING));
1468}
1469
1470IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
1471                       DoesWorkOnHttpWithFlag) {
1472  net::SpawnedTestServer http_server(
1473      net::SpawnedTestServer::TYPE_HTTP,
1474      net::SpawnedTestServer::kLocalhost,
1475      base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1476  ASSERT_TRUE(http_server.Start());
1477  EXPECT_TRUE(RunTestPage(http_server));
1478}
1479
1480// Like the parent test, but doesn't add the --reduce-security-for-testing flag.
1481class AutofillDialogControllerSecurityTest :
1482    public AutofillDialogControllerTest {
1483 public:
1484  AutofillDialogControllerSecurityTest() {}
1485  virtual ~AutofillDialogControllerSecurityTest() {}
1486
1487  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
1488    CHECK(!command_line->HasSwitch(::switches::kReduceSecurityForTesting));
1489  }
1490
1491  typedef net::BaseTestServer::SSLOptions SSLOptions;
1492
1493 private:
1494  DISALLOW_COPY_AND_ASSIGN(AutofillDialogControllerSecurityTest);
1495};
1496
1497IN_PROC_BROWSER_TEST_F(AutofillDialogControllerSecurityTest,
1498                       DoesntWorkOnHttp) {
1499  net::SpawnedTestServer http_server(
1500      net::SpawnedTestServer::TYPE_HTTP,
1501      net::SpawnedTestServer::kLocalhost,
1502      base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1503  ASSERT_TRUE(http_server.Start());
1504  EXPECT_FALSE(RunTestPage(http_server));
1505}
1506
1507IN_PROC_BROWSER_TEST_F(AutofillDialogControllerSecurityTest,
1508                       DoesWorkOnHttpWithFlags) {
1509  net::SpawnedTestServer https_server(
1510      net::SpawnedTestServer::TYPE_HTTPS,
1511      SSLOptions(SSLOptions::CERT_OK),
1512      base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1513  ASSERT_TRUE(https_server.Start());
1514  EXPECT_TRUE(RunTestPage(https_server));
1515}
1516
1517IN_PROC_BROWSER_TEST_F(AutofillDialogControllerSecurityTest,
1518                       DoesntWorkOnBrokenHttps) {
1519  net::SpawnedTestServer https_server(
1520      net::SpawnedTestServer::TYPE_HTTPS,
1521      SSLOptions(SSLOptions::CERT_EXPIRED),
1522      base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1523  ASSERT_TRUE(https_server.Start());
1524  EXPECT_FALSE(RunTestPage(https_server));
1525}
1526
1527IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
1528                       CountryChangeRebuildsSection) {
1529  EXPECT_FALSE(SectionHasField(SECTION_BILLING, ADDRESS_BILLING_SORTING_CODE));
1530  EXPECT_FALSE(SectionHasField(SECTION_SHIPPING, ADDRESS_HOME_SORTING_CODE));
1531
1532  // Select "Add new shipping address...".
1533  controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(1);
1534
1535  // Add some valid user input that should be preserved when country changes.
1536  scoped_ptr<AutofillDialogViewTester> view = GetViewTester();
1537  view->SetTextContentsOfInput(NAME_FULL, ASCIIToUTF16("B. Loblaw"));
1538
1539  // Change both sections' countries.
1540  view->SetTextContentsOfInput(ADDRESS_BILLING_COUNTRY, ASCIIToUTF16("France"));
1541  view->ActivateInput(ADDRESS_BILLING_COUNTRY);
1542  view->SetTextContentsOfInput(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("Belarus"));
1543  view->ActivateInput(ADDRESS_HOME_COUNTRY);
1544
1545  // Verify the name is still there.
1546  EXPECT_EQ(ASCIIToUTF16("B. Loblaw"), view->GetTextContentsOfInput(NAME_FULL));
1547
1548  EXPECT_TRUE(SectionHasField(SECTION_BILLING, ADDRESS_BILLING_SORTING_CODE));
1549  EXPECT_TRUE(SectionHasField(SECTION_SHIPPING, ADDRESS_HOME_SORTING_CODE));
1550}
1551
1552// Changing the data source to or from Wallet preserves the shipping country,
1553// but not the billing country because Wallet only supports US billing
1554// addresses.
1555IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
1556                       ChangingDataSourcePreservesCountry) {
1557  InitializeControllerWithoutShowing();
1558  controller()->GetTestingManager()->set_default_country_code("CA");
1559  controller()->Show();
1560  CycleRunLoops();
1561
1562  AutofillProfile verified_profile(test::GetVerifiedProfile());
1563  controller()->GetTestingManager()->AddTestingProfile(&verified_profile);
1564
1565  CreditCard verified_card(test::GetVerifiedCreditCard());
1566  controller()->GetTestingManager()->AddTestingCreditCard(&verified_card);
1567  EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_SHIPPING));
1568
1569  controller()->OnDidFetchWalletCookieValue(std::string());
1570  scoped_ptr<wallet::WalletItems> items =
1571      wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED);
1572  items->AddAccount(wallet::GetTestGaiaAccount());
1573  items->AddInstrument(wallet::GetTestMaskedInstrument());
1574  items->AddAddress(wallet::GetTestShippingAddress());
1575  controller()->OnDidGetWalletItems(items.Pass());
1576
1577  EXPECT_TRUE(controller()->IsPayingWithWallet());
1578
1579  // Select "Add new shipping address...".
1580  controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(2);
1581  EXPECT_TRUE(controller()->IsManuallyEditingSection(SECTION_SHIPPING));
1582
1583  // Default shipping country matches PDM's default, but default billing is
1584  // always US in Wallet mode.
1585  scoped_ptr<AutofillDialogViewTester> view = GetViewTester();
1586  ASSERT_EQ(ASCIIToUTF16("Canada"),
1587            view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY));
1588  ASSERT_EQ(ASCIIToUTF16("United States"),
1589            view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY));
1590
1591  // Switch the shipping country.
1592  view->SetTextContentsOfInput(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("Belarus"));
1593  EXPECT_EQ(ASCIIToUTF16("Belarus"),
1594            view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY));
1595  view->ActivateInput(ADDRESS_HOME_COUNTRY);
1596
1597  // Switch to using Autofill instead of Wallet.
1598  ui::MenuModel* account_chooser = controller()->MenuModelForAccountChooser();
1599  account_chooser->ActivatedAt(account_chooser->GetItemCount() - 1);
1600
1601  EXPECT_FALSE(controller()->IsPayingWithWallet());
1602
1603  // Shipping country should have stayed the same.
1604  EXPECT_EQ(ASCIIToUTF16("Belarus"),
1605            view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY));
1606  ASSERT_TRUE(SectionHasField(SECTION_SHIPPING, ADDRESS_HOME_SORTING_CODE));
1607
1608  controller()->MenuModelForSection(SECTION_BILLING)->ActivatedAt(1);
1609  view->SetTextContentsOfInput(ADDRESS_BILLING_COUNTRY,
1610                               ASCIIToUTF16("Belarus"));
1611  view->ActivateInput(ADDRESS_BILLING_COUNTRY);
1612  EXPECT_EQ(ASCIIToUTF16("Belarus"),
1613            view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY));
1614  ASSERT_TRUE(SectionHasField(SECTION_BILLING, ADDRESS_BILLING_SORTING_CODE));
1615
1616  // Switch back to Wallet. Country should go back to US.
1617  account_chooser->ActivatedAt(0);
1618  EXPECT_EQ(ASCIIToUTF16("United States"),
1619            view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY));
1620  ASSERT_FALSE(
1621      SectionHasField(SECTION_CC_BILLING, ADDRESS_BILLING_SORTING_CODE));
1622
1623  // Make sure shipping is still on Belarus.
1624  EXPECT_EQ(ASCIIToUTF16("Belarus"),
1625            view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY));
1626  ASSERT_TRUE(SectionHasField(SECTION_SHIPPING, ADDRESS_HOME_SORTING_CODE));
1627}
1628
1629IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AddNewResetsCountry) {
1630  AutofillProfile verified_profile(test::GetVerifiedProfile());
1631  controller()->GetTestingManager()->AddTestingProfile(&verified_profile);
1632
1633  // Select "Add new billing/shipping address...".
1634  controller()->MenuModelForSection(SECTION_BILLING)->ActivatedAt(1);
1635  controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(2);
1636
1637  scoped_ptr<AutofillDialogViewTester> view = GetViewTester();
1638  ASSERT_EQ(ASCIIToUTF16("United States"),
1639            view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY));
1640  ASSERT_EQ(ASCIIToUTF16("United States"),
1641            view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY));
1642
1643  // Switch both billing and shipping countries.
1644  view->SetTextContentsOfInput(ADDRESS_BILLING_COUNTRY, ASCIIToUTF16("Brazil"));
1645  view->ActivateInput(ADDRESS_BILLING_COUNTRY);
1646  view->SetTextContentsOfInput(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("France"));
1647  view->ActivateInput(ADDRESS_HOME_COUNTRY);
1648
1649  // Select "Add new billing/shipping address...".
1650  controller()->MenuModelForSection(SECTION_BILLING)->ActivatedAt(1);
1651  controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(2);
1652
1653  EXPECT_EQ(ASCIIToUTF16("United States"),
1654            view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY));
1655  EXPECT_EQ(ASCIIToUTF16("United States"),
1656            view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY));
1657}
1658
1659IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
1660                       FillingFormRebuildsInputs) {
1661  AutofillProfile full_profile(test::GetFullProfile());
1662  full_profile.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("DE"));
1663  controller()->GetTestingManager()->AddTestingProfile(&full_profile);
1664
1665  // Select "Add new shipping address...".
1666  controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(1);
1667
1668  scoped_ptr<AutofillDialogViewTester> view = GetViewTester();
1669  ASSERT_EQ(ASCIIToUTF16("United States"),
1670            view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY));
1671  ASSERT_EQ(ASCIIToUTF16("United States"),
1672            view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY));
1673
1674  base::string16 name = full_profile.GetRawInfo(NAME_FULL);
1675  view->SetTextContentsOfInput(NAME_FULL, name.substr(0, name.size() / 2));
1676  view->ActivateInput(NAME_FULL);
1677  ASSERT_EQ(NAME_FULL, controller()->popup_input_type());
1678  controller()->DidAcceptSuggestion(base::string16(), 0);
1679
1680  EXPECT_EQ(ASCIIToUTF16("Germany"),
1681            view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY));
1682  EXPECT_EQ(ASCIIToUTF16("Germany"),
1683            view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY));
1684}
1685
1686IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
1687                       FillingFormPreservesChangedCountry) {
1688  AutofillProfile full_profile(test::GetFullProfile());
1689  full_profile.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("DE"));
1690  controller()->GetTestingManager()->AddTestingProfile(&full_profile);
1691
1692  // Select "Add new shipping address...".
1693  controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(1);
1694
1695  scoped_ptr<AutofillDialogViewTester> view = GetViewTester();
1696  view->SetTextContentsOfInput(ADDRESS_BILLING_COUNTRY, ASCIIToUTF16("France"));
1697  view->ActivateInput(ADDRESS_BILLING_COUNTRY);
1698  view->SetTextContentsOfInput(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("Belarus"));
1699  view->ActivateInput(ADDRESS_HOME_COUNTRY);
1700
1701  base::string16 name = full_profile.GetRawInfo(NAME_FULL);
1702  view->SetTextContentsOfInput(NAME_FULL, name.substr(0, name.size() / 2));
1703  view->ActivateInput(NAME_FULL);
1704  ASSERT_EQ(NAME_FULL, controller()->popup_input_type());
1705  controller()->DidAcceptSuggestion(base::string16(), 0);
1706
1707  EXPECT_EQ(ASCIIToUTF16("France"),
1708            view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY));
1709  EXPECT_EQ(ASCIIToUTF16("Belarus"),
1710            view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY));
1711}
1712
1713IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, RulesLoaded) {
1714  // Select "Add new shipping address...".
1715  controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(1);
1716  controller()->set_use_validation(true);
1717
1718  EXPECT_CALL(*controller()->GetMockValidator(),
1719              ValidateAddress(CountryCodeMatcher("DE"), _, _)).Times(2).
1720              WillOnce(Return(AddressValidator::RULES_NOT_READY));
1721
1722  // Validation should occur on country change and see the rules haven't loaded.
1723  scoped_ptr<AutofillDialogViewTester> view = GetViewTester();
1724  view->SetTextContentsOfInput(ADDRESS_HOME_ZIP, ASCIIToUTF16("123"));
1725  view->SetTextContentsOfInput(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("Germany"));
1726  view->ActivateInput(ADDRESS_HOME_COUNTRY);
1727
1728  // Different country loaded, validation should not occur.
1729  controller()->OnAddressValidationRulesLoaded("FR", true);
1730
1731  // Relevant country loaded, validation should occur.
1732  controller()->OnAddressValidationRulesLoaded("DE", true);
1733
1734  // Relevant country loaded but revalidation already happened, no further
1735  // validation should occur.
1736  controller()->OnAddressValidationRulesLoaded("DE", false);
1737
1738  // Cancelling the dialog causes additional validation to see if the user
1739  // cancelled with invalid fields, so verify and clear here.
1740  testing::Mock::VerifyAndClearExpectations(controller()->GetMockValidator());
1741}
1742
1743}  // namespace autofill
1744