| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/bind.h" |
| #include "base/command_line.h" |
| #include "base/logging.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/prefs/pref_service.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/test/histogram_tester.h" |
| #include "base/time/time.h" |
| #include "chrome/browser/autofill/personal_data_manager_factory.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/signin/account_tracker_service_factory.h" |
| #include "chrome/browser/ui/autofill/account_chooser_model.h" |
| #include "chrome/browser/ui/autofill/autofill_dialog_controller_impl.h" |
| #include "chrome/browser/ui/autofill/autofill_dialog_i18n_input.h" |
| #include "chrome/browser/ui/autofill/autofill_dialog_view.h" |
| #include "chrome/browser/ui/autofill/autofill_dialog_view_tester.h" |
| #include "chrome/browser/ui/autofill/chrome_autofill_client.h" |
| #include "chrome/browser/ui/autofill/data_model_wrapper.h" |
| #include "chrome/browser/ui/autofill/mock_address_validator.h" |
| #include "chrome/browser/ui/autofill/test_generated_credit_card_bubble_controller.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/browser/ui/browser_tabstrip.h" |
| #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/common/url_constants.h" |
| #include "chrome/test/base/in_process_browser_test.h" |
| #include "chrome/test/base/ui_test_utils.h" |
| #include "components/autofill/content/browser/risk/proto/fingerprint.pb.h" |
| #include "components/autofill/content/browser/wallet/gaia_account.h" |
| #include "components/autofill/content/browser/wallet/mock_wallet_client.h" |
| #include "components/autofill/content/browser/wallet/wallet_service_url.h" |
| #include "components/autofill/content/browser/wallet/wallet_test_util.h" |
| #include "components/autofill/core/browser/autofill_metrics.h" |
| #include "components/autofill/core/browser/autofill_test_utils.h" |
| #include "components/autofill/core/browser/test_personal_data_manager.h" |
| #include "components/autofill/core/browser/validation.h" |
| #include "components/autofill/core/common/autofill_switches.h" |
| #include "components/autofill/core/common/form_data.h" |
| #include "components/autofill/core/common/form_field_data.h" |
| #include "components/signin/core/browser/account_tracker_service.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/interstitial_page.h" |
| #include "content/public/browser/navigation_details.h" |
| #include "content/public/browser/navigation_entry.h" |
| #include "content/public/browser/notification_service.h" |
| #include "content/public/browser/notification_types.h" |
| #include "content/public/browser/page_navigator.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/browser/web_contents_delegate.h" |
| #include "content/public/common/content_switches.h" |
| #include "content/public/common/referrer.h" |
| #include "content/public/common/url_constants.h" |
| #include "content/public/test/browser_test_utils.h" |
| #include "content/public/test/test_utils.h" |
| #include "google_apis/gaia/google_service_auth_error.h" |
| #include "net/test/spawned_test_server/spawned_test_server.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/WebKit/public/web/WebInputEvent.h" |
| #include "ui/base/page_transition_types.h" |
| #include "ui/base/window_open_disposition.h" |
| #include "url/gurl.h" |
| |
| #if defined(OS_WIN) |
| #include "base/win/windows_version.h" |
| #elif defined(OS_MACOSX) |
| #include "base/mac/scoped_nsautorelease_pool.h" |
| #include "chrome/browser/ui/cocoa/run_loop_testing.h" |
| #endif |
| |
| using base::ASCIIToUTF16; |
| |
| namespace autofill { |
| |
| namespace { |
| |
| using testing::Return; |
| using testing::_; |
| |
| void MockCallback(AutofillClient::RequestAutocompleteResult, |
| const base::string16& message, |
| const FormStructure*) { |
| } |
| |
| class TestAutofillDialogController : public AutofillDialogControllerImpl { |
| public: |
| TestAutofillDialogController( |
| content::WebContents* contents, |
| const FormData& form_data, |
| scoped_refptr<content::MessageLoopRunner> runner) |
| : AutofillDialogControllerImpl(contents, |
| form_data, |
| form_data.origin, |
| base::Bind(&MockCallback)), |
| mock_wallet_client_( |
| Profile::FromBrowserContext(contents->GetBrowserContext())-> |
| GetRequestContext(), this, form_data.origin), |
| message_loop_runner_(runner), |
| use_validation_(false), |
| sign_in_user_index_(0U), |
| weak_ptr_factory_(this) { |
| Profile* profile = |
| Profile::FromBrowserContext(contents->GetBrowserContext()); |
| test_manager_.Init( |
| NULL, |
| profile->GetPrefs(), |
| AccountTrackerServiceFactory::GetForProfile(profile), |
| false); |
| } |
| |
| ~TestAutofillDialogController() override {} |
| |
| GURL FakeSignInUrl() const { |
| return GURL(chrome::kChromeUIVersionURL); |
| } |
| |
| void ShowSignIn(const GURL& url) override { |
| AutofillDialogControllerImpl::ShowSignIn(FakeSignInUrl()); |
| } |
| |
| void ViewClosed() override { |
| message_loop_runner_->Quit(); |
| AutofillDialogControllerImpl::ViewClosed(); |
| } |
| |
| base::string16 InputValidityMessage( |
| DialogSection section, |
| ServerFieldType type, |
| const base::string16& value) override { |
| if (!use_validation_) |
| return base::string16(); |
| return AutofillDialogControllerImpl::InputValidityMessage( |
| section, type, value); |
| } |
| |
| ValidityMessages InputsAreValid( |
| DialogSection section, |
| const FieldValueMap& inputs) override { |
| if (!use_validation_) |
| return ValidityMessages(); |
| return AutofillDialogControllerImpl::InputsAreValid(section, inputs); |
| } |
| |
| // Saving to Chrome is tested in AutofillDialogControllerImpl unit tests. |
| // TODO(estade): test that the view defaults to saving to Chrome. |
| bool ShouldOfferToSaveInChrome() const override { |
| return true; |
| } |
| |
| void ForceFinishSubmit() { |
| DoFinishSubmit(); |
| } |
| |
| // Increase visibility for testing. |
| using AutofillDialogControllerImpl::view; |
| using AutofillDialogControllerImpl::popup_input_type; |
| |
| MOCK_METHOD0(LoadRiskFingerprintData, void()); |
| |
| std::vector<DialogNotification> CurrentNotifications() override { |
| return notifications_; |
| } |
| |
| void set_notifications(const std::vector<DialogNotification>& notifications) { |
| notifications_ = notifications; |
| } |
| |
| TestPersonalDataManager* GetTestingManager() { |
| return &test_manager_; |
| } |
| |
| MockAddressValidator* GetMockValidator() { |
| return &mock_validator_; |
| } |
| |
| using AutofillDialogControllerImpl::IsEditingExistingData; |
| using AutofillDialogControllerImpl::IsManuallyEditingSection; |
| using AutofillDialogControllerImpl::IsPayingWithWallet; |
| using AutofillDialogControllerImpl::IsSubmitPausedOn; |
| using AutofillDialogControllerImpl::OnDidLoadRiskFingerprintData; |
| using AutofillDialogControllerImpl::AccountChooserModelForTesting; |
| using AutofillDialogControllerImpl:: |
| ClearLastWalletItemsFetchTimestampForTesting; |
| |
| void set_use_validation(bool use_validation) { |
| use_validation_ = use_validation; |
| } |
| |
| base::WeakPtr<TestAutofillDialogController> AsWeakPtr() { |
| return weak_ptr_factory_.GetWeakPtr(); |
| } |
| |
| wallet::MockWalletClient* GetTestingWalletClient() { |
| return &mock_wallet_client_; |
| } |
| |
| void set_sign_in_user_index(size_t sign_in_user_index) { |
| sign_in_user_index_ = sign_in_user_index; |
| } |
| |
| protected: |
| PersonalDataManager* GetManager() const override { |
| return &const_cast<TestAutofillDialogController*>(this)->test_manager_; |
| } |
| |
| AddressValidator* GetValidator() override { |
| return &mock_validator_; |
| } |
| |
| wallet::WalletClient* GetWalletClient() override { |
| return &mock_wallet_client_; |
| } |
| |
| bool IsSignInContinueUrl(const GURL& url, size_t* user_index) const override { |
| *user_index = sign_in_user_index_; |
| return url == wallet::GetSignInContinueUrl(); |
| } |
| |
| private: |
| TestPersonalDataManager test_manager_; |
| testing::NiceMock<MockAddressValidator> mock_validator_; |
| testing::NiceMock<wallet::MockWalletClient> mock_wallet_client_; |
| scoped_refptr<content::MessageLoopRunner> message_loop_runner_; |
| bool use_validation_; |
| |
| // A list of notifications to show in the notification area of the dialog. |
| // This is used to control what |CurrentNotifications()| returns for testing. |
| std::vector<DialogNotification> notifications_; |
| |
| // The user index that is assigned in IsSignInContinueUrl(). |
| size_t sign_in_user_index_; |
| |
| // Allows generation of WeakPtrs, so controller liveness can be tested. |
| base::WeakPtrFactory<TestAutofillDialogController> weak_ptr_factory_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TestAutofillDialogController); |
| }; |
| |
| // This is a copy of ui_test_utils::UrlLoadObserver, except it observes |
| // NAV_ENTRY_COMMITTED instead of LOAD_STOP. This is to match the notification |
| // that AutofillDialogControllerImpl observes. Since NAV_ENTRY_COMMITTED comes |
| // before LOAD_STOP, and the controller deletes the web contents after receiving |
| // the former, we will sometimes fail to observe a LOAD_STOP. |
| // TODO(estade): Should the controller observe LOAD_STOP instead? |
| class NavEntryCommittedObserver : public content::WindowedNotificationObserver { |
| public: |
| NavEntryCommittedObserver(const GURL& url, |
| const content::NotificationSource& source) |
| : WindowedNotificationObserver(content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| source), |
| url_(url) {} |
| |
| ~NavEntryCommittedObserver() override {} |
| |
| // content::NotificationObserver: |
| void Observe(int type, |
| const content::NotificationSource& source, |
| const content::NotificationDetails& details) override { |
| content::LoadCommittedDetails* load_details = |
| content::Details<content::LoadCommittedDetails>(details).ptr(); |
| if (load_details->entry->GetVirtualURL() != url_) |
| return; |
| |
| WindowedNotificationObserver::Observe(type, source, details); |
| } |
| |
| private: |
| GURL url_; |
| |
| DISALLOW_COPY_AND_ASSIGN(NavEntryCommittedObserver); |
| }; |
| |
| } // namespace |
| |
| class AutofillDialogControllerTest : public InProcessBrowserTest { |
| public: |
| AutofillDialogControllerTest() : controller_(NULL) {} |
| ~AutofillDialogControllerTest() override {} |
| |
| void SetUpCommandLine(base::CommandLine* command_line) override { |
| command_line->AppendSwitch(::switches::kReduceSecurityForTesting); |
| } |
| |
| void SetUpOnMainThread() override { |
| autofill::test::DisableSystemServices(browser()->profile()->GetPrefs()); |
| InitializeController(); |
| } |
| |
| protected: |
| bool SectionHasField(DialogSection section, ServerFieldType type) { |
| const DetailInputs& fields = |
| controller()->RequestedFieldsForSection(section); |
| for (size_t i = 0; i < fields.size(); ++i) { |
| if (type == fields[i].type) |
| return true; |
| } |
| return false; |
| } |
| |
| // A helper function that cycles the MessageLoop, and on Mac, the Cocoa run |
| // loop. It also drains the NSAutoreleasePool. |
| void CycleRunLoops() { |
| content::RunAllPendingInMessageLoop(); |
| #if defined(OS_MACOSX) |
| chrome::testing::NSRunLoopRunAllPending(); |
| AutoreleasePool()->Recycle(); |
| #endif |
| } |
| |
| void InitializeControllerWithoutShowing() { |
| if (controller_) |
| controller_->Hide(); |
| |
| FormData form; |
| form.name = ASCIIToUTF16("TestForm"); |
| form.user_submitted = true; |
| |
| FormFieldData field; |
| field.autocomplete_attribute = "shipping tel"; |
| form.fields.push_back(field); |
| |
| FormFieldData cc; |
| cc.autocomplete_attribute = "cc-number"; |
| form.fields.push_back(cc); |
| |
| test_generated_bubble_controller_ = |
| new testing::NiceMock<TestGeneratedCreditCardBubbleController>( |
| GetActiveWebContents()); |
| ASSERT_TRUE(test_generated_bubble_controller_->IsInstalled()); |
| |
| message_loop_runner_ = new content::MessageLoopRunner; |
| controller_ = new TestAutofillDialogController( |
| GetActiveWebContents(), |
| form, |
| message_loop_runner_); |
| } |
| |
| void InitializeController() { |
| InitializeControllerWithoutShowing(); |
| controller_->Show(); |
| CycleRunLoops(); // Ensures dialog is fully visible. |
| } |
| |
| content::WebContents* GetActiveWebContents() { |
| return browser()->tab_strip_model()->GetActiveWebContents(); |
| } |
| |
| content::RenderViewHost* GetRenderViewHost() { |
| return GetActiveWebContents()->GetRenderViewHost(); |
| } |
| |
| scoped_ptr<AutofillDialogViewTester> GetViewTester() { |
| return AutofillDialogViewTester::For(controller()->view()).Pass(); |
| } |
| |
| TestAutofillDialogController* controller() { return controller_; } |
| |
| void RunMessageLoop() { |
| message_loop_runner_->Run(); |
| } |
| |
| // Loads an HTML page in |GetActiveWebContents()| with markup as follows: |
| // <form>|form_inner_html|</form>. After loading, emulates a click event on |
| // the page as requestAutocomplete() must be in response to a user gesture. |
| // Returns the |AutofillDialogControllerImpl| created by this invocation. |
| AutofillDialogControllerImpl* SetUpHtmlAndInvoke( |
| const std::string& form_inner_html) { |
| content::WebContents* contents = GetActiveWebContents(); |
| ChromeAutofillClient* client = |
| ChromeAutofillClient::FromWebContents(contents); |
| CHECK(!client->GetDialogControllerForTesting()); |
| |
| ui_test_utils::NavigateToURL( |
| browser(), GURL(std::string("data:text/html,") + |
| "<!doctype html>" |
| "<html>" |
| "<body>" |
| "<form>" + form_inner_html + "</form>" |
| "<script>" |
| "var invalidEvents = [];" |
| "function recordInvalid(e) {" |
| "if (e.type != 'invalid') throw 'only invalid events allowed';" |
| "invalidEvents.push(e);" |
| "}" |
| "function send(msg) {" |
| "domAutomationController.setAutomationId(0);" |
| "domAutomationController.send(msg);" |
| "}" |
| "document.forms[0].onautocompleteerror = function(e) {" |
| "send('error: ' + e.reason);" |
| "};" |
| "document.forms[0].onautocomplete = function() {" |
| "send('success');" |
| "};" |
| "window.onclick = function() {" |
| "var inputs = document.forms[0].querySelectorAll('input');" |
| "for (var i = 0; i < inputs.length; ++i) {" |
| "inputs[i].oninvalid = recordInvalid;" |
| "}" |
| "document.forms[0].requestAutocomplete();" |
| "send('clicked');" |
| "};" |
| "function loadIframe() {" |
| " var iframe = document.createElement('iframe');" |
| " iframe.onload = function() {" |
| " send('iframe loaded');" |
| " };" |
| " iframe.src = 'about:blank';" |
| " document.body.appendChild(iframe);" |
| "}" |
| "function getValueForFieldOfType(type) {" |
| " var fields = document.getElementsByTagName('input');" |
| " for (var i = 0; i < fields.length; i++) {" |
| " if (fields[i].autocomplete == type) {" |
| " send(fields[i].value);" |
| " return;" |
| " }" |
| " }" |
| " send('');" |
| "};" |
| "</script>" |
| "</body>" |
| "</html>")); |
| |
| InitiateDialog(); |
| AutofillDialogControllerImpl* controller = |
| static_cast<AutofillDialogControllerImpl*>( |
| client->GetDialogControllerForTesting()); |
| return controller; |
| } |
| |
| // Loads an html page on a provided server, the causes it to launch rAc. |
| // Returns whether rAc succesfully launched. |
| bool RunTestPage(const net::SpawnedTestServer& server) { |
| GURL url = server.GetURL( |
| "files/request_autocomplete/test_page.html"); |
| ui_test_utils::NavigateToURL(browser(), url); |
| |
| // Pass through the broken SSL interstitial, if any. |
| content::WebContents* contents = GetActiveWebContents(); |
| content::InterstitialPage* interstitial_page = |
| contents->GetInterstitialPage(); |
| if (interstitial_page) { |
| ui_test_utils::UrlLoadObserver observer( |
| url, |
| content::Source<content::NavigationController>( |
| &contents->GetController())); |
| interstitial_page->Proceed(); |
| observer.Wait(); |
| } |
| |
| InitiateDialog(); |
| |
| ChromeAutofillClient* client = |
| ChromeAutofillClient::FromWebContents(contents); |
| AutofillDialogControllerImpl* controller = |
| static_cast<AutofillDialogControllerImpl*>( |
| client->GetDialogControllerForTesting()); |
| return !!controller; |
| } |
| |
| void RunTestPageInIframe(const net::SpawnedTestServer& server) { |
| InitializeDOMMessageQueue(); |
| GURL iframe_url = server.GetURL( |
| "files/request_autocomplete/test_page.html"); |
| |
| ui_test_utils::NavigateToURL( |
| browser(), GURL(std::string("data:text/html,") + |
| "<!doctype html>" |
| "<html>" |
| "<body>" |
| "<iframe style='position: fixed;" |
| "height: 100%;" |
| "width: 100%;'" |
| "id='racFrame'></iframe>" |
| "<script>" |
| "function send(msg) {" |
| "domAutomationController.setAutomationId(0);" |
| "domAutomationController.send(msg);" |
| "}" |
| "var racFrame = document.getElementById('racFrame');" |
| "racFrame.onload = function() {" |
| "send('iframe loaded');" |
| "};" |
| "racFrame.src = \"" + iframe_url.spec() + "\";" |
| "function navigateFrame() {" |
| "racFrame.src = 'about:blank';" |
| "}" |
| "</script>" |
| "</body>" |
| "</html>")); |
| |
| ChromeAutofillClient* client = |
| ChromeAutofillClient::FromWebContents(GetActiveWebContents()); |
| ExpectDomMessage("iframe loaded"); |
| EXPECT_FALSE(client->GetDialogControllerForTesting()); |
| InitiateDialog(); |
| EXPECT_TRUE(client->GetDialogControllerForTesting()); |
| } |
| |
| // Wait for a message from the DOM automation controller (from JS in the |
| // page). Requires |SetUpHtmlAndInvoke()| be called first. |
| void ExpectDomMessage(const std::string& expected) { |
| std::string message; |
| ASSERT_TRUE(dom_message_queue_->WaitForMessage(&message)); |
| dom_message_queue_->ClearQueue(); |
| EXPECT_EQ("\"" + expected + "\"", message); |
| } |
| |
| void InitiateDialog() { |
| InitializeDOMMessageQueue(); |
| // Triggers the onclick handler which invokes requestAutocomplete(). |
| content::WebContents* contents = GetActiveWebContents(); |
| content::SimulateMouseClick(contents, 0, blink::WebMouseEvent::ButtonLeft); |
| ExpectDomMessage("clicked"); |
| } |
| |
| void InitializeDOMMessageQueue() { |
| dom_message_queue_.reset(new content::DOMMessageQueue); |
| } |
| |
| // Returns the value filled into the first field with autocomplete attribute |
| // equal to |autocomplete_type|, or an empty string if there is no such field. |
| std::string GetValueForHTMLFieldOfType(const std::string& autocomplete_type) { |
| std::string script = "getValueForFieldOfType('" + autocomplete_type + "');"; |
| std::string result; |
| EXPECT_TRUE(content::ExecuteScriptAndExtractString(GetRenderViewHost(), |
| script, |
| &result)); |
| return result; |
| } |
| |
| void AddCreditcardToProfile(Profile* profile, const CreditCard& card) { |
| PersonalDataManagerFactory::GetForProfile(profile)->AddCreditCard(card); |
| WaitForWebDB(); |
| } |
| |
| void AddAutofillProfileToProfile(Profile* profile, |
| const AutofillProfile& autofill_profile) { |
| PersonalDataManagerFactory::GetForProfile(profile)->AddProfile( |
| autofill_profile); |
| WaitForWebDB(); |
| } |
| |
| TestGeneratedCreditCardBubbleController* test_generated_bubble_controller() { |
| return test_generated_bubble_controller_; |
| } |
| |
| private: |
| void WaitForWebDB() { |
| content::RunAllPendingInMessageLoop(content::BrowserThread::DB); |
| } |
| |
| TestAutofillDialogController* controller_; // Weak reference. |
| scoped_refptr<content::MessageLoopRunner> message_loop_runner_; |
| scoped_ptr<content::DOMMessageQueue> dom_message_queue_; |
| |
| // Weak; owned by the active web contents. |
| TestGeneratedCreditCardBubbleController* test_generated_bubble_controller_; |
| |
| DISALLOW_COPY_AND_ASSIGN(AutofillDialogControllerTest); |
| }; |
| |
| // Submit the form data. |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, Submit) { |
| base::HistogramTester histogram; |
| GetViewTester()->SubmitForTesting(); |
| RunMessageLoop(); |
| |
| histogram.ExpectTotalCount("RequestAutocomplete.UiDuration.Submit", 1); |
| histogram.ExpectTotalCount("RequestAutocomplete.UiDuration.Cancel", 0); |
| } |
| |
| // Cancel out of the dialog. |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, Cancel) { |
| base::HistogramTester histogram; |
| GetViewTester()->CancelForTesting(); |
| RunMessageLoop(); |
| |
| histogram.ExpectTotalCount("RequestAutocomplete.UiDuration.Submit", 0); |
| histogram.ExpectTotalCount("RequestAutocomplete.UiDuration.Cancel", 1); |
| histogram.ExpectUniqueSample( |
| "RequestAutocomplete.DismissalState", |
| AutofillMetrics::DIALOG_CANCELED_NO_INVALID_FIELDS, 1); |
| } |
| |
| // Take some other action that dismisses the dialog. |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, Hide) { |
| base::HistogramTester histogram; |
| controller()->Hide(); |
| |
| RunMessageLoop(); |
| |
| histogram.ExpectTotalCount("RequestAutocomplete.UiDuration.Submit", 0); |
| histogram.ExpectTotalCount("RequestAutocomplete.UiDuration.Cancel", 1); |
| histogram.ExpectUniqueSample( |
| "RequestAutocomplete.DismissalState", |
| AutofillMetrics::DIALOG_CANCELED_NO_INVALID_FIELDS, 1); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, CancelWithSuggestions) { |
| base::HistogramTester histogram; |
| |
| CreditCard card(test::GetVerifiedCreditCard()); |
| controller()->GetTestingManager()->AddTestingCreditCard(&card); |
| AutofillProfile profile(test::GetVerifiedProfile()); |
| controller()->GetTestingManager()->AddTestingProfile(&profile); |
| |
| EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_CC)); |
| EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_BILLING)); |
| EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_SHIPPING)); |
| |
| GetViewTester()->CancelForTesting(); |
| RunMessageLoop(); |
| |
| histogram.ExpectTotalCount("RequestAutocomplete.UiDuration.Submit", 0); |
| histogram.ExpectTotalCount("RequestAutocomplete.UiDuration.Cancel", 1); |
| histogram.ExpectUniqueSample("RequestAutocomplete.DismissalState", |
| AutofillMetrics::DIALOG_CANCELED_NO_EDITS, 1); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AcceptWithSuggestions) { |
| base::HistogramTester histogram; |
| CreditCard card(test::GetVerifiedCreditCard()); |
| controller()->GetTestingManager()->AddTestingCreditCard(&card); |
| AutofillProfile profile(test::GetVerifiedProfile()); |
| controller()->GetTestingManager()->AddTestingProfile(&profile); |
| |
| EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_CC)); |
| EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_BILLING)); |
| EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_SHIPPING)); |
| |
| GetViewTester()->SubmitForTesting(); |
| RunMessageLoop(); |
| |
| histogram.ExpectTotalCount("RequestAutocomplete.UiDuration.Submit", 1); |
| histogram.ExpectTotalCount("RequestAutocomplete.UiDuration.Cancel", 0); |
| histogram.ExpectUniqueSample( |
| "RequestAutocomplete.DismissalState", |
| AutofillMetrics::DIALOG_ACCEPTED_EXISTING_AUTOFILL_DATA, 1); |
| } |
| |
| // Ensure that Hide() will only destroy the controller object after the |
| // message loop has run. Otherwise, there may be read-after-free issues |
| // during some tests. |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, DeferredDestruction) { |
| base::WeakPtr<TestAutofillDialogController> weak_ptr = |
| controller()->AsWeakPtr(); |
| EXPECT_TRUE(weak_ptr.get()); |
| |
| controller()->Hide(); |
| EXPECT_TRUE(weak_ptr.get()); |
| |
| RunMessageLoop(); |
| EXPECT_FALSE(weak_ptr.get()); |
| } |
| |
| // Ensure that the expected metric is logged when the dialog is closed during |
| // signin. |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, CloseDuringSignin) { |
| base::HistogramTester histogram; |
| controller()->SignInLinkClicked(); |
| |
| GetViewTester()->CancelForTesting(); |
| |
| RunMessageLoop(); |
| |
| histogram.ExpectTotalCount("RequestAutocomplete.UiDuration.Submit", 0); |
| histogram.ExpectTotalCount("RequestAutocomplete.UiDuration.Cancel", 1); |
| histogram.ExpectUniqueSample("RequestAutocomplete.DismissalState", |
| AutofillMetrics::DIALOG_CANCELED_DURING_SIGNIN, |
| 1); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, FillInputFromAutofill) { |
| AutofillProfile full_profile(test::GetFullProfile()); |
| const base::string16 formatted_phone(ASCIIToUTF16("+1 (310) 555 1234")); |
| full_profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, formatted_phone); |
| controller()->GetTestingManager()->AddTestingProfile(&full_profile); |
| |
| // Dialog is already asking for a new billing address. |
| EXPECT_TRUE(controller()->IsManuallyEditingSection(SECTION_BILLING)); |
| |
| // Select "Add new shipping address...". |
| ui::MenuModel* model = controller()->MenuModelForSection(SECTION_SHIPPING); |
| model->ActivatedAt(model->GetItemCount() - 2); |
| ASSERT_TRUE(controller()->IsManuallyEditingSection(SECTION_SHIPPING)); |
| |
| // Enter something in a shipping input. |
| const DetailInputs& inputs = |
| controller()->RequestedFieldsForSection(SECTION_SHIPPING); |
| const ServerFieldType triggering_type = inputs[0].type; |
| base::string16 value = full_profile.GetRawInfo(triggering_type); |
| scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); |
| view->SetTextContentsOfInput(triggering_type, |
| value.substr(0, value.size() / 2)); |
| view->ActivateInput(triggering_type); |
| |
| ASSERT_EQ(triggering_type, controller()->popup_input_type()); |
| controller()->DidAcceptSuggestion(base::string16(), 0); |
| |
| // All inputs should be filled. |
| AutofillProfileWrapper wrapper(&full_profile); |
| for (size_t i = 0; i < inputs.size(); ++i) { |
| EXPECT_EQ(wrapper.GetInfoForDisplay(AutofillType(inputs[i].type)), |
| view->GetTextContentsOfInput(inputs[i].type)); |
| |
| // Double check the correct formatting is used for the phone number. |
| if (inputs[i].type == PHONE_HOME_WHOLE_NUMBER) |
| EXPECT_EQ(formatted_phone, view->GetTextContentsOfInput(inputs[i].type)); |
| } |
| |
| // Inputs from the other section (billing) should be left alone. |
| const DetailInputs& other_section_inputs = |
| controller()->RequestedFieldsForSection(SECTION_BILLING); |
| for (size_t i = 0; i < inputs.size(); ++i) { |
| base::string16 input_value = |
| view->GetTextContentsOfInput(other_section_inputs[i].type); |
| // If there's a combobox, the string should be non-empty. |
| if (controller()->ComboboxModelForAutofillType( |
| other_section_inputs[i].type)) { |
| EXPECT_NE(base::string16(), input_value); |
| } else { |
| EXPECT_EQ(base::string16(), input_value); |
| } |
| } |
| |
| // Now simulate some user edits and try again. |
| std::vector<base::string16> expectations; |
| for (size_t i = 0; i < inputs.size(); ++i) { |
| if (controller()->ComboboxModelForAutofillType(inputs[i].type)) { |
| expectations.push_back(base::string16()); |
| continue; |
| } |
| base::string16 users_input = i % 2 == 0 ? base::string16() |
| : ASCIIToUTF16("dummy"); |
| view->SetTextContentsOfInput(inputs[i].type, users_input); |
| // Empty inputs should be filled, others should be left alone. |
| base::string16 expectation = |
| inputs[i].type == triggering_type || users_input.empty() ? |
| wrapper.GetInfoForDisplay(AutofillType(inputs[i].type)) : |
| users_input; |
| expectations.push_back(expectation); |
| } |
| |
| view->SetTextContentsOfInput(triggering_type, |
| value.substr(0, value.size() / 2)); |
| view->ActivateInput(triggering_type); |
| ASSERT_EQ(triggering_type, controller()->popup_input_type()); |
| controller()->DidAcceptSuggestion(base::string16(), 0); |
| |
| for (size_t i = 0; i < inputs.size(); ++i) { |
| if (controller()->ComboboxModelForAutofillType(inputs[i].type)) |
| continue; |
| EXPECT_EQ(expectations[i], view->GetTextContentsOfInput(inputs[i].type)); |
| } |
| |
| base::HistogramTester histogram; |
| view->SubmitForTesting(); |
| histogram.ExpectUniqueSample( |
| "RequestAutocomplete.DismissalState", |
| AutofillMetrics::DIALOG_ACCEPTED_SAVE_TO_AUTOFILL, 1); |
| } |
| |
| // This test makes sure that picking a profile variant in the Autofill |
| // popup works as expected. |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, |
| FillInputFromAutofillVariant) { |
| AutofillProfile full_profile(test::GetFullProfile()); |
| |
| // Set up some variant data. |
| std::vector<base::string16> names; |
| names.push_back(ASCIIToUTF16("John Doe")); |
| names.push_back(ASCIIToUTF16("Jane Doe")); |
| full_profile.SetRawMultiInfo(NAME_FULL, names); |
| std::vector<base::string16> emails; |
| emails.push_back(ASCIIToUTF16("user@example.com")); |
| emails.push_back(ASCIIToUTF16("admin@example.com")); |
| full_profile.SetRawMultiInfo(EMAIL_ADDRESS, emails); |
| controller()->GetTestingManager()->AddTestingProfile(&full_profile); |
| |
| const DetailInputs& inputs = |
| controller()->RequestedFieldsForSection(SECTION_BILLING); |
| const ServerFieldType triggering_type = inputs[0].type; |
| EXPECT_EQ(NAME_BILLING_FULL, triggering_type); |
| scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); |
| view->ActivateInput(triggering_type); |
| |
| ASSERT_EQ(triggering_type, controller()->popup_input_type()); |
| |
| // Choose the variant suggestion. |
| controller()->DidAcceptSuggestion(base::string16(), 1); |
| |
| // All inputs should be filled. |
| AutofillProfileWrapper wrapper( |
| &full_profile, AutofillType(NAME_BILLING_FULL), 1); |
| for (size_t i = 0; i < inputs.size(); ++i) { |
| EXPECT_EQ(wrapper.GetInfoForDisplay(AutofillType(inputs[i].type)), |
| view->GetTextContentsOfInput(inputs[i].type)); |
| } |
| |
| // Make sure the wrapper applies the variant index to the right group. |
| EXPECT_EQ(names[1], wrapper.GetInfo(AutofillType(NAME_BILLING_FULL))); |
| // Make sure the wrapper doesn't apply the variant index to the wrong group. |
| EXPECT_EQ(emails[0], wrapper.GetInfo(AutofillType(EMAIL_ADDRESS))); |
| } |
| |
| // Tests that changing the value of a CC expiration date combobox works as |
| // expected when Autofill is used to fill text inputs. |
| // |
| // Flaky on Win7, WinXP, and Win Aura. http://crbug.com/270314. |
| #if defined(OS_WIN) |
| #define MAYBE_FillComboboxFromAutofill DISABLED_FillComboboxFromAutofill |
| #else |
| #define MAYBE_FillComboboxFromAutofill FillComboboxFromAutofill |
| #endif |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, |
| MAYBE_FillComboboxFromAutofill) { |
| CreditCard card1; |
| test::SetCreditCardInfo(&card1, "JJ Smith", "4111111111111111", "12", "2018"); |
| controller()->GetTestingManager()->AddTestingCreditCard(&card1); |
| CreditCard card2; |
| test::SetCreditCardInfo(&card2, "B Bird", "3111111111111111", "11", "2017"); |
| controller()->GetTestingManager()->AddTestingCreditCard(&card2); |
| AutofillProfile full_profile(test::GetFullProfile()); |
| controller()->GetTestingManager()->AddTestingProfile(&full_profile); |
| |
| const DetailInputs& inputs = |
| controller()->RequestedFieldsForSection(SECTION_CC); |
| const ServerFieldType triggering_type = inputs[0].type; |
| base::string16 value = card1.GetRawInfo(triggering_type); |
| scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); |
| view->SetTextContentsOfInput(triggering_type, |
| value.substr(0, value.size() / 2)); |
| view->ActivateInput(triggering_type); |
| |
| ASSERT_EQ(triggering_type, controller()->popup_input_type()); |
| controller()->DidAcceptSuggestion(base::string16(), 0); |
| |
| // All inputs should be filled. |
| AutofillCreditCardWrapper wrapper1(&card1); |
| for (size_t i = 0; i < inputs.size(); ++i) { |
| EXPECT_EQ(wrapper1.GetInfo(AutofillType(inputs[i].type)), |
| view->GetTextContentsOfInput(inputs[i].type)); |
| } |
| |
| // Try again with different data. Only expiration date and the triggering |
| // input should be overwritten. |
| value = card2.GetRawInfo(triggering_type); |
| view->SetTextContentsOfInput(triggering_type, |
| value.substr(0, value.size() / 2)); |
| view->ActivateInput(triggering_type); |
| ASSERT_EQ(triggering_type, controller()->popup_input_type()); |
| controller()->DidAcceptSuggestion(base::string16(), 0); |
| |
| AutofillCreditCardWrapper wrapper2(&card2); |
| for (size_t i = 0; i < inputs.size(); ++i) { |
| const ServerFieldType type = inputs[i].type; |
| if (type == triggering_type || |
| type == CREDIT_CARD_EXP_MONTH || |
| type == CREDIT_CARD_EXP_4_DIGIT_YEAR) { |
| EXPECT_EQ(wrapper2.GetInfo(AutofillType(type)), |
| view->GetTextContentsOfInput(type)); |
| } else if (type == CREDIT_CARD_VERIFICATION_CODE) { |
| EXPECT_TRUE(view->GetTextContentsOfInput(type).empty()); |
| } else { |
| EXPECT_EQ(wrapper1.GetInfo(AutofillType(type)), |
| view->GetTextContentsOfInput(type)); |
| } |
| } |
| |
| // Now fill from a profile. It should not overwrite any CC info. |
| const DetailInputs& billing_inputs = |
| controller()->RequestedFieldsForSection(SECTION_BILLING); |
| const ServerFieldType billing_triggering_type = billing_inputs[0].type; |
| value = full_profile.GetRawInfo(triggering_type); |
| view->SetTextContentsOfInput(billing_triggering_type, |
| value.substr(0, value.size() / 2)); |
| view->ActivateInput(billing_triggering_type); |
| |
| ASSERT_EQ(billing_triggering_type, controller()->popup_input_type()); |
| controller()->DidAcceptSuggestion(base::string16(), 0); |
| |
| for (size_t i = 0; i < inputs.size(); ++i) { |
| const ServerFieldType type = inputs[i].type; |
| if (type == triggering_type || |
| type == CREDIT_CARD_EXP_MONTH || |
| type == CREDIT_CARD_EXP_4_DIGIT_YEAR) { |
| EXPECT_EQ(wrapper2.GetInfo(AutofillType(type)), |
| view->GetTextContentsOfInput(type)); |
| } else if (type == CREDIT_CARD_VERIFICATION_CODE) { |
| EXPECT_TRUE(view->GetTextContentsOfInput(type).empty()); |
| } else { |
| EXPECT_EQ(wrapper1.GetInfo(AutofillType(type)), |
| view->GetTextContentsOfInput(type)); |
| } |
| } |
| } |
| |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, ShouldShowErrorBubble) { |
| controller()->set_use_validation(true); |
| EXPECT_TRUE(controller()->ShouldShowErrorBubble()); |
| |
| CreditCard card(test::GetCreditCard()); |
| ASSERT_FALSE(card.IsVerified()); |
| controller()->GetTestingManager()->AddTestingCreditCard(&card); |
| |
| EXPECT_TRUE(controller()->IsManuallyEditingSection(SECTION_CC)); |
| scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); |
| view->SetTextContentsOfInput( |
| CREDIT_CARD_NUMBER, |
| card.GetRawInfo(CREDIT_CARD_NUMBER).substr(0, 1)); |
| |
| view->ActivateInput(CREDIT_CARD_NUMBER); |
| EXPECT_FALSE(controller()->ShouldShowErrorBubble()); |
| |
| controller()->FocusMoved(); |
| EXPECT_TRUE(controller()->ShouldShowErrorBubble()); |
| |
| base::HistogramTester histogram; |
| controller()->Hide(); |
| histogram.ExpectUniqueSample( |
| "RequestAutocomplete.DismissalState", |
| AutofillMetrics::DIALOG_CANCELED_WITH_INVALID_FIELDS, 1); |
| } |
| |
| // Ensure that expired cards trigger invalid suggestions. |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, ExpiredCard) { |
| CreditCard verified_card(test::GetCreditCard()); |
| verified_card.set_origin("Chrome settings"); |
| ASSERT_TRUE(verified_card.IsVerified()); |
| controller()->GetTestingManager()->AddTestingCreditCard(&verified_card); |
| |
| CreditCard expired_card(test::GetCreditCard()); |
| expired_card.set_origin("Chrome settings"); |
| expired_card.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2007")); |
| ASSERT_TRUE(expired_card.IsVerified()); |
| ASSERT_FALSE( |
| autofill::IsValidCreditCardExpirationDate( |
| expired_card.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR), |
| expired_card.GetRawInfo(CREDIT_CARD_EXP_MONTH), |
| base::Time::Now())); |
| controller()->GetTestingManager()->AddTestingCreditCard(&expired_card); |
| |
| ui::MenuModel* model = controller()->MenuModelForSection(SECTION_CC); |
| ASSERT_EQ(4, model->GetItemCount()); |
| |
| ASSERT_TRUE(model->IsItemCheckedAt(0)); |
| EXPECT_FALSE(controller()->IsEditingExistingData(SECTION_CC)); |
| |
| model->ActivatedAt(1); |
| ASSERT_TRUE(model->IsItemCheckedAt(1)); |
| EXPECT_TRUE(controller()->IsEditingExistingData(SECTION_CC)); |
| } |
| |
| // Notifications with long message text should not make the dialog bigger. |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, LongNotifications) { |
| const gfx::Size no_notification_size = GetViewTester()->GetSize(); |
| ASSERT_GT(no_notification_size.width(), 0); |
| |
| std::vector<DialogNotification> notifications; |
| notifications.push_back( |
| DialogNotification(DialogNotification::DEVELOPER_WARNING, ASCIIToUTF16( |
| "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do " |
| "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim " |
| "ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut " |
| "aliquip ex ea commodo consequat. Duis aute irure dolor in " |
| "reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla " |
| "pariatur. Excepteur sint occaecat cupidatat non proident, sunt in " |
| "culpa qui officia deserunt mollit anim id est laborum."))); |
| controller()->set_notifications(notifications); |
| controller()->view()->UpdateNotificationArea(); |
| |
| EXPECT_EQ(no_notification_size.width(), |
| GetViewTester()->GetSize().width()); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AutocompleteEvent) { |
| AutofillDialogControllerImpl* controller = |
| SetUpHtmlAndInvoke("<input autocomplete='cc-name'>"); |
| ASSERT_TRUE(controller); |
| |
| AddCreditcardToProfile(controller->profile(), test::GetVerifiedCreditCard()); |
| AddAutofillProfileToProfile(controller->profile(), |
| test::GetVerifiedProfile()); |
| |
| scoped_ptr<AutofillDialogViewTester> view = |
| AutofillDialogViewTester::For( |
| static_cast<TestAutofillDialogController*>(controller)->view()); |
| view->SetTextContentsOfSuggestionInput(SECTION_CC, ASCIIToUTF16("123")); |
| view->SubmitForTesting(); |
| ExpectDomMessage("success"); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, |
| AutocompleteErrorEventReasonInvalid) { |
| AutofillDialogControllerImpl* controller = |
| SetUpHtmlAndInvoke("<input autocomplete='cc-name' pattern='.*zebra.*'>"); |
| ASSERT_TRUE(controller); |
| |
| const CreditCard& credit_card = test::GetVerifiedCreditCard(); |
| ASSERT_TRUE( |
| credit_card.GetRawInfo(CREDIT_CARD_NAME).find(ASCIIToUTF16("zebra")) == |
| base::string16::npos); |
| AddCreditcardToProfile(controller->profile(), credit_card); |
| AddAutofillProfileToProfile(controller->profile(), |
| test::GetVerifiedProfile()); |
| |
| scoped_ptr<AutofillDialogViewTester> view = |
| AutofillDialogViewTester::For( |
| static_cast<TestAutofillDialogController*>(controller)->view()); |
| view->SetTextContentsOfSuggestionInput(SECTION_CC, ASCIIToUTF16("123")); |
| view->SubmitForTesting(); |
| ExpectDomMessage("error: invalid"); |
| |
| int invalid_count = -1; |
| ASSERT_TRUE(content::ExecuteScriptAndExtractInt( |
| GetRenderViewHost(), "send(invalidEvents.length);", &invalid_count)); |
| EXPECT_EQ(1, invalid_count); |
| |
| std::string invalid_type; |
| ASSERT_TRUE(content::ExecuteScriptAndExtractString( |
| GetRenderViewHost(), |
| "send(invalidEvents[0].target.autocomplete);", |
| &invalid_type)); |
| EXPECT_EQ("cc-name", invalid_type); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, |
| AutocompleteErrorEventReasonCancel) { |
| AutofillDialogControllerImpl* controller = |
| SetUpHtmlAndInvoke("<input autocomplete='cc-name'>"); |
| ASSERT_TRUE(controller); |
| AutofillDialogViewTester::For( |
| static_cast<TestAutofillDialogController*>(controller)->view())-> |
| CancelForTesting(); |
| ExpectDomMessage("error: cancel"); |
| } |
| |
| // http://crbug.com/318526 |
| #if defined(OS_MACOSX) |
| #define MAYBE_ErrorWithFrameNavigation DISABLED_ErrorWithFrameNavigation |
| #else |
| #define MAYBE_ErrorWithFrameNavigation ErrorWithFrameNavigation |
| #endif |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, |
| MAYBE_ErrorWithFrameNavigation) { |
| AutofillDialogControllerImpl* controller = |
| SetUpHtmlAndInvoke("<input autocomplete='cc-name'>"); |
| ASSERT_TRUE(controller); |
| |
| std::string unused; |
| ASSERT_TRUE(content::ExecuteScriptAndExtractString(GetRenderViewHost(), |
| "loadIframe();", |
| &unused)); |
| ExpectDomMessage("iframe loaded"); |
| |
| AutofillDialogViewTester::For( |
| static_cast<TestAutofillDialogController*>(controller)->view())-> |
| CancelForTesting(); |
| ExpectDomMessage("error: cancel"); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, NoCvcSegfault) { |
| controller()->set_use_validation(true); |
| |
| CreditCard credit_card(test::GetVerifiedCreditCard()); |
| controller()->GetTestingManager()->AddTestingCreditCard(&credit_card); |
| EXPECT_FALSE(controller()->IsEditingExistingData(SECTION_CC)); |
| |
| ASSERT_NO_FATAL_FAILURE(GetViewTester()->SubmitForTesting()); |
| } |
| |
| // Flaky on Win7, WinXP, and Win Aura. http://crbug.com/270314. |
| #if defined(OS_WIN) |
| #define MAYBE_PreservedSections DISABLED_PreservedSections |
| #else |
| #define MAYBE_PreservedSections PreservedSections |
| #endif |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, MAYBE_PreservedSections) { |
| controller()->set_use_validation(true); |
| |
| scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); |
| view->SetTextContentsOfInput(CREDIT_CARD_NUMBER, |
| ASCIIToUTF16("4111111111111111")); |
| |
| // Create some invalid, manually inputted shipping data. |
| view->SetTextContentsOfInput(ADDRESS_HOME_ZIP, ASCIIToUTF16("shipping zip")); |
| |
| // Switch to Wallet by simulating a successful server response. |
| controller()->OnDidFetchWalletCookieValue(std::string()); |
| controller()->OnDidGetWalletItems( |
| wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED)); |
| ASSERT_TRUE(controller()->IsPayingWithWallet()); |
| |
| // The valid data should be preserved. |
| EXPECT_EQ(ASCIIToUTF16("4111111111111111"), |
| view->GetTextContentsOfInput(CREDIT_CARD_NUMBER)); |
| |
| // The invalid data should be dropped. |
| EXPECT_TRUE(view->GetTextContentsOfInput(ADDRESS_HOME_ZIP).empty()); |
| |
| // Switch back to Autofill. |
| ui::MenuModel* account_chooser = controller()->MenuModelForAccountChooser(); |
| account_chooser->ActivatedAt(account_chooser->GetItemCount() - 1); |
| ASSERT_FALSE(controller()->IsPayingWithWallet()); |
| |
| // The valid data should still be preserved when switched back. |
| EXPECT_EQ(ASCIIToUTF16("4111111111111111"), |
| view->GetTextContentsOfInput(CREDIT_CARD_NUMBER)); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, |
| GeneratedCardLastFourAfterVerifyCvv) { |
| controller()->OnDidFetchWalletCookieValue(std::string()); |
| |
| scoped_ptr<wallet::WalletItems> wallet_items = |
| wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED); |
| wallet_items->AddInstrument(wallet::GetTestMaskedInstrument()); |
| wallet_items->AddAddress(wallet::GetTestShippingAddress()); |
| |
| base::string16 last_four = |
| wallet_items->instruments()[0]->TypeAndLastFourDigits(); |
| controller()->OnDidGetWalletItems(wallet_items.Pass()); |
| |
| scoped_ptr<AutofillDialogViewTester> test_view = GetViewTester(); |
| EXPECT_FALSE(test_view->IsShowingOverlay()); |
| EXPECT_CALL(*controller(), LoadRiskFingerprintData()); |
| controller()->OnAccept(); |
| EXPECT_TRUE(test_view->IsShowingOverlay()); |
| |
| EXPECT_CALL(*controller()->GetTestingWalletClient(), GetFullWallet(_)); |
| controller()->OnDidLoadRiskFingerprintData("a"); |
| |
| controller()->OnDidGetFullWallet( |
| wallet::GetTestFullWalletWithRequiredActions( |
| std::vector<wallet::RequiredAction>(1, wallet::VERIFY_CVV))); |
| |
| ASSERT_TRUE(controller()->IsSubmitPausedOn(wallet::VERIFY_CVV)); |
| |
| std::string fake_cvc("123"); |
| test_view->SetTextContentsOfSuggestionInput(SECTION_CC_BILLING, |
| ASCIIToUTF16(fake_cvc)); |
| |
| EXPECT_FALSE(test_view->IsShowingOverlay()); |
| EXPECT_CALL(*controller()->GetTestingWalletClient(), |
| AuthenticateInstrument(_, fake_cvc)); |
| controller()->OnAccept(); |
| EXPECT_TRUE(test_view->IsShowingOverlay()); |
| |
| base::HistogramTester histogram; |
| EXPECT_CALL(*controller()->GetTestingWalletClient(), GetFullWallet(_)); |
| controller()->OnDidAuthenticateInstrument(true); |
| controller()->OnDidGetFullWallet(wallet::GetTestFullWallet()); |
| controller()->ForceFinishSubmit(); |
| |
| histogram.ExpectUniqueSample( |
| "RequestAutocomplete.DismissalState", |
| AutofillMetrics::DIALOG_ACCEPTED_EXISTING_WALLET_DATA, 1); |
| |
| RunMessageLoop(); |
| |
| EXPECT_EQ(1, test_generated_bubble_controller()->bubbles_shown()); |
| EXPECT_EQ(last_four, test_generated_bubble_controller()->backing_card_name()); |
| } |
| |
| // Simulates the user signing in to the dialog from the inline web contents. |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, SimulateSuccessfulSignIn) { |
| #if defined(OS_WIN) |
| // TODO(msw): Fix potential flakiness on Windows XP; http://crbug.com/333641 |
| if (base::win::GetVersion() <= base::win::VERSION_XP) |
| return; |
| #endif |
| browser()->profile()->GetPrefs()->SetBoolean( |
| ::prefs::kAutofillDialogPayWithoutWallet, |
| true); |
| |
| InitializeController(); |
| |
| controller()->OnDidFetchWalletCookieValue(std::string()); |
| controller()->OnDidGetWalletItems( |
| wallet::GetTestWalletItemsWithRequiredAction(wallet::GAIA_AUTH)); |
| |
| NavEntryCommittedObserver sign_in_page_observer( |
| controller()->FakeSignInUrl(), |
| content::NotificationService::AllSources()); |
| |
| // Simulate a user clicking "Sign In" (which loads dialog's web contents). |
| controller()->SignInLinkClicked(); |
| EXPECT_TRUE(controller()->ShouldShowSignInWebView()); |
| |
| scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); |
| content::WebContents* sign_in_contents = view->GetSignInWebContents(); |
| ASSERT_TRUE(sign_in_contents); |
| |
| sign_in_page_observer.Wait(); |
| |
| NavEntryCommittedObserver continue_page_observer( |
| wallet::GetSignInContinueUrl(), |
| content::NotificationService::AllSources()); |
| |
| EXPECT_EQ(sign_in_contents->GetURL(), controller()->FakeSignInUrl()); |
| |
| AccountChooserModel* account_chooser_model = |
| controller()->AccountChooserModelForTesting(); |
| EXPECT_FALSE(account_chooser_model->WalletIsSelected()); |
| |
| content::OpenURLParams params(wallet::GetSignInContinueUrl(), |
| content::Referrer(), |
| CURRENT_TAB, |
| ui::PAGE_TRANSITION_LINK, |
| true); |
| |
| sign_in_contents->GetDelegate()->OpenURLFromTab(sign_in_contents, params); |
| |
| EXPECT_CALL(*controller()->GetTestingWalletClient(), GetWalletItems(_, _)); |
| continue_page_observer.Wait(); |
| content::RunAllPendingInMessageLoop(); |
| |
| EXPECT_FALSE(controller()->ShouldShowSignInWebView()); |
| |
| scoped_ptr<wallet::WalletItems> wallet_items = |
| wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED); |
| wallet_items->AddInstrument(wallet::GetTestMaskedInstrument()); |
| controller()->OnDidGetWalletItems(wallet_items.Pass()); |
| |
| // Wallet should now be selected and Chrome shouldn't have crashed (which can |
| // happen if the WebContents is deleted while proccessing a nav entry commit). |
| EXPECT_TRUE(account_chooser_model->WalletIsSelected()); |
| EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_CC_BILLING)); |
| EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_SHIPPING)); |
| |
| base::HistogramTester histogram; |
| view->SubmitForTesting(); |
| controller()->OnDidGetFullWallet(wallet::GetTestFullWallet()); |
| controller()->ForceFinishSubmit(); |
| histogram.ExpectUniqueSample( |
| "RequestAutocomplete.DismissalState", |
| AutofillMetrics::DIALOG_ACCEPTED_EXISTING_WALLET_DATA, 1); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AddAccount) { |
| #if defined(OS_WIN) |
| // TODO(msw): Fix potential flakiness on Windows XP; http://crbug.com/333641 |
| if (base::win::GetVersion() <= base::win::VERSION_XP) |
| return; |
| #endif |
| |
| controller()->OnDidFetchWalletCookieValue(std::string()); |
| std::vector<std::string> usernames; |
| usernames.push_back("user_0@example.com"); |
| controller()->OnDidGetWalletItems( |
| wallet::GetTestWalletItemsWithUsers(usernames, 0)); |
| |
| // Switch to Autofill. |
| AccountChooserModel* account_chooser_model = |
| controller()->AccountChooserModelForTesting(); |
| account_chooser_model->ActivatedAt( |
| account_chooser_model->GetItemCount() - 1); |
| |
| NavEntryCommittedObserver sign_in_page_observer( |
| controller()->FakeSignInUrl(), |
| content::NotificationService::AllSources()); |
| |
| // Simulate a user clicking "add account". |
| account_chooser_model->ActivatedAt( |
| account_chooser_model->GetItemCount() - 2); |
| EXPECT_TRUE(controller()->ShouldShowSignInWebView()); |
| |
| scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); |
| content::WebContents* sign_in_contents = view->GetSignInWebContents(); |
| ASSERT_TRUE(sign_in_contents); |
| |
| sign_in_page_observer.Wait(); |
| |
| NavEntryCommittedObserver continue_page_observer( |
| wallet::GetSignInContinueUrl(), |
| content::NotificationService::AllSources()); |
| |
| EXPECT_EQ(sign_in_contents->GetURL(), controller()->FakeSignInUrl()); |
| |
| EXPECT_FALSE(account_chooser_model->WalletIsSelected()); |
| |
| // User signs into new account, account 3. |
| controller()->set_sign_in_user_index(3U); |
| content::OpenURLParams params(wallet::GetSignInContinueUrl(), |
| content::Referrer(), |
| CURRENT_TAB, |
| ui::PAGE_TRANSITION_LINK, |
| true); |
| sign_in_contents->GetDelegate()->OpenURLFromTab(sign_in_contents, params); |
| |
| EXPECT_CALL(*controller()->GetTestingWalletClient(), GetWalletItems(_, _)); |
| continue_page_observer.Wait(); |
| content::RunAllPendingInMessageLoop(); |
| |
| EXPECT_FALSE(controller()->ShouldShowSignInWebView()); |
| EXPECT_EQ(3U, controller()->GetTestingWalletClient()->user_index()); |
| |
| usernames.push_back("user_1@example.com"); |
| usernames.push_back("user_2@example.com"); |
| usernames.push_back("user_3@example.com"); |
| usernames.push_back("user_4@example.com"); |
| // Curveball: wallet items comes back with user 4 selected. |
| controller()->OnDidGetWalletItems( |
| wallet::GetTestWalletItemsWithUsers(usernames, 4U)); |
| |
| EXPECT_TRUE(account_chooser_model->WalletIsSelected()); |
| EXPECT_EQ(4U, account_chooser_model->GetActiveWalletAccountIndex()); |
| EXPECT_EQ(4U, controller()->GetTestingWalletClient()->user_index()); |
| } |
| |
| // Verify that filling a form works correctly, including filling the CVC when |
| // that is requested separately. |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, |
| FillFormIncludesCVC) { |
| AutofillDialogControllerImpl* controller = |
| SetUpHtmlAndInvoke("<input autocomplete='cc-csc'>"); |
| ASSERT_TRUE(controller); |
| |
| AddCreditcardToProfile(controller->profile(), test::GetVerifiedCreditCard()); |
| AddAutofillProfileToProfile(controller->profile(), |
| test::GetVerifiedProfile()); |
| |
| scoped_ptr<AutofillDialogViewTester> view = |
| AutofillDialogViewTester::For( |
| static_cast<TestAutofillDialogController*>(controller)->view()); |
| view->SetTextContentsOfSuggestionInput(SECTION_CC, ASCIIToUTF16("123")); |
| view->SubmitForTesting(); |
| ExpectDomMessage("success"); |
| EXPECT_EQ("123", GetValueForHTMLFieldOfType("cc-csc")); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AddNewClearsComboboxes) { |
| // Ensure the input under test is a combobox. |
| ASSERT_TRUE( |
| controller()->ComboboxModelForAutofillType(CREDIT_CARD_EXP_MONTH)); |
| |
| // Set up an expired card. |
| CreditCard card; |
| test::SetCreditCardInfo(&card, "Roy Demeo", "4111111111111111", "8", "2013"); |
| card.set_origin("Chrome settings"); |
| ASSERT_TRUE(card.IsVerified()); |
| |
| // Add the card and check that there's a menu for that section. |
| controller()->GetTestingManager()->AddTestingCreditCard(&card); |
| ASSERT_TRUE(controller()->MenuModelForSection(SECTION_CC)); |
| |
| // Select the invalid, suggested card from the menu. |
| controller()->MenuModelForSection(SECTION_CC)->ActivatedAt(0); |
| EXPECT_TRUE(controller()->IsEditingExistingData(SECTION_CC)); |
| |
| // Get the contents of the combobox of the credit card's expiration month. |
| scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); |
| base::string16 cc_exp_month_text = |
| view->GetTextContentsOfInput(CREDIT_CARD_EXP_MONTH); |
| |
| // Select "New X..." from the suggestion menu to clear the section's inputs. |
| controller()->MenuModelForSection(SECTION_CC)->ActivatedAt(1); |
| EXPECT_FALSE(controller()->IsEditingExistingData(SECTION_CC)); |
| |
| // Ensure that the credit card expiration month has changed. |
| EXPECT_NE(cc_exp_month_text, |
| view->GetTextContentsOfInput(CREDIT_CARD_EXP_MONTH)); |
| } |
| |
| // Flaky on Win7 (http://crbug.com/446432) |
| #if defined(OS_WIN) |
| #define MAYBE_TabOpensToJustRight DISABLED_TabOpensToJustRight |
| #else |
| #define MAYBE_TabOpensToJustRight TabOpensToJustRight |
| #endif |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, |
| MAYBE_TabOpensToJustRight) { |
| ASSERT_TRUE(browser()->is_type_tabbed()); |
| |
| // Tabs should currently be: / rAc() \. |
| content::WebContents* dialog_invoker = controller()->GetWebContents(); |
| EXPECT_EQ(dialog_invoker, GetActiveWebContents()); |
| |
| TabStripModel* tab_strip = browser()->tab_strip_model(); |
| ASSERT_EQ(1, tab_strip->count()); |
| EXPECT_EQ(0, tab_strip->GetIndexOfWebContents(dialog_invoker)); |
| |
| // Open a tab to about:blank in the background at the end of the tab strip. |
| chrome::AddTabAt(browser(), GURL(), -1, false); |
| // Tabs should now be: / rAc() \/ blank \. |
| EXPECT_EQ(2, tab_strip->count()); |
| EXPECT_EQ(0, tab_strip->active_index()); |
| EXPECT_EQ(dialog_invoker, GetActiveWebContents()); |
| |
| content::WebContents* blank_tab = tab_strip->GetWebContentsAt(1); |
| |
| // Simulate clicking "Manage X...". |
| controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(2); |
| // Tab should now be: / rAc() \/ manage 1 \/ blank \. |
| EXPECT_EQ(3, tab_strip->count()); |
| int dialog_index = tab_strip->GetIndexOfWebContents(dialog_invoker); |
| EXPECT_EQ(0, dialog_index); |
| EXPECT_EQ(1, tab_strip->active_index()); |
| EXPECT_EQ(2, tab_strip->GetIndexOfWebContents(blank_tab)); |
| |
| content::WebContents* first_manage_tab = tab_strip->GetWebContentsAt(1); |
| |
| // Re-activate the dialog's tab (like a user would have to). |
| tab_strip->ActivateTabAt(dialog_index, true); |
| EXPECT_EQ(dialog_invoker, GetActiveWebContents()); |
| |
| // Simulate clicking "Manage X...". |
| controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(2); |
| // Tabs should now be: / rAc() \/ manage 2 \/ manage 1 \/ blank \. |
| EXPECT_EQ(4, tab_strip->count()); |
| EXPECT_EQ(0, tab_strip->GetIndexOfWebContents(dialog_invoker)); |
| EXPECT_EQ(1, tab_strip->active_index()); |
| EXPECT_EQ(2, tab_strip->GetIndexOfWebContents(first_manage_tab)); |
| EXPECT_EQ(3, tab_strip->GetIndexOfWebContents(blank_tab)); |
| } |
| |
| // Flaky on Win7 (http://crbug.com/446432) |
| #if defined(OS_WIN) |
| #define MAYBE_SignInWebViewOpensLinksInNewTab DISABLED_SignInWebViewOpensLinksInNewTab |
| #else |
| #define MAYBE_SignInWebViewOpensLinksInNewTab SignInWebViewOpensLinksInNewTab |
| #endif |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, |
| MAYBE_SignInWebViewOpensLinksInNewTab) { |
| controller()->OnDidFetchWalletCookieValue(std::string()); |
| controller()->OnDidGetWalletItems( |
| wallet::GetTestWalletItemsWithRequiredAction(wallet::GAIA_AUTH)); |
| |
| NavEntryCommittedObserver sign_in_page_observer( |
| controller()->FakeSignInUrl(), |
| content::NotificationService::AllSources()); |
| |
| controller()->SignInLinkClicked(); |
| |
| content::WebContents* sign_in_contents = |
| GetViewTester()->GetSignInWebContents(); |
| ASSERT_TRUE(sign_in_contents); |
| |
| sign_in_page_observer.Wait(); |
| |
| content::OpenURLParams params(GURL("http://google.com"), |
| content::Referrer(), |
| CURRENT_TAB, |
| ui::PAGE_TRANSITION_LINK, |
| true); |
| params.user_gesture = true; |
| |
| int num_tabs = browser()->tab_strip_model()->count(); |
| sign_in_contents->GetDelegate()->OpenURLFromTab(sign_in_contents, params); |
| EXPECT_EQ(num_tabs + 1, browser()->tab_strip_model()->count()); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, RefreshOnManageTabClose) { |
| ASSERT_TRUE(browser()->is_type_tabbed()); |
| |
| // GetWalletItems(_, _) is called when controller() is created in SetUp(). |
| EXPECT_CALL(*controller()->GetTestingWalletClient(), GetWalletItems(_, _)); |
| controller()->OnDidFetchWalletCookieValue(std::string()); |
| controller()->OnDidGetWalletItems( |
| wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED)); |
| |
| content::WebContents* dialog_invoker = controller()->GetWebContents(); |
| ChromeAutofillClient::FromWebContents(dialog_invoker) |
| ->SetDialogControllerForTesting(controller()->AsWeakPtr()); |
| |
| // Open a new tab by selecting "Manage my shipping details..." in Wallet mode. |
| EXPECT_EQ(1, browser()->tab_strip_model()->count()); |
| controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(2); |
| EXPECT_EQ(2, browser()->tab_strip_model()->count()); |
| ASSERT_NE(dialog_invoker, GetActiveWebContents()); |
| |
| // Closing the tab opened by "Manage my shipping details..." should refresh |
| // the dialog. |
| controller()->ClearLastWalletItemsFetchTimestampForTesting(); |
| EXPECT_CALL(*controller()->GetTestingWalletClient(), GetWalletItems(_, _)); |
| GetActiveWebContents()->Close(); |
| } |
| |
| // Changes from Wallet to Autofill and verifies that the combined billing/cc |
| // sections are showing (or not) at the correct times. |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, |
| ChangingDataSourceShowsCorrectSections) { |
| scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); |
| EXPECT_TRUE(view->IsShowingSection(SECTION_CC)); |
| EXPECT_TRUE(view->IsShowingSection(SECTION_BILLING)); |
| EXPECT_FALSE(view->IsShowingSection(SECTION_CC_BILLING)); |
| |
| // Switch the dialog to paying with Wallet. |
| controller()->OnDidFetchWalletCookieValue(std::string()); |
| controller()->OnDidGetWalletItems( |
| wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED)); |
| ASSERT_TRUE(controller()->IsPayingWithWallet()); |
| |
| EXPECT_FALSE(view->IsShowingSection(SECTION_CC)); |
| EXPECT_FALSE(view->IsShowingSection(SECTION_BILLING)); |
| EXPECT_TRUE(view->IsShowingSection(SECTION_CC_BILLING)); |
| |
| // Now switch back to Autofill to ensure this direction works as well. |
| ui::MenuModel* account_chooser = controller()->MenuModelForAccountChooser(); |
| account_chooser->ActivatedAt(account_chooser->GetItemCount() - 1); |
| |
| EXPECT_TRUE(view->IsShowingSection(SECTION_CC)); |
| EXPECT_TRUE(view->IsShowingSection(SECTION_BILLING)); |
| EXPECT_FALSE(view->IsShowingSection(SECTION_CC_BILLING)); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, |
| DoesWorkOnHttpWithFlag) { |
| net::SpawnedTestServer http_server( |
| net::SpawnedTestServer::TYPE_HTTP, |
| net::SpawnedTestServer::kLocalhost, |
| base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); |
| ASSERT_TRUE(http_server.Start()); |
| EXPECT_TRUE(RunTestPage(http_server)); |
| } |
| |
| // Like the parent test, but doesn't add the --reduce-security-for-testing flag. |
| class AutofillDialogControllerSecurityTest : |
| public AutofillDialogControllerTest { |
| public: |
| AutofillDialogControllerSecurityTest() {} |
| ~AutofillDialogControllerSecurityTest() override {} |
| |
| void SetUpCommandLine(base::CommandLine* command_line) override { |
| CHECK(!command_line->HasSwitch(::switches::kReduceSecurityForTesting)); |
| } |
| |
| typedef net::BaseTestServer::SSLOptions SSLOptions; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(AutofillDialogControllerSecurityTest); |
| }; |
| |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerSecurityTest, |
| DoesntWorkOnHttp) { |
| net::SpawnedTestServer http_server( |
| net::SpawnedTestServer::TYPE_HTTP, |
| net::SpawnedTestServer::kLocalhost, |
| base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); |
| ASSERT_TRUE(http_server.Start()); |
| EXPECT_FALSE(RunTestPage(http_server)); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerSecurityTest, |
| DoesWorkOnHttpWithFlags) { |
| net::SpawnedTestServer https_server( |
| net::SpawnedTestServer::TYPE_HTTPS, |
| SSLOptions(SSLOptions::CERT_OK), |
| base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); |
| ASSERT_TRUE(https_server.Start()); |
| EXPECT_TRUE(RunTestPage(https_server)); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerSecurityTest, |
| DISABLED_DoesntWorkOnBrokenHttps) { |
| net::SpawnedTestServer https_server( |
| net::SpawnedTestServer::TYPE_HTTPS, |
| SSLOptions(SSLOptions::CERT_EXPIRED), |
| base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); |
| ASSERT_TRUE(https_server.Start()); |
| EXPECT_FALSE(RunTestPage(https_server)); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, |
| CountryChangeRebuildsSection) { |
| EXPECT_FALSE(SectionHasField(SECTION_BILLING, ADDRESS_BILLING_SORTING_CODE)); |
| EXPECT_FALSE(SectionHasField(SECTION_SHIPPING, ADDRESS_HOME_SORTING_CODE)); |
| |
| // Select "Add new shipping address...". |
| controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(1); |
| |
| // Add some valid user input that should be preserved when country changes. |
| scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); |
| view->SetTextContentsOfInput(NAME_FULL, ASCIIToUTF16("B. Loblaw")); |
| |
| // Change both sections' countries. |
| view->SetTextContentsOfInput(ADDRESS_BILLING_COUNTRY, ASCIIToUTF16("France")); |
| view->ActivateInput(ADDRESS_BILLING_COUNTRY); |
| view->SetTextContentsOfInput(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("Belarus")); |
| view->ActivateInput(ADDRESS_HOME_COUNTRY); |
| |
| // Verify the name is still there. |
| EXPECT_EQ(ASCIIToUTF16("B. Loblaw"), view->GetTextContentsOfInput(NAME_FULL)); |
| |
| EXPECT_TRUE(SectionHasField(SECTION_BILLING, ADDRESS_BILLING_SORTING_CODE)); |
| EXPECT_TRUE(SectionHasField(SECTION_SHIPPING, ADDRESS_HOME_SORTING_CODE)); |
| } |
| |
| // Changing the data source to or from Wallet preserves the shipping country, |
| // but not the billing country because Wallet only supports US billing |
| // addresses. |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, |
| ChangingDataSourcePreservesCountry) { |
| InitializeControllerWithoutShowing(); |
| controller()->GetTestingManager()->set_default_country_code("CA"); |
| controller()->Show(); |
| CycleRunLoops(); |
| |
| AutofillProfile verified_profile(test::GetVerifiedProfile()); |
| controller()->GetTestingManager()->AddTestingProfile(&verified_profile); |
| |
| CreditCard verified_card(test::GetVerifiedCreditCard()); |
| controller()->GetTestingManager()->AddTestingCreditCard(&verified_card); |
| EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_SHIPPING)); |
| |
| controller()->OnDidFetchWalletCookieValue(std::string()); |
| scoped_ptr<wallet::WalletItems> items = |
| wallet::GetTestWalletItems(wallet::AMEX_DISALLOWED); |
| items->AddAccount(wallet::GetTestGaiaAccount()); |
| items->AddInstrument(wallet::GetTestMaskedInstrument()); |
| items->AddAddress(wallet::GetTestShippingAddress()); |
| controller()->OnDidGetWalletItems(items.Pass()); |
| |
| EXPECT_TRUE(controller()->IsPayingWithWallet()); |
| |
| // Select "Add new shipping address...". |
| controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(2); |
| EXPECT_TRUE(controller()->IsManuallyEditingSection(SECTION_SHIPPING)); |
| |
| // Default shipping country matches PDM's default, but default billing is |
| // always US in Wallet mode. |
| scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); |
| ASSERT_EQ(ASCIIToUTF16("Canada"), |
| view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY)); |
| ASSERT_EQ(ASCIIToUTF16("United States"), |
| view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY)); |
| |
| // Switch the shipping country. |
| view->SetTextContentsOfInput(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("Belarus")); |
| EXPECT_EQ(ASCIIToUTF16("Belarus"), |
| view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY)); |
| view->ActivateInput(ADDRESS_HOME_COUNTRY); |
| |
| // Switch to using Autofill instead of Wallet. |
| ui::MenuModel* account_chooser = controller()->MenuModelForAccountChooser(); |
| account_chooser->ActivatedAt(account_chooser->GetItemCount() - 1); |
| |
| EXPECT_FALSE(controller()->IsPayingWithWallet()); |
| |
| // Shipping country should have stayed the same. |
| EXPECT_EQ(ASCIIToUTF16("Belarus"), |
| view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY)); |
| ASSERT_TRUE(SectionHasField(SECTION_SHIPPING, ADDRESS_HOME_SORTING_CODE)); |
| |
| controller()->MenuModelForSection(SECTION_BILLING)->ActivatedAt(1); |
| view->SetTextContentsOfInput(ADDRESS_BILLING_COUNTRY, |
| ASCIIToUTF16("Belarus")); |
| view->ActivateInput(ADDRESS_BILLING_COUNTRY); |
| EXPECT_EQ(ASCIIToUTF16("Belarus"), |
| view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY)); |
| ASSERT_TRUE(SectionHasField(SECTION_BILLING, ADDRESS_BILLING_SORTING_CODE)); |
| |
| // Switch back to Wallet. Country should go back to US. |
| account_chooser->ActivatedAt(0); |
| EXPECT_EQ(ASCIIToUTF16("United States"), |
| view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY)); |
| ASSERT_FALSE( |
| SectionHasField(SECTION_CC_BILLING, ADDRESS_BILLING_SORTING_CODE)); |
| |
| // Make sure shipping is still on Belarus. |
| EXPECT_EQ(ASCIIToUTF16("Belarus"), |
| view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY)); |
| ASSERT_TRUE(SectionHasField(SECTION_SHIPPING, ADDRESS_HOME_SORTING_CODE)); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AddNewResetsCountry) { |
| AutofillProfile verified_profile(test::GetVerifiedProfile()); |
| controller()->GetTestingManager()->AddTestingProfile(&verified_profile); |
| |
| // Select "Add new billing/shipping address...". |
| controller()->MenuModelForSection(SECTION_BILLING)->ActivatedAt(1); |
| controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(2); |
| |
| scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); |
| ASSERT_EQ(ASCIIToUTF16("United States"), |
| view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY)); |
| ASSERT_EQ(ASCIIToUTF16("United States"), |
| view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY)); |
| |
| // Switch both billing and shipping countries. |
| view->SetTextContentsOfInput(ADDRESS_BILLING_COUNTRY, ASCIIToUTF16("Brazil")); |
| view->ActivateInput(ADDRESS_BILLING_COUNTRY); |
| view->SetTextContentsOfInput(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("France")); |
| view->ActivateInput(ADDRESS_HOME_COUNTRY); |
| |
| // Select "Add new billing/shipping address...". |
| controller()->MenuModelForSection(SECTION_BILLING)->ActivatedAt(1); |
| controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(2); |
| |
| EXPECT_EQ(ASCIIToUTF16("United States"), |
| view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY)); |
| EXPECT_EQ(ASCIIToUTF16("United States"), |
| view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY)); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, |
| FillingFormRebuildsInputs) { |
| AutofillProfile full_profile(test::GetFullProfile()); |
| full_profile.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("DE")); |
| controller()->GetTestingManager()->AddTestingProfile(&full_profile); |
| |
| // Select "Add new shipping address...". |
| controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(1); |
| |
| scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); |
| ASSERT_EQ(ASCIIToUTF16("United States"), |
| view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY)); |
| ASSERT_EQ(ASCIIToUTF16("United States"), |
| view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY)); |
| |
| const ServerFieldType input_type = EMAIL_ADDRESS; |
| base::string16 name = full_profile.GetRawInfo(input_type); |
| view->SetTextContentsOfInput(input_type, name.substr(0, name.size() / 2)); |
| view->ActivateInput(input_type); |
| ASSERT_EQ(input_type, controller()->popup_input_type()); |
| controller()->DidAcceptSuggestion(base::string16(), 0); |
| |
| EXPECT_EQ(ASCIIToUTF16("Germany"), |
| view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY)); |
| EXPECT_EQ(ASCIIToUTF16("United States"), |
| view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY)); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, |
| FillingFormPreservesChangedCountry) { |
| AutofillProfile full_profile(test::GetFullProfile()); |
| full_profile.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("DE")); |
| controller()->GetTestingManager()->AddTestingProfile(&full_profile); |
| |
| // Select "Add new shipping address...". |
| controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(1); |
| |
| scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); |
| view->SetTextContentsOfInput(ADDRESS_BILLING_COUNTRY, ASCIIToUTF16("France")); |
| view->ActivateInput(ADDRESS_BILLING_COUNTRY); |
| view->SetTextContentsOfInput(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("Belarus")); |
| view->ActivateInput(ADDRESS_HOME_COUNTRY); |
| |
| base::string16 name = full_profile.GetRawInfo(NAME_FULL); |
| view->SetTextContentsOfInput(NAME_FULL, name.substr(0, name.size() / 2)); |
| view->ActivateInput(NAME_FULL); |
| ASSERT_EQ(NAME_FULL, controller()->popup_input_type()); |
| controller()->DidAcceptSuggestion(base::string16(), 0); |
| |
| EXPECT_EQ(ASCIIToUTF16("France"), |
| view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY)); |
| EXPECT_EQ(ASCIIToUTF16("Belarus"), |
| view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY)); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, RulesLoaded) { |
| // Select "Add new shipping address...". |
| controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(1); |
| controller()->set_use_validation(true); |
| |
| EXPECT_CALL(*controller()->GetMockValidator(), |
| ValidateAddress(CountryCodeMatcher("DE"), _, _)).Times(2). |
| WillOnce(Return(AddressValidator::RULES_NOT_READY)); |
| |
| // Validation should occur on country change and see the rules haven't loaded. |
| scoped_ptr<AutofillDialogViewTester> view = GetViewTester(); |
| view->SetTextContentsOfInput(ADDRESS_HOME_ZIP, ASCIIToUTF16("123")); |
| view->SetTextContentsOfInput(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("Germany")); |
| view->ActivateInput(ADDRESS_HOME_COUNTRY); |
| |
| // Different country loaded, validation should not occur. |
| controller()->OnAddressValidationRulesLoaded("FR", true); |
| |
| // Relevant country loaded, validation should occur. |
| controller()->OnAddressValidationRulesLoaded("DE", true); |
| |
| // Relevant country loaded but revalidation already happened, no further |
| // validation should occur. |
| controller()->OnAddressValidationRulesLoaded("DE", false); |
| |
| // Cancelling the dialog causes additional validation to see if the user |
| // cancelled with invalid fields, so verify and clear here. |
| testing::Mock::VerifyAndClearExpectations(controller()->GetMockValidator()); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, |
| TransactionAmount) { |
| std::string html( |
| "<input type='number' step='0.01'" |
| " autocomplete='transaction-amount' value='24'>" |
| "<input autocomplete='transaction-currency' value='USD'>" |
| "<input autocomplete='cc-csc'>"); |
| AutofillDialogControllerImpl* controller = SetUpHtmlAndInvoke(html); |
| ASSERT_TRUE(controller); |
| |
| EXPECT_EQ(ASCIIToUTF16("24"), controller->transaction_amount_); |
| EXPECT_EQ(ASCIIToUTF16("USD"), controller->transaction_currency_); |
| } |
| |
| // Same as above, plus readonly attribute. |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, |
| TransactionAmountReadonly) { |
| std::string html( |
| "<input type='number' step='0.01'" |
| " autocomplete='transaction-amount' value='24' readonly>" |
| "<input autocomplete='transaction-currency' value='USD' readonly>" |
| "<input autocomplete='cc-csc'>"); |
| AutofillDialogControllerImpl* controller = SetUpHtmlAndInvoke(html); |
| ASSERT_TRUE(controller); |
| |
| EXPECT_EQ(ASCIIToUTF16("24"), controller->transaction_amount_); |
| EXPECT_EQ(ASCIIToUTF16("USD"), controller->transaction_currency_); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, HideOnNavigate) { |
| base::WeakPtr<TestAutofillDialogController> weak_ptr = |
| controller()->AsWeakPtr(); |
| EXPECT_TRUE(weak_ptr.get()); |
| |
| ui_test_utils::NavigateToURL(browser(), GURL("about:blank")); |
| EXPECT_FALSE(weak_ptr.get()); |
| } |
| |
| // Tests that the rAc dialog hides when the main frame is navigated, even if |
| // it was invoked from a child frame. |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, HideOnNavigateMainFrame) { |
| net::SpawnedTestServer http_server( |
| net::SpawnedTestServer::TYPE_HTTP, |
| net::SpawnedTestServer::kLocalhost, |
| base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); |
| ASSERT_TRUE(http_server.Start()); |
| RunTestPageInIframe(http_server); |
| |
| ui_test_utils::NavigateToURL(browser(), GURL("about:blank")); |
| ChromeAutofillClient* client = |
| ChromeAutofillClient::FromWebContents(GetActiveWebContents()); |
| EXPECT_FALSE(client->GetDialogControllerForTesting()); |
| } |
| |
| // Tests that the rAc dialog hides when the iframe it's in is navigated. |
| IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, HideOnNavigateIframe) { |
| net::SpawnedTestServer http_server( |
| net::SpawnedTestServer::TYPE_HTTP, |
| net::SpawnedTestServer::kLocalhost, |
| base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); |
| ASSERT_TRUE(http_server.Start()); |
| RunTestPageInIframe(http_server); |
| |
| std::string unused; |
| ASSERT_TRUE(content::ExecuteScriptAndExtractString(GetRenderViewHost(), |
| "navigateFrame();", |
| &unused)); |
| ExpectDomMessage("iframe loaded"); |
| ChromeAutofillClient* client = |
| ChromeAutofillClient::FromWebContents(GetActiveWebContents()); |
| EXPECT_FALSE(client->GetDialogControllerForTesting()); |
| } |
| |
| } // namespace autofill |