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