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