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