ExtensionSyncService: listen for relevant changes instead of being explicitly called...
[chromium-blink-merge.git] / chrome / browser / ui / autofill / autofill_dialog_controller_browsertest.cc
blob7eaf7c14e0249df6b767a5a10149fad0828105f9
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.
5 #include "base/bind.h"
6 #include "base/command_line.h"
7 #include "base/logging.h"
8 #include "base/memory/ref_counted.h"
9 #include "base/memory/weak_ptr.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/test/histogram_tester.h"
14 #include "base/time/time.h"
15 #include "chrome/browser/autofill/personal_data_manager_factory.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/signin/account_tracker_service_factory.h"
18 #include "chrome/browser/ui/autofill/autofill_dialog_controller_impl.h"
19 #include "chrome/browser/ui/autofill/autofill_dialog_i18n_input.h"
20 #include "chrome/browser/ui/autofill/autofill_dialog_view.h"
21 #include "chrome/browser/ui/autofill/autofill_dialog_view_tester.h"
22 #include "chrome/browser/ui/autofill/chrome_autofill_client.h"
23 #include "chrome/browser/ui/autofill/data_model_wrapper.h"
24 #include "chrome/browser/ui/autofill/mock_address_validator.h"
25 #include "chrome/browser/ui/browser.h"
26 #include "chrome/browser/ui/browser_tabstrip.h"
27 #include "chrome/browser/ui/tabs/tab_strip_model.h"
28 #include "chrome/common/chrome_switches.h"
29 #include "chrome/common/pref_names.h"
30 #include "chrome/common/url_constants.h"
31 #include "chrome/test/base/in_process_browser_test.h"
32 #include "chrome/test/base/ui_test_utils.h"
33 #include "components/autofill/content/browser/risk/proto/fingerprint.pb.h"
34 #include "components/autofill/core/browser/autofill_metrics.h"
35 #include "components/autofill/core/browser/autofill_test_utils.h"
36 #include "components/autofill/core/browser/test_personal_data_manager.h"
37 #include "components/autofill/core/browser/validation.h"
38 #include "components/autofill/core/common/autofill_switches.h"
39 #include "components/autofill/core/common/form_data.h"
40 #include "components/autofill/core/common/form_field_data.h"
41 #include "components/signin/core/browser/account_tracker_service.h"
42 #include "content/public/browser/browser_thread.h"
43 #include "content/public/browser/interstitial_page.h"
44 #include "content/public/browser/navigation_details.h"
45 #include "content/public/browser/navigation_entry.h"
46 #include "content/public/browser/notification_service.h"
47 #include "content/public/browser/notification_types.h"
48 #include "content/public/browser/page_navigator.h"
49 #include "content/public/browser/web_contents.h"
50 #include "content/public/browser/web_contents_delegate.h"
51 #include "content/public/common/content_switches.h"
52 #include "content/public/common/referrer.h"
53 #include "content/public/common/url_constants.h"
54 #include "content/public/test/browser_test_utils.h"
55 #include "content/public/test/test_utils.h"
56 #include "google_apis/gaia/google_service_auth_error.h"
57 #include "net/test/spawned_test_server/spawned_test_server.h"
58 #include "testing/gmock/include/gmock/gmock.h"
59 #include "testing/gtest/include/gtest/gtest.h"
60 #include "third_party/WebKit/public/web/WebInputEvent.h"
61 #include "ui/base/page_transition_types.h"
62 #include "ui/base/window_open_disposition.h"
63 #include "url/gurl.h"
65 #if defined(OS_WIN)
66 #include "base/win/windows_version.h"
67 #elif defined(OS_MACOSX)
68 #include "base/mac/scoped_nsautorelease_pool.h"
69 #include "chrome/browser/ui/cocoa/run_loop_testing.h"
70 #endif
72 using base::ASCIIToUTF16;
74 namespace autofill {
76 namespace {
78 using testing::Return;
79 using testing::_;
81 void MockCallback(AutofillClient::RequestAutocompleteResult,
82 const base::string16& message,
83 const FormStructure*) {
86 class TestAutofillDialogController : public AutofillDialogControllerImpl {
87 public:
88 TestAutofillDialogController(
89 content::WebContents* contents,
90 const FormData& form_data,
91 scoped_refptr<content::MessageLoopRunner> runner)
92 : AutofillDialogControllerImpl(contents,
93 form_data,
94 form_data.origin,
95 base::Bind(&MockCallback)),
96 message_loop_runner_(runner),
97 use_validation_(false),
98 sign_in_user_index_(0U),
99 weak_ptr_factory_(this) {
100 Profile* profile =
101 Profile::FromBrowserContext(contents->GetBrowserContext());
102 test_manager_.Init(
103 NULL,
104 profile->GetPrefs(),
105 AccountTrackerServiceFactory::GetForProfile(profile),
106 false);
109 ~TestAutofillDialogController() override {}
111 GURL FakeSignInUrl() const {
112 return GURL(chrome::kChromeUIVersionURL);
115 void ViewClosed() override {
116 message_loop_runner_->Quit();
117 AutofillDialogControllerImpl::ViewClosed();
120 base::string16 InputValidityMessage(
121 DialogSection section,
122 ServerFieldType type,
123 const base::string16& value) override {
124 if (!use_validation_)
125 return base::string16();
126 return AutofillDialogControllerImpl::InputValidityMessage(
127 section, type, value);
130 ValidityMessages InputsAreValid(
131 DialogSection section,
132 const FieldValueMap& inputs) override {
133 if (!use_validation_)
134 return ValidityMessages();
135 return AutofillDialogControllerImpl::InputsAreValid(section, inputs);
138 // Saving to Chrome is tested in AutofillDialogControllerImpl unit tests.
139 // TODO(estade): test that the view defaults to saving to Chrome.
140 bool ShouldOfferToSaveInChrome() const override {
141 return true;
144 // Increase visibility for testing.
145 using AutofillDialogControllerImpl::view;
146 using AutofillDialogControllerImpl::popup_input_type;
148 MOCK_METHOD0(LoadRiskFingerprintData, void());
150 std::vector<DialogNotification> CurrentNotifications() override {
151 return notifications_;
154 void set_notifications(const std::vector<DialogNotification>& notifications) {
155 notifications_ = notifications;
158 TestPersonalDataManager* GetTestingManager() {
159 return &test_manager_;
162 MockAddressValidator* GetMockValidator() {
163 return &mock_validator_;
166 using AutofillDialogControllerImpl::IsEditingExistingData;
167 using AutofillDialogControllerImpl::IsManuallyEditingSection;
169 void set_use_validation(bool use_validation) {
170 use_validation_ = use_validation;
173 base::WeakPtr<TestAutofillDialogController> AsWeakPtr() {
174 return weak_ptr_factory_.GetWeakPtr();
177 protected:
178 PersonalDataManager* GetManager() const override {
179 return &const_cast<TestAutofillDialogController*>(this)->test_manager_;
182 AddressValidator* GetValidator() override {
183 return &mock_validator_;
186 private:
187 TestPersonalDataManager test_manager_;
188 testing::NiceMock<MockAddressValidator> mock_validator_;
189 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
190 bool use_validation_;
192 // A list of notifications to show in the notification area of the dialog.
193 // This is used to control what |CurrentNotifications()| returns for testing.
194 std::vector<DialogNotification> notifications_;
196 // The user index that is assigned in IsSignInContinueUrl().
197 size_t sign_in_user_index_;
199 // Allows generation of WeakPtrs, so controller liveness can be tested.
200 base::WeakPtrFactory<TestAutofillDialogController> weak_ptr_factory_;
202 DISALLOW_COPY_AND_ASSIGN(TestAutofillDialogController);
205 // This is a copy of ui_test_utils::UrlLoadObserver, except it observes
206 // NAV_ENTRY_COMMITTED instead of LOAD_STOP. This is to match the notification
207 // that AutofillDialogControllerImpl observes. Since NAV_ENTRY_COMMITTED comes
208 // before LOAD_STOP, and the controller deletes the web contents after receiving
209 // the former, we will sometimes fail to observe a LOAD_STOP.
210 // TODO(estade): Should the controller observe LOAD_STOP instead?
211 class NavEntryCommittedObserver : public content::WindowedNotificationObserver {
212 public:
213 NavEntryCommittedObserver(const GURL& url,
214 const content::NotificationSource& source)
215 : WindowedNotificationObserver(content::NOTIFICATION_NAV_ENTRY_COMMITTED,
216 source),
217 url_(url) {}
219 ~NavEntryCommittedObserver() override {}
221 // content::NotificationObserver:
222 void Observe(int type,
223 const content::NotificationSource& source,
224 const content::NotificationDetails& details) override {
225 content::LoadCommittedDetails* load_details =
226 content::Details<content::LoadCommittedDetails>(details).ptr();
227 if (load_details->entry->GetVirtualURL() != url_)
228 return;
230 WindowedNotificationObserver::Observe(type, source, details);
233 private:
234 GURL url_;
236 DISALLOW_COPY_AND_ASSIGN(NavEntryCommittedObserver);
239 } // namespace
241 class AutofillDialogControllerTest : public InProcessBrowserTest {
242 public:
243 AutofillDialogControllerTest() : controller_(NULL) {}
244 ~AutofillDialogControllerTest() override {}
246 void SetUpCommandLine(base::CommandLine* command_line) override {
247 command_line->AppendSwitch(::switches::kReduceSecurityForTesting);
250 void SetUpOnMainThread() override {
251 autofill::test::DisableSystemServices(browser()->profile()->GetPrefs());
252 InitializeController();
255 protected:
256 bool SectionHasField(DialogSection section, ServerFieldType type) {
257 const DetailInputs& fields =
258 controller()->RequestedFieldsForSection(section);
259 for (size_t i = 0; i < fields.size(); ++i) {
260 if (type == fields[i].type)
261 return true;
263 return false;
266 // A helper function that cycles the MessageLoop, and on Mac, the Cocoa run
267 // loop. It also drains the NSAutoreleasePool.
268 void CycleRunLoops() {
269 content::RunAllPendingInMessageLoop();
270 #if defined(OS_MACOSX)
271 chrome::testing::NSRunLoopRunAllPending();
272 AutoreleasePool()->Recycle();
273 #endif
276 void InitializeControllerWithoutShowing() {
277 if (controller_)
278 controller_->Hide();
280 FormData form;
281 form.name = ASCIIToUTF16("TestForm");
283 FormFieldData field;
284 field.autocomplete_attribute = "shipping tel";
285 form.fields.push_back(field);
287 FormFieldData cc;
288 cc.autocomplete_attribute = "cc-number";
289 form.fields.push_back(cc);
291 message_loop_runner_ = new content::MessageLoopRunner;
292 controller_ = new TestAutofillDialogController(
293 GetActiveWebContents(),
294 form,
295 message_loop_runner_);
298 void InitializeController() {
299 InitializeControllerWithoutShowing();
300 controller_->Show();
301 CycleRunLoops(); // Ensures dialog is fully visible.
304 content::WebContents* GetActiveWebContents() {
305 return browser()->tab_strip_model()->GetActiveWebContents();
308 content::RenderViewHost* GetRenderViewHost() {
309 return GetActiveWebContents()->GetRenderViewHost();
312 scoped_ptr<AutofillDialogViewTester> GetViewTester() {
313 return AutofillDialogViewTester::For(controller()->view()).Pass();
316 TestAutofillDialogController* controller() { return controller_; }
318 void RunMessageLoop() {
319 message_loop_runner_->Run();
322 // Loads an HTML page in |GetActiveWebContents()| with markup as follows:
323 // <form>|form_inner_html|</form>. After loading, emulates a click event on
324 // the page as requestAutocomplete() must be in response to a user gesture.
325 // Returns the |AutofillDialogControllerImpl| created by this invocation.
326 AutofillDialogControllerImpl* SetUpHtmlAndInvoke(
327 const std::string& form_inner_html) {
328 content::WebContents* contents = GetActiveWebContents();
329 ChromeAutofillClient* client =
330 ChromeAutofillClient::FromWebContents(contents);
331 CHECK(!client->GetDialogControllerForTesting());
333 ui_test_utils::NavigateToURL(
334 browser(), GURL(std::string("data:text/html,") +
335 "<!doctype html>"
336 "<html>"
337 "<body>"
338 "<form>" + form_inner_html + "</form>"
339 "<script>"
340 "var invalidEvents = [];"
341 "function recordInvalid(e) {"
342 "if (e.type != 'invalid') throw 'only invalid events allowed';"
343 "invalidEvents.push(e);"
345 "function send(msg) {"
346 "domAutomationController.setAutomationId(0);"
347 "domAutomationController.send(msg);"
349 "document.forms[0].onautocompleteerror = function(e) {"
350 "send('error: ' + e.reason);"
351 "};"
352 "document.forms[0].onautocomplete = function() {"
353 "send('success');"
354 "};"
355 "window.onclick = function() {"
356 "var inputs = document.forms[0].querySelectorAll('input');"
357 "for (var i = 0; i < inputs.length; ++i) {"
358 "inputs[i].oninvalid = recordInvalid;"
360 "document.forms[0].requestAutocomplete();"
361 "send('clicked');"
362 "};"
363 "function loadIframe() {"
364 " var iframe = document.createElement('iframe');"
365 " iframe.onload = function() {"
366 " send('iframe loaded');"
367 " };"
368 " iframe.src = 'about:blank';"
369 " document.body.appendChild(iframe);"
371 "function getValueForFieldOfType(type) {"
372 " var fields = document.getElementsByTagName('input');"
373 " for (var i = 0; i < fields.length; i++) {"
374 " if (fields[i].autocomplete == type) {"
375 " send(fields[i].value);"
376 " return;"
377 " }"
378 " }"
379 " send('');"
380 "};"
381 "</script>"
382 "</body>"
383 "</html>"));
385 InitiateDialog();
386 AutofillDialogControllerImpl* controller =
387 static_cast<AutofillDialogControllerImpl*>(
388 client->GetDialogControllerForTesting());
389 return controller;
392 // Loads an html page on a provided server, the causes it to launch rAc.
393 // Returns whether rAc succesfully launched.
394 bool RunTestPage(const net::SpawnedTestServer& server) {
395 GURL url = server.GetURL(
396 "files/request_autocomplete/test_page.html");
397 ui_test_utils::NavigateToURL(browser(), url);
399 // Pass through the broken SSL interstitial, if any.
400 content::WebContents* contents = GetActiveWebContents();
401 content::InterstitialPage* interstitial_page =
402 contents->GetInterstitialPage();
403 if (interstitial_page) {
404 ui_test_utils::UrlLoadObserver observer(
405 url,
406 content::Source<content::NavigationController>(
407 &contents->GetController()));
408 interstitial_page->Proceed();
409 observer.Wait();
412 InitiateDialog();
414 ChromeAutofillClient* client =
415 ChromeAutofillClient::FromWebContents(contents);
416 AutofillDialogControllerImpl* controller =
417 static_cast<AutofillDialogControllerImpl*>(
418 client->GetDialogControllerForTesting());
419 return !!controller;
422 void RunTestPageInIframe(const net::SpawnedTestServer& server) {
423 InitializeDOMMessageQueue();
424 GURL iframe_url = server.GetURL(
425 "files/request_autocomplete/test_page.html");
427 ui_test_utils::NavigateToURL(
428 browser(), GURL(std::string("data:text/html,") +
429 "<!doctype html>"
430 "<html>"
431 "<body>"
432 "<iframe style='position: fixed;"
433 "height: 100%;"
434 "width: 100%;'"
435 "id='racFrame'></iframe>"
436 "<script>"
437 "function send(msg) {"
438 "domAutomationController.setAutomationId(0);"
439 "domAutomationController.send(msg);"
441 "var racFrame = document.getElementById('racFrame');"
442 "racFrame.onload = function() {"
443 "send('iframe loaded');"
444 "};"
445 "racFrame.src = \"" + iframe_url.spec() + "\";"
446 "function navigateFrame() {"
447 "racFrame.src = 'about:blank';"
449 "</script>"
450 "</body>"
451 "</html>"));
453 ChromeAutofillClient* client =
454 ChromeAutofillClient::FromWebContents(GetActiveWebContents());
455 ExpectDomMessage("iframe loaded");
456 EXPECT_FALSE(client->GetDialogControllerForTesting());
457 InitiateDialog();
458 EXPECT_TRUE(client->GetDialogControllerForTesting());
461 // Wait for a message from the DOM automation controller (from JS in the
462 // page). Requires |SetUpHtmlAndInvoke()| be called first.
463 void ExpectDomMessage(const std::string& expected) {
464 std::string message;
465 ASSERT_TRUE(dom_message_queue_->WaitForMessage(&message));
466 dom_message_queue_->ClearQueue();
467 EXPECT_EQ("\"" + expected + "\"", message);
470 void InitiateDialog() {
471 InitializeDOMMessageQueue();
472 // Triggers the onclick handler which invokes requestAutocomplete().
473 content::WebContents* contents = GetActiveWebContents();
474 content::SimulateMouseClick(contents, 0, blink::WebMouseEvent::ButtonLeft);
475 ExpectDomMessage("clicked");
478 void InitializeDOMMessageQueue() {
479 dom_message_queue_.reset(new content::DOMMessageQueue);
482 // Returns the value filled into the first field with autocomplete attribute
483 // equal to |autocomplete_type|, or an empty string if there is no such field.
484 std::string GetValueForHTMLFieldOfType(const std::string& autocomplete_type) {
485 std::string script = "getValueForFieldOfType('" + autocomplete_type + "');";
486 std::string result;
487 EXPECT_TRUE(content::ExecuteScriptAndExtractString(GetRenderViewHost(),
488 script,
489 &result));
490 return result;
493 void AddCreditcardToProfile(Profile* profile, const CreditCard& card) {
494 PersonalDataManagerFactory::GetForProfile(profile)->AddCreditCard(card);
495 WaitForWebDB();
498 void AddAutofillProfileToProfile(Profile* profile,
499 const AutofillProfile& autofill_profile) {
500 PersonalDataManagerFactory::GetForProfile(profile)->AddProfile(
501 autofill_profile);
502 WaitForWebDB();
505 private:
506 void WaitForWebDB() {
507 content::RunAllPendingInMessageLoop(content::BrowserThread::DB);
510 TestAutofillDialogController* controller_; // Weak reference.
511 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
512 scoped_ptr<content::DOMMessageQueue> dom_message_queue_;
514 DISALLOW_COPY_AND_ASSIGN(AutofillDialogControllerTest);
517 // Submit the form data.
518 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, Submit) {
519 base::HistogramTester histogram;
520 AddCreditcardToProfile(controller()->profile(),
521 test::GetVerifiedCreditCard());
522 AddAutofillProfileToProfile(controller()->profile(),
523 test::GetVerifiedProfile());
524 scoped_ptr<AutofillDialogViewTester> view = AutofillDialogViewTester::For(
525 static_cast<TestAutofillDialogController*>(controller())->view());
526 view->SetTextContentsOfSuggestionInput(SECTION_CC, ASCIIToUTF16("123"));
527 GetViewTester()->SubmitForTesting();
528 RunMessageLoop();
530 histogram.ExpectTotalCount("RequestAutocomplete.UiDuration.Submit", 1);
531 histogram.ExpectTotalCount("RequestAutocomplete.UiDuration.Cancel", 0);
534 // Cancel out of the dialog.
535 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, Cancel) {
536 base::HistogramTester histogram;
537 GetViewTester()->CancelForTesting();
538 RunMessageLoop();
540 histogram.ExpectTotalCount("RequestAutocomplete.UiDuration.Submit", 0);
541 histogram.ExpectTotalCount("RequestAutocomplete.UiDuration.Cancel", 1);
542 histogram.ExpectUniqueSample(
543 "RequestAutocomplete.DismissalState",
544 AutofillMetrics::DIALOG_CANCELED_NO_INVALID_FIELDS, 1);
547 // Take some other action that dismisses the dialog.
548 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, Hide) {
549 base::HistogramTester histogram;
550 controller()->Hide();
552 RunMessageLoop();
554 histogram.ExpectTotalCount("RequestAutocomplete.UiDuration.Submit", 0);
555 histogram.ExpectTotalCount("RequestAutocomplete.UiDuration.Cancel", 1);
556 histogram.ExpectUniqueSample(
557 "RequestAutocomplete.DismissalState",
558 AutofillMetrics::DIALOG_CANCELED_NO_INVALID_FIELDS, 1);
561 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, CancelWithSuggestions) {
562 base::HistogramTester histogram;
564 CreditCard card(test::GetVerifiedCreditCard());
565 controller()->GetTestingManager()->AddTestingCreditCard(&card);
566 AutofillProfile profile(test::GetVerifiedProfile());
567 controller()->GetTestingManager()->AddTestingProfile(&profile);
569 EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_CC));
570 EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_BILLING));
571 EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_SHIPPING));
573 GetViewTester()->CancelForTesting();
574 RunMessageLoop();
576 histogram.ExpectTotalCount("RequestAutocomplete.UiDuration.Submit", 0);
577 histogram.ExpectTotalCount("RequestAutocomplete.UiDuration.Cancel", 1);
578 histogram.ExpectUniqueSample("RequestAutocomplete.DismissalState",
579 AutofillMetrics::DIALOG_CANCELED_NO_EDITS, 1);
582 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AcceptWithSuggestions) {
583 base::HistogramTester histogram;
584 CreditCard card(test::GetVerifiedCreditCard());
585 controller()->GetTestingManager()->AddTestingCreditCard(&card);
586 AutofillProfile profile(test::GetVerifiedProfile());
587 controller()->GetTestingManager()->AddTestingProfile(&profile);
589 EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_CC));
590 EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_BILLING));
591 EXPECT_FALSE(controller()->IsManuallyEditingSection(SECTION_SHIPPING));
593 GetViewTester()->SubmitForTesting();
594 RunMessageLoop();
596 histogram.ExpectTotalCount("RequestAutocomplete.UiDuration.Submit", 1);
597 histogram.ExpectTotalCount("RequestAutocomplete.UiDuration.Cancel", 0);
598 histogram.ExpectUniqueSample(
599 "RequestAutocomplete.DismissalState",
600 AutofillMetrics::DIALOG_ACCEPTED_EXISTING_AUTOFILL_DATA, 1);
603 // Ensure that Hide() will only destroy the controller object after the
604 // message loop has run. Otherwise, there may be read-after-free issues
605 // during some tests.
606 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, DeferredDestruction) {
607 base::WeakPtr<TestAutofillDialogController> weak_ptr =
608 controller()->AsWeakPtr();
609 EXPECT_TRUE(weak_ptr.get());
611 controller()->Hide();
612 EXPECT_TRUE(weak_ptr.get());
614 RunMessageLoop();
615 EXPECT_FALSE(weak_ptr.get());
618 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, FillInputFromAutofill) {
619 AutofillProfile full_profile(test::GetFullProfile());
620 const base::string16 formatted_phone(ASCIIToUTF16("+1 (310) 555 1234"));
621 full_profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, formatted_phone);
622 controller()->GetTestingManager()->AddTestingProfile(&full_profile);
624 // Dialog is already asking for a new billing address.
625 EXPECT_TRUE(controller()->IsManuallyEditingSection(SECTION_BILLING));
627 // Select "Add new shipping address...".
628 ui::MenuModel* model = controller()->MenuModelForSection(SECTION_SHIPPING);
629 model->ActivatedAt(model->GetItemCount() - 2);
630 ASSERT_TRUE(controller()->IsManuallyEditingSection(SECTION_SHIPPING));
632 // Enter something in a shipping input.
633 const DetailInputs& inputs =
634 controller()->RequestedFieldsForSection(SECTION_SHIPPING);
635 const ServerFieldType triggering_type = inputs[0].type;
636 base::string16 value = full_profile.GetRawInfo(triggering_type);
637 scoped_ptr<AutofillDialogViewTester> view = GetViewTester();
638 view->SetTextContentsOfInput(triggering_type,
639 value.substr(0, value.size() / 2));
640 view->ActivateInput(triggering_type);
642 ASSERT_EQ(triggering_type, controller()->popup_input_type());
643 controller()->DidAcceptSuggestion(base::string16(), 0, 1);
645 // All inputs should be filled.
646 AutofillProfileWrapper wrapper(&full_profile);
647 for (size_t i = 0; i < inputs.size(); ++i) {
648 EXPECT_EQ(wrapper.GetInfoForDisplay(AutofillType(inputs[i].type)),
649 view->GetTextContentsOfInput(inputs[i].type));
651 // Double check the correct formatting is used for the phone number.
652 if (inputs[i].type == PHONE_HOME_WHOLE_NUMBER)
653 EXPECT_EQ(formatted_phone, view->GetTextContentsOfInput(inputs[i].type));
656 // Inputs from the other section (billing) should be left alone.
657 const DetailInputs& other_section_inputs =
658 controller()->RequestedFieldsForSection(SECTION_BILLING);
659 for (size_t i = 0; i < inputs.size(); ++i) {
660 base::string16 input_value =
661 view->GetTextContentsOfInput(other_section_inputs[i].type);
662 // If there's a combobox, the string should be non-empty.
663 if (controller()->ComboboxModelForAutofillType(
664 other_section_inputs[i].type)) {
665 EXPECT_NE(base::string16(), input_value);
666 } else {
667 EXPECT_EQ(base::string16(), input_value);
671 // Now simulate some user edits and try again.
672 std::vector<base::string16> expectations;
673 for (size_t i = 0; i < inputs.size(); ++i) {
674 if (controller()->ComboboxModelForAutofillType(inputs[i].type)) {
675 expectations.push_back(base::string16());
676 continue;
678 base::string16 users_input = i % 2 == 0 ? base::string16()
679 : ASCIIToUTF16("dummy");
680 view->SetTextContentsOfInput(inputs[i].type, users_input);
681 // Empty inputs should be filled, others should be left alone.
682 base::string16 expectation =
683 inputs[i].type == triggering_type || users_input.empty() ?
684 wrapper.GetInfoForDisplay(AutofillType(inputs[i].type)) :
685 users_input;
686 expectations.push_back(expectation);
689 view->SetTextContentsOfInput(triggering_type,
690 value.substr(0, value.size() / 2));
691 view->ActivateInput(triggering_type);
692 ASSERT_EQ(triggering_type, controller()->popup_input_type());
693 controller()->DidAcceptSuggestion(base::string16(), 0, 1);
695 for (size_t i = 0; i < inputs.size(); ++i) {
696 if (controller()->ComboboxModelForAutofillType(inputs[i].type))
697 continue;
698 EXPECT_EQ(expectations[i], view->GetTextContentsOfInput(inputs[i].type));
701 base::HistogramTester histogram;
702 view->SubmitForTesting();
703 histogram.ExpectUniqueSample(
704 "RequestAutocomplete.DismissalState",
705 AutofillMetrics::DIALOG_ACCEPTED_SAVE_TO_AUTOFILL, 1);
708 // Tests that changing the value of a CC expiration date combobox works as
709 // expected when Autofill is used to fill text inputs.
711 // Flaky on Win7, WinXP, and Win Aura. http://crbug.com/270314.
712 #if defined(OS_WIN)
713 #define MAYBE_FillComboboxFromAutofill DISABLED_FillComboboxFromAutofill
714 #else
715 #define MAYBE_FillComboboxFromAutofill FillComboboxFromAutofill
716 #endif
717 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
718 MAYBE_FillComboboxFromAutofill) {
719 CreditCard card1;
720 test::SetCreditCardInfo(&card1, "JJ Smith", "4111111111111111", "12", "2018");
721 controller()->GetTestingManager()->AddTestingCreditCard(&card1);
722 CreditCard card2;
723 test::SetCreditCardInfo(&card2, "B Bird", "3111111111111111", "11", "2017");
724 controller()->GetTestingManager()->AddTestingCreditCard(&card2);
725 AutofillProfile full_profile(test::GetFullProfile());
726 controller()->GetTestingManager()->AddTestingProfile(&full_profile);
728 const DetailInputs& inputs =
729 controller()->RequestedFieldsForSection(SECTION_CC);
730 const ServerFieldType triggering_type = inputs[0].type;
731 base::string16 value = card1.GetRawInfo(triggering_type);
732 scoped_ptr<AutofillDialogViewTester> view = GetViewTester();
733 view->SetTextContentsOfInput(triggering_type,
734 value.substr(0, value.size() / 2));
735 view->ActivateInput(triggering_type);
737 ASSERT_EQ(triggering_type, controller()->popup_input_type());
738 controller()->DidAcceptSuggestion(base::string16(), 0, 1);
740 // All inputs should be filled.
741 AutofillCreditCardWrapper wrapper1(&card1);
742 for (size_t i = 0; i < inputs.size(); ++i) {
743 EXPECT_EQ(wrapper1.GetInfo(AutofillType(inputs[i].type)),
744 view->GetTextContentsOfInput(inputs[i].type));
747 // Try again with different data. Only expiration date and the triggering
748 // input should be overwritten.
749 value = card2.GetRawInfo(triggering_type);
750 view->SetTextContentsOfInput(triggering_type,
751 value.substr(0, value.size() / 2));
752 view->ActivateInput(triggering_type);
753 ASSERT_EQ(triggering_type, controller()->popup_input_type());
754 controller()->DidAcceptSuggestion(base::string16(), 0, 1);
756 AutofillCreditCardWrapper wrapper2(&card2);
757 for (size_t i = 0; i < inputs.size(); ++i) {
758 const ServerFieldType type = inputs[i].type;
759 if (type == triggering_type ||
760 type == CREDIT_CARD_EXP_MONTH ||
761 type == CREDIT_CARD_EXP_4_DIGIT_YEAR) {
762 EXPECT_EQ(wrapper2.GetInfo(AutofillType(type)),
763 view->GetTextContentsOfInput(type));
764 } else if (type == CREDIT_CARD_VERIFICATION_CODE) {
765 EXPECT_TRUE(view->GetTextContentsOfInput(type).empty());
766 } else {
767 EXPECT_EQ(wrapper1.GetInfo(AutofillType(type)),
768 view->GetTextContentsOfInput(type));
772 // Now fill from a profile. It should not overwrite any CC info.
773 const DetailInputs& billing_inputs =
774 controller()->RequestedFieldsForSection(SECTION_BILLING);
775 const ServerFieldType billing_triggering_type = billing_inputs[0].type;
776 value = full_profile.GetRawInfo(triggering_type);
777 view->SetTextContentsOfInput(billing_triggering_type,
778 value.substr(0, value.size() / 2));
779 view->ActivateInput(billing_triggering_type);
781 ASSERT_EQ(billing_triggering_type, controller()->popup_input_type());
782 controller()->DidAcceptSuggestion(base::string16(), 0, 1);
784 for (size_t i = 0; i < inputs.size(); ++i) {
785 const ServerFieldType type = inputs[i].type;
786 if (type == triggering_type ||
787 type == CREDIT_CARD_EXP_MONTH ||
788 type == CREDIT_CARD_EXP_4_DIGIT_YEAR) {
789 EXPECT_EQ(wrapper2.GetInfo(AutofillType(type)),
790 view->GetTextContentsOfInput(type));
791 } else if (type == CREDIT_CARD_VERIFICATION_CODE) {
792 EXPECT_TRUE(view->GetTextContentsOfInput(type).empty());
793 } else {
794 EXPECT_EQ(wrapper1.GetInfo(AutofillType(type)),
795 view->GetTextContentsOfInput(type));
800 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, ShouldShowErrorBubble) {
801 controller()->set_use_validation(true);
802 EXPECT_TRUE(controller()->ShouldShowErrorBubble());
804 CreditCard card(test::GetCreditCard());
805 ASSERT_FALSE(card.IsVerified());
806 controller()->GetTestingManager()->AddTestingCreditCard(&card);
808 EXPECT_TRUE(controller()->IsManuallyEditingSection(SECTION_CC));
809 scoped_ptr<AutofillDialogViewTester> view = GetViewTester();
810 view->SetTextContentsOfInput(
811 CREDIT_CARD_NUMBER,
812 card.GetRawInfo(CREDIT_CARD_NUMBER).substr(0, 1));
814 view->ActivateInput(CREDIT_CARD_NUMBER);
815 EXPECT_FALSE(controller()->ShouldShowErrorBubble());
817 controller()->FocusMoved();
818 EXPECT_TRUE(controller()->ShouldShowErrorBubble());
820 base::HistogramTester histogram;
821 controller()->Hide();
822 histogram.ExpectUniqueSample(
823 "RequestAutocomplete.DismissalState",
824 AutofillMetrics::DIALOG_CANCELED_WITH_INVALID_FIELDS, 1);
827 // Ensure that expired cards trigger invalid suggestions.
828 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, ExpiredCard) {
829 CreditCard verified_card(test::GetCreditCard());
830 verified_card.set_origin("Chrome settings");
831 ASSERT_TRUE(verified_card.IsVerified());
832 controller()->GetTestingManager()->AddTestingCreditCard(&verified_card);
834 CreditCard expired_card(test::GetCreditCard());
835 expired_card.set_origin("Chrome settings");
836 expired_card.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2007"));
837 ASSERT_TRUE(expired_card.IsVerified());
838 ASSERT_FALSE(
839 autofill::IsValidCreditCardExpirationDate(
840 expired_card.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR),
841 expired_card.GetRawInfo(CREDIT_CARD_EXP_MONTH),
842 base::Time::Now()));
843 controller()->GetTestingManager()->AddTestingCreditCard(&expired_card);
845 ui::MenuModel* model = controller()->MenuModelForSection(SECTION_CC);
846 ASSERT_EQ(4, model->GetItemCount());
848 ASSERT_TRUE(model->IsItemCheckedAt(0));
849 EXPECT_FALSE(controller()->IsEditingExistingData(SECTION_CC));
851 model->ActivatedAt(1);
852 ASSERT_TRUE(model->IsItemCheckedAt(1));
853 EXPECT_TRUE(controller()->IsEditingExistingData(SECTION_CC));
856 // Notifications with long message text should not make the dialog bigger.
857 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, LongNotifications) {
858 const gfx::Size no_notification_size = GetViewTester()->GetSize();
859 ASSERT_GT(no_notification_size.width(), 0);
861 std::vector<DialogNotification> notifications;
862 notifications.push_back(
863 DialogNotification(DialogNotification::DEVELOPER_WARNING, ASCIIToUTF16(
864 "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do "
865 "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim "
866 "ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut "
867 "aliquip ex ea commodo consequat. Duis aute irure dolor in "
868 "reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla "
869 "pariatur. Excepteur sint occaecat cupidatat non proident, sunt in "
870 "culpa qui officia deserunt mollit anim id est laborum.")));
871 controller()->set_notifications(notifications);
872 controller()->view()->UpdateNotificationArea();
874 EXPECT_EQ(no_notification_size.width(),
875 GetViewTester()->GetSize().width());
878 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AutocompleteEvent) {
879 AutofillDialogControllerImpl* controller =
880 SetUpHtmlAndInvoke("<input autocomplete='cc-name'>");
881 ASSERT_TRUE(controller);
883 AddCreditcardToProfile(controller->profile(), test::GetVerifiedCreditCard());
884 AddAutofillProfileToProfile(controller->profile(),
885 test::GetVerifiedProfile());
887 scoped_ptr<AutofillDialogViewTester> view =
888 AutofillDialogViewTester::For(
889 static_cast<TestAutofillDialogController*>(controller)->view());
890 view->SetTextContentsOfSuggestionInput(SECTION_CC, ASCIIToUTF16("123"));
891 view->SubmitForTesting();
892 ExpectDomMessage("success");
895 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
896 AutocompleteErrorEventReasonInvalid) {
897 AutofillDialogControllerImpl* controller =
898 SetUpHtmlAndInvoke("<input autocomplete='cc-name' pattern='.*zebra.*'>");
899 ASSERT_TRUE(controller);
901 const CreditCard& credit_card = test::GetVerifiedCreditCard();
902 ASSERT_TRUE(
903 credit_card.GetRawInfo(CREDIT_CARD_NAME).find(ASCIIToUTF16("zebra")) ==
904 base::string16::npos);
905 AddCreditcardToProfile(controller->profile(), credit_card);
906 AddAutofillProfileToProfile(controller->profile(),
907 test::GetVerifiedProfile());
909 scoped_ptr<AutofillDialogViewTester> view =
910 AutofillDialogViewTester::For(
911 static_cast<TestAutofillDialogController*>(controller)->view());
912 view->SetTextContentsOfSuggestionInput(SECTION_CC, ASCIIToUTF16("123"));
913 view->SubmitForTesting();
914 ExpectDomMessage("error: invalid");
916 int invalid_count = -1;
917 ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
918 GetRenderViewHost(), "send(invalidEvents.length);", &invalid_count));
919 EXPECT_EQ(1, invalid_count);
921 std::string invalid_type;
922 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
923 GetRenderViewHost(),
924 "send(invalidEvents[0].target.autocomplete);",
925 &invalid_type));
926 EXPECT_EQ("cc-name", invalid_type);
929 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
930 AutocompleteErrorEventReasonCancel) {
931 AutofillDialogControllerImpl* controller =
932 SetUpHtmlAndInvoke("<input autocomplete='cc-name'>");
933 ASSERT_TRUE(controller);
934 AutofillDialogViewTester::For(
935 static_cast<TestAutofillDialogController*>(controller)->view())->
936 CancelForTesting();
937 ExpectDomMessage("error: cancel");
940 // http://crbug.com/318526
941 #if defined(OS_MACOSX)
942 #define MAYBE_ErrorWithFrameNavigation DISABLED_ErrorWithFrameNavigation
943 #else
944 #define MAYBE_ErrorWithFrameNavigation ErrorWithFrameNavigation
945 #endif
946 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
947 MAYBE_ErrorWithFrameNavigation) {
948 AutofillDialogControllerImpl* controller =
949 SetUpHtmlAndInvoke("<input autocomplete='cc-name'>");
950 ASSERT_TRUE(controller);
952 std::string unused;
953 ASSERT_TRUE(content::ExecuteScriptAndExtractString(GetRenderViewHost(),
954 "loadIframe();",
955 &unused));
956 ExpectDomMessage("iframe loaded");
958 AutofillDialogViewTester::For(
959 static_cast<TestAutofillDialogController*>(controller)->view())->
960 CancelForTesting();
961 ExpectDomMessage("error: cancel");
964 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, NoCvcSegfault) {
965 controller()->set_use_validation(true);
967 CreditCard credit_card(test::GetVerifiedCreditCard());
968 controller()->GetTestingManager()->AddTestingCreditCard(&credit_card);
969 EXPECT_FALSE(controller()->IsEditingExistingData(SECTION_CC));
971 ASSERT_NO_FATAL_FAILURE(GetViewTester()->SubmitForTesting());
974 // Verify that filling a form works correctly, including filling the CVC when
975 // that is requested separately.
976 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
977 FillFormIncludesCVC) {
978 AutofillDialogControllerImpl* controller =
979 SetUpHtmlAndInvoke("<input autocomplete='cc-csc'>");
980 ASSERT_TRUE(controller);
982 AddCreditcardToProfile(controller->profile(), test::GetVerifiedCreditCard());
983 AddAutofillProfileToProfile(controller->profile(),
984 test::GetVerifiedProfile());
986 scoped_ptr<AutofillDialogViewTester> view =
987 AutofillDialogViewTester::For(
988 static_cast<TestAutofillDialogController*>(controller)->view());
989 view->SetTextContentsOfSuggestionInput(SECTION_CC, ASCIIToUTF16("123"));
990 view->SubmitForTesting();
991 ExpectDomMessage("success");
992 EXPECT_EQ("123", GetValueForHTMLFieldOfType("cc-csc"));
995 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AddNewClearsComboboxes) {
996 // Ensure the input under test is a combobox.
997 ASSERT_TRUE(
998 controller()->ComboboxModelForAutofillType(CREDIT_CARD_EXP_MONTH));
1000 // Set up an expired card.
1001 CreditCard card;
1002 test::SetCreditCardInfo(&card, "Roy Demeo", "4111111111111111", "8", "2013");
1003 card.set_origin("Chrome settings");
1004 ASSERT_TRUE(card.IsVerified());
1006 // Add the card and check that there's a menu for that section.
1007 controller()->GetTestingManager()->AddTestingCreditCard(&card);
1008 ASSERT_TRUE(controller()->MenuModelForSection(SECTION_CC));
1010 // Select the invalid, suggested card from the menu.
1011 controller()->MenuModelForSection(SECTION_CC)->ActivatedAt(0);
1012 EXPECT_TRUE(controller()->IsEditingExistingData(SECTION_CC));
1014 // Get the contents of the combobox of the credit card's expiration month.
1015 scoped_ptr<AutofillDialogViewTester> view = GetViewTester();
1016 base::string16 cc_exp_month_text =
1017 view->GetTextContentsOfInput(CREDIT_CARD_EXP_MONTH);
1019 // Select "New X..." from the suggestion menu to clear the section's inputs.
1020 controller()->MenuModelForSection(SECTION_CC)->ActivatedAt(1);
1021 EXPECT_FALSE(controller()->IsEditingExistingData(SECTION_CC));
1023 // Ensure that the credit card expiration month has changed.
1024 EXPECT_NE(cc_exp_month_text,
1025 view->GetTextContentsOfInput(CREDIT_CARD_EXP_MONTH));
1028 // Flaky on Win7 (http://crbug.com/446432)
1029 #if defined(OS_WIN)
1030 #define MAYBE_TabOpensToJustRight DISABLED_TabOpensToJustRight
1031 #else
1032 #define MAYBE_TabOpensToJustRight TabOpensToJustRight
1033 #endif
1034 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
1035 MAYBE_TabOpensToJustRight) {
1036 ASSERT_TRUE(browser()->is_type_tabbed());
1038 // Tabs should currently be: / rAc() \.
1039 content::WebContents* dialog_invoker = controller()->GetWebContents();
1040 EXPECT_EQ(dialog_invoker, GetActiveWebContents());
1042 TabStripModel* tab_strip = browser()->tab_strip_model();
1043 ASSERT_EQ(1, tab_strip->count());
1044 EXPECT_EQ(0, tab_strip->GetIndexOfWebContents(dialog_invoker));
1046 // Open a tab to about:blank in the background at the end of the tab strip.
1047 chrome::AddTabAt(browser(), GURL(), -1, false);
1048 // Tabs should now be: / rAc() \/ blank \.
1049 EXPECT_EQ(2, tab_strip->count());
1050 EXPECT_EQ(0, tab_strip->active_index());
1051 EXPECT_EQ(dialog_invoker, GetActiveWebContents());
1053 content::WebContents* blank_tab = tab_strip->GetWebContentsAt(1);
1055 // Simulate clicking "Manage X...".
1056 controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(2);
1057 // Tab should now be: / rAc() \/ manage 1 \/ blank \.
1058 EXPECT_EQ(3, tab_strip->count());
1059 int dialog_index = tab_strip->GetIndexOfWebContents(dialog_invoker);
1060 EXPECT_EQ(0, dialog_index);
1061 EXPECT_EQ(1, tab_strip->active_index());
1062 EXPECT_EQ(2, tab_strip->GetIndexOfWebContents(blank_tab));
1064 content::WebContents* first_manage_tab = tab_strip->GetWebContentsAt(1);
1066 // Re-activate the dialog's tab (like a user would have to).
1067 tab_strip->ActivateTabAt(dialog_index, true);
1068 EXPECT_EQ(dialog_invoker, GetActiveWebContents());
1070 // Simulate clicking "Manage X...".
1071 controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(2);
1072 // Tabs should now be: / rAc() \/ manage 2 \/ manage 1 \/ blank \.
1073 EXPECT_EQ(4, tab_strip->count());
1074 EXPECT_EQ(0, tab_strip->GetIndexOfWebContents(dialog_invoker));
1075 EXPECT_EQ(1, tab_strip->active_index());
1076 EXPECT_EQ(2, tab_strip->GetIndexOfWebContents(first_manage_tab));
1077 EXPECT_EQ(3, tab_strip->GetIndexOfWebContents(blank_tab));
1080 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
1081 DoesWorkOnHttpWithFlag) {
1082 net::SpawnedTestServer http_server(
1083 net::SpawnedTestServer::TYPE_HTTP,
1084 net::SpawnedTestServer::kLocalhost,
1085 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1086 ASSERT_TRUE(http_server.Start());
1087 EXPECT_TRUE(RunTestPage(http_server));
1090 // Like the parent test, but doesn't add the --reduce-security-for-testing flag.
1091 class AutofillDialogControllerSecurityTest :
1092 public AutofillDialogControllerTest {
1093 public:
1094 AutofillDialogControllerSecurityTest() {}
1095 ~AutofillDialogControllerSecurityTest() override {}
1097 void SetUpCommandLine(base::CommandLine* command_line) override {
1098 CHECK(!command_line->HasSwitch(::switches::kReduceSecurityForTesting));
1101 typedef net::BaseTestServer::SSLOptions SSLOptions;
1103 private:
1104 DISALLOW_COPY_AND_ASSIGN(AutofillDialogControllerSecurityTest);
1107 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerSecurityTest,
1108 DoesntWorkOnHttp) {
1109 net::SpawnedTestServer http_server(
1110 net::SpawnedTestServer::TYPE_HTTP,
1111 net::SpawnedTestServer::kLocalhost,
1112 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1113 ASSERT_TRUE(http_server.Start());
1114 EXPECT_FALSE(RunTestPage(http_server));
1117 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerSecurityTest,
1118 DoesWorkOnHttpWithFlags) {
1119 net::SpawnedTestServer https_server(
1120 net::SpawnedTestServer::TYPE_HTTPS,
1121 SSLOptions(SSLOptions::CERT_OK),
1122 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1123 ASSERT_TRUE(https_server.Start());
1124 EXPECT_TRUE(RunTestPage(https_server));
1127 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerSecurityTest,
1128 DISABLED_DoesntWorkOnBrokenHttps) {
1129 net::SpawnedTestServer https_server(
1130 net::SpawnedTestServer::TYPE_HTTPS,
1131 SSLOptions(SSLOptions::CERT_EXPIRED),
1132 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1133 ASSERT_TRUE(https_server.Start());
1134 EXPECT_FALSE(RunTestPage(https_server));
1137 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
1138 CountryChangeRebuildsSection) {
1139 EXPECT_FALSE(SectionHasField(SECTION_BILLING, ADDRESS_BILLING_SORTING_CODE));
1140 EXPECT_FALSE(SectionHasField(SECTION_SHIPPING, ADDRESS_HOME_SORTING_CODE));
1142 // Select "Add new shipping address...".
1143 controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(1);
1145 // Add some valid user input that should be preserved when country changes.
1146 scoped_ptr<AutofillDialogViewTester> view = GetViewTester();
1147 view->SetTextContentsOfInput(NAME_FULL, ASCIIToUTF16("B. Loblaw"));
1149 // Change both sections' countries.
1150 view->SetTextContentsOfInput(ADDRESS_BILLING_COUNTRY, ASCIIToUTF16("France"));
1151 view->ActivateInput(ADDRESS_BILLING_COUNTRY);
1152 view->SetTextContentsOfInput(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("Belarus"));
1153 view->ActivateInput(ADDRESS_HOME_COUNTRY);
1155 // Verify the name is still there.
1156 EXPECT_EQ(ASCIIToUTF16("B. Loblaw"), view->GetTextContentsOfInput(NAME_FULL));
1158 EXPECT_TRUE(SectionHasField(SECTION_BILLING, ADDRESS_BILLING_SORTING_CODE));
1159 EXPECT_TRUE(SectionHasField(SECTION_SHIPPING, ADDRESS_HOME_SORTING_CODE));
1162 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AddNewResetsCountry) {
1163 AutofillProfile verified_profile(test::GetVerifiedProfile());
1164 controller()->GetTestingManager()->AddTestingProfile(&verified_profile);
1166 // Select "Add new billing/shipping address...".
1167 controller()->MenuModelForSection(SECTION_BILLING)->ActivatedAt(1);
1168 controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(2);
1170 scoped_ptr<AutofillDialogViewTester> view = GetViewTester();
1171 ASSERT_EQ(ASCIIToUTF16("United States"),
1172 view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY));
1173 ASSERT_EQ(ASCIIToUTF16("United States"),
1174 view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY));
1176 // Switch both billing and shipping countries.
1177 view->SetTextContentsOfInput(ADDRESS_BILLING_COUNTRY, ASCIIToUTF16("Brazil"));
1178 view->ActivateInput(ADDRESS_BILLING_COUNTRY);
1179 view->SetTextContentsOfInput(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("France"));
1180 view->ActivateInput(ADDRESS_HOME_COUNTRY);
1182 // Select "Add new billing/shipping address...".
1183 controller()->MenuModelForSection(SECTION_BILLING)->ActivatedAt(1);
1184 controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(2);
1186 EXPECT_EQ(ASCIIToUTF16("United States"),
1187 view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY));
1188 EXPECT_EQ(ASCIIToUTF16("United States"),
1189 view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY));
1192 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
1193 FillingFormRebuildsInputs) {
1194 AutofillProfile full_profile(test::GetFullProfile());
1195 full_profile.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("DE"));
1196 controller()->GetTestingManager()->AddTestingProfile(&full_profile);
1198 // Select "Add new shipping address...".
1199 controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(1);
1201 scoped_ptr<AutofillDialogViewTester> view = GetViewTester();
1202 ASSERT_EQ(ASCIIToUTF16("United States"),
1203 view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY));
1204 ASSERT_EQ(ASCIIToUTF16("United States"),
1205 view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY));
1207 const ServerFieldType input_type = EMAIL_ADDRESS;
1208 base::string16 name = full_profile.GetRawInfo(input_type);
1209 view->SetTextContentsOfInput(input_type, name.substr(0, name.size() / 2));
1210 view->ActivateInput(input_type);
1211 ASSERT_EQ(input_type, controller()->popup_input_type());
1212 controller()->DidAcceptSuggestion(base::string16(), 0, 1);
1214 EXPECT_EQ(ASCIIToUTF16("Germany"),
1215 view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY));
1216 EXPECT_EQ(ASCIIToUTF16("United States"),
1217 view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY));
1220 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
1221 FillingFormPreservesChangedCountry) {
1222 AutofillProfile full_profile(test::GetFullProfile());
1223 full_profile.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("DE"));
1224 controller()->GetTestingManager()->AddTestingProfile(&full_profile);
1226 // Select "Add new shipping address...".
1227 controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(1);
1229 scoped_ptr<AutofillDialogViewTester> view = GetViewTester();
1230 view->SetTextContentsOfInput(ADDRESS_BILLING_COUNTRY, ASCIIToUTF16("France"));
1231 view->ActivateInput(ADDRESS_BILLING_COUNTRY);
1232 view->SetTextContentsOfInput(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("Belarus"));
1233 view->ActivateInput(ADDRESS_HOME_COUNTRY);
1235 base::string16 name = full_profile.GetRawInfo(NAME_FULL);
1236 view->SetTextContentsOfInput(NAME_FULL, name.substr(0, name.size() / 2));
1237 view->ActivateInput(NAME_FULL);
1238 ASSERT_EQ(NAME_FULL, controller()->popup_input_type());
1239 controller()->DidAcceptSuggestion(base::string16(), 0, 1);
1241 EXPECT_EQ(ASCIIToUTF16("France"),
1242 view->GetTextContentsOfInput(ADDRESS_BILLING_COUNTRY));
1243 EXPECT_EQ(ASCIIToUTF16("Belarus"),
1244 view->GetTextContentsOfInput(ADDRESS_HOME_COUNTRY));
1247 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, RulesLoaded) {
1248 // Select "Add new shipping address...".
1249 controller()->MenuModelForSection(SECTION_SHIPPING)->ActivatedAt(1);
1250 controller()->set_use_validation(true);
1252 EXPECT_CALL(*controller()->GetMockValidator(),
1253 ValidateAddress(CountryCodeMatcher("DE"), _, _)).Times(2).
1254 WillOnce(Return(AddressValidator::RULES_NOT_READY));
1256 // Validation should occur on country change and see the rules haven't loaded.
1257 scoped_ptr<AutofillDialogViewTester> view = GetViewTester();
1258 view->SetTextContentsOfInput(ADDRESS_HOME_ZIP, ASCIIToUTF16("123"));
1259 view->SetTextContentsOfInput(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("Germany"));
1260 view->ActivateInput(ADDRESS_HOME_COUNTRY);
1262 // Different country loaded, validation should not occur.
1263 controller()->OnAddressValidationRulesLoaded("FR", true);
1265 // Relevant country loaded, validation should occur.
1266 controller()->OnAddressValidationRulesLoaded("DE", true);
1268 // Relevant country loaded but revalidation already happened, no further
1269 // validation should occur.
1270 controller()->OnAddressValidationRulesLoaded("DE", false);
1272 // Cancelling the dialog causes additional validation to see if the user
1273 // cancelled with invalid fields, so verify and clear here.
1274 testing::Mock::VerifyAndClearExpectations(controller()->GetMockValidator());
1277 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
1278 TransactionAmount) {
1279 std::string html(
1280 "<input type='number' step='0.01'"
1281 " autocomplete='transaction-amount' value='24'>"
1282 "<input autocomplete='transaction-currency' value='USD'>"
1283 "<input autocomplete='cc-csc'>");
1284 AutofillDialogControllerImpl* controller = SetUpHtmlAndInvoke(html);
1285 ASSERT_TRUE(controller);
1287 EXPECT_EQ(ASCIIToUTF16("24"), controller->transaction_amount_);
1288 EXPECT_EQ(ASCIIToUTF16("USD"), controller->transaction_currency_);
1291 // Same as above, plus readonly attribute.
1292 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
1293 TransactionAmountReadonly) {
1294 std::string html(
1295 "<input type='number' step='0.01'"
1296 " autocomplete='transaction-amount' value='24' readonly>"
1297 "<input autocomplete='transaction-currency' value='USD' readonly>"
1298 "<input autocomplete='cc-csc'>");
1299 AutofillDialogControllerImpl* controller = SetUpHtmlAndInvoke(html);
1300 ASSERT_TRUE(controller);
1302 EXPECT_EQ(ASCIIToUTF16("24"), controller->transaction_amount_);
1303 EXPECT_EQ(ASCIIToUTF16("USD"), controller->transaction_currency_);
1306 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, HideOnNavigate) {
1307 base::WeakPtr<TestAutofillDialogController> weak_ptr =
1308 controller()->AsWeakPtr();
1309 EXPECT_TRUE(weak_ptr.get());
1311 ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
1312 EXPECT_FALSE(weak_ptr.get());
1315 // Tests that the rAc dialog hides when the main frame is navigated, even if
1316 // it was invoked from a child frame.
1317 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, HideOnNavigateMainFrame) {
1318 net::SpawnedTestServer http_server(
1319 net::SpawnedTestServer::TYPE_HTTP,
1320 net::SpawnedTestServer::kLocalhost,
1321 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1322 ASSERT_TRUE(http_server.Start());
1323 RunTestPageInIframe(http_server);
1325 ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
1326 ChromeAutofillClient* client =
1327 ChromeAutofillClient::FromWebContents(GetActiveWebContents());
1328 EXPECT_FALSE(client->GetDialogControllerForTesting());
1331 // Tests that the rAc dialog hides when the iframe it's in is navigated.
1332 IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, HideOnNavigateIframe) {
1333 net::SpawnedTestServer http_server(
1334 net::SpawnedTestServer::TYPE_HTTP,
1335 net::SpawnedTestServer::kLocalhost,
1336 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1337 ASSERT_TRUE(http_server.Start());
1338 RunTestPageInIframe(http_server);
1340 std::string unused;
1341 ASSERT_TRUE(content::ExecuteScriptAndExtractString(GetRenderViewHost(),
1342 "navigateFrame();",
1343 &unused));
1344 ExpectDomMessage("iframe loaded");
1345 ChromeAutofillClient* client =
1346 ChromeAutofillClient::FromWebContents(GetActiveWebContents());
1347 EXPECT_FALSE(client->GetDialogControllerForTesting());
1350 } // namespace autofill