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