Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/guid.h" | 5 #include "base/guid.h" |
| 6 #include "base/memory/scoped_ptr.h" | 6 #include "base/memory/scoped_ptr.h" |
| 7 #include "base/message_loop.h" | 7 #include "base/message_loop.h" |
| 8 #include "base/prefs/pref_service.h" | 8 #include "base/prefs/pref_service.h" |
| 9 #include "base/utf_string_conversions.h" | 9 #include "base/utf_string_conversions.h" |
| 10 #include "chrome/browser/ui/autofill/autofill_dialog_controller_impl.h" | 10 #include "chrome/browser/ui/autofill/autofill_dialog_controller_impl.h" |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 45 virtual void Show() OVERRIDE {} | 45 virtual void Show() OVERRIDE {} |
| 46 virtual void Hide() OVERRIDE {} | 46 virtual void Hide() OVERRIDE {} |
| 47 virtual void UpdateNotificationArea() OVERRIDE {} | 47 virtual void UpdateNotificationArea() OVERRIDE {} |
| 48 virtual void UpdateAccountChooser() OVERRIDE {} | 48 virtual void UpdateAccountChooser() OVERRIDE {} |
| 49 virtual void UpdateButtonStrip() OVERRIDE {} | 49 virtual void UpdateButtonStrip() OVERRIDE {} |
| 50 virtual void UpdateSection(DialogSection section) OVERRIDE {} | 50 virtual void UpdateSection(DialogSection section) OVERRIDE {} |
| 51 virtual void GetUserInput(DialogSection section, DetailOutputMap* output) | 51 virtual void GetUserInput(DialogSection section, DetailOutputMap* output) |
| 52 OVERRIDE {} | 52 OVERRIDE {} |
| 53 virtual string16 GetCvc() OVERRIDE { return string16(); } | 53 virtual string16 GetCvc() OVERRIDE { return string16(); } |
| 54 virtual bool UseBillingForShipping() OVERRIDE { return false; } | 54 virtual bool UseBillingForShipping() OVERRIDE { return false; } |
| 55 virtual bool SaveDetailsInWallet() OVERRIDE { return false; } | |
| 56 virtual bool SaveDetailsLocally() OVERRIDE { return false; } | 55 virtual bool SaveDetailsLocally() OVERRIDE { return false; } |
| 57 virtual const content::NavigationController* ShowSignIn() OVERRIDE { | 56 virtual const content::NavigationController* ShowSignIn() OVERRIDE { |
| 58 return NULL; | 57 return NULL; |
| 59 } | 58 } |
| 60 virtual void HideSignIn() OVERRIDE {} | 59 virtual void HideSignIn() OVERRIDE {} |
| 61 virtual void UpdateProgressBar(double value) OVERRIDE {} | 60 virtual void UpdateProgressBar(double value) OVERRIDE {} |
| 62 virtual void SubmitForTesting() OVERRIDE {} | 61 virtual void SubmitForTesting() OVERRIDE {} |
| 63 virtual void CancelForTesting() OVERRIDE {} | 62 virtual void CancelForTesting() OVERRIDE {} |
| 64 | 63 |
| 65 MOCK_METHOD0(ModelChanged, void()); | 64 MOCK_METHOD0(ModelChanged, void()); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 136 const base::Callback<void(const FormStructure*, | 135 const base::Callback<void(const FormStructure*, |
| 137 const std::string&)>& callback) | 136 const std::string&)>& callback) |
| 138 : AutofillDialogControllerImpl(contents, | 137 : AutofillDialogControllerImpl(contents, |
| 139 form_structure, | 138 form_structure, |
| 140 source_url, | 139 source_url, |
| 141 dialog_type, | 140 dialog_type, |
| 142 callback), | 141 callback), |
| 143 metric_logger_(metric_logger), | 142 metric_logger_(metric_logger), |
| 144 ALLOW_THIS_IN_INITIALIZER_LIST(test_wallet_client_( | 143 ALLOW_THIS_IN_INITIALIZER_LIST(test_wallet_client_( |
| 145 Profile::FromBrowserContext(contents->GetBrowserContext())-> | 144 Profile::FromBrowserContext(contents->GetBrowserContext())-> |
| 146 GetRequestContext(), this)) {} | 145 GetRequestContext(), this)), |
| 146 is_first_run_(true) {} | |
| 147 virtual ~TestAutofillDialogController() {} | 147 virtual ~TestAutofillDialogController() {} |
| 148 | 148 |
| 149 virtual AutofillDialogView* CreateView() OVERRIDE { | 149 virtual AutofillDialogView* CreateView() OVERRIDE { |
| 150 return new testing::NiceMock<TestAutofillDialogView>(); | 150 return new testing::NiceMock<TestAutofillDialogView>(); |
| 151 } | 151 } |
| 152 | 152 |
| 153 void Init(content::BrowserContext* browser_context) { | 153 void Init(content::BrowserContext* browser_context) { |
| 154 test_manager_.Init(browser_context); | 154 test_manager_.Init(browser_context); |
| 155 } | 155 } |
| 156 | 156 |
| 157 TestAutofillDialogView* GetView() { | 157 TestAutofillDialogView* GetView() { |
| 158 return static_cast<TestAutofillDialogView*>(view()); | 158 return static_cast<TestAutofillDialogView*>(view()); |
| 159 } | 159 } |
| 160 | 160 |
| 161 TestPersonalDataManager* GetTestingManager() { | 161 TestPersonalDataManager* GetTestingManager() { |
| 162 return &test_manager_; | 162 return &test_manager_; |
| 163 } | 163 } |
| 164 | 164 |
| 165 TestWalletClient* GetTestingWalletClient() { | 165 TestWalletClient* GetTestingWalletClient() { |
| 166 return &test_wallet_client_; | 166 return &test_wallet_client_; |
| 167 } | 167 } |
| 168 | 168 |
| 169 void set_is_first_run(bool is_first_run) { is_first_run_ = is_first_run; } | |
| 170 | |
| 169 protected: | 171 protected: |
| 170 virtual PersonalDataManager* GetManager() OVERRIDE { | 172 virtual PersonalDataManager* GetManager() OVERRIDE { |
| 171 return &test_manager_; | 173 return &test_manager_; |
| 172 } | 174 } |
| 173 | 175 |
| 174 virtual wallet::WalletClient* GetWalletClient() OVERRIDE { | 176 virtual wallet::WalletClient* GetWalletClient() OVERRIDE { |
| 175 return &test_wallet_client_; | 177 return &test_wallet_client_; |
| 176 } | 178 } |
| 177 | 179 |
| 180 virtual bool IsFirstRun() const OVERRIDE { | |
| 181 return is_first_run_; | |
| 182 } | |
| 183 | |
| 178 private: | 184 private: |
| 179 // To specify our own metric logger. | 185 // To specify our own metric logger. |
| 180 virtual const AutofillMetrics& GetMetricLogger() const OVERRIDE { | 186 virtual const AutofillMetrics& GetMetricLogger() const OVERRIDE { |
| 181 return metric_logger_; | 187 return metric_logger_; |
| 182 } | 188 } |
| 183 | 189 |
| 184 const AutofillMetrics& metric_logger_; | 190 const AutofillMetrics& metric_logger_; |
| 185 TestPersonalDataManager test_manager_; | 191 TestPersonalDataManager test_manager_; |
| 186 testing::NiceMock<TestWalletClient> test_wallet_client_; | 192 testing::NiceMock<TestWalletClient> test_wallet_client_; |
| 193 bool is_first_run_; | |
| 187 | 194 |
| 188 DISALLOW_COPY_AND_ASSIGN(TestAutofillDialogController); | 195 DISALLOW_COPY_AND_ASSIGN(TestAutofillDialogController); |
| 189 }; | 196 }; |
| 190 | 197 |
| 191 class AutofillDialogControllerTest : public testing::Test { | 198 class AutofillDialogControllerTest : public testing::Test { |
| 192 public: | 199 public: |
| 193 AutofillDialogControllerTest() | 200 AutofillDialogControllerTest() |
| 194 : ui_thread_(BrowserThread::UI, &loop_), | 201 : ui_thread_(BrowserThread::UI, &loop_), |
| 195 file_thread_(BrowserThread::FILE), | 202 file_thread_(BrowserThread::FILE), |
| 196 file_blocking_thread_(BrowserThread::FILE_USER_BLOCKING), | 203 file_blocking_thread_(BrowserThread::FILE_USER_BLOCKING), |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 248 | 255 |
| 249 static scoped_ptr<wallet::FullWallet> CreateFullWalletWithVerifyCvv() { | 256 static scoped_ptr<wallet::FullWallet> CreateFullWalletWithVerifyCvv() { |
| 250 base::DictionaryValue dict; | 257 base::DictionaryValue dict; |
| 251 scoped_ptr<base::ListValue> list(new base::ListValue()); | 258 scoped_ptr<base::ListValue> list(new base::ListValue()); |
| 252 list->AppendString("verify_cvv"); | 259 list->AppendString("verify_cvv"); |
| 253 dict.Set("required_action", list.release()); | 260 dict.Set("required_action", list.release()); |
| 254 return wallet::FullWallet::CreateFullWallet(dict); | 261 return wallet::FullWallet::CreateFullWallet(dict); |
| 255 } | 262 } |
| 256 | 263 |
| 257 void SetUpWallet() { | 264 void SetUpWallet() { |
| 258 controller()->MenuModelForAccountChooser()->ActivatedAt(0); | 265 controller()->MenuModelForAccountChooser()->ActivatedAt( |
| 266 AccountChooserModel::kWalletItemId); | |
| 259 controller()->OnUserNameFetchSuccess("user@example.com"); | 267 controller()->OnUserNameFetchSuccess("user@example.com"); |
| 260 } | 268 } |
| 261 | 269 |
| 262 TestAutofillDialogController* controller() { return controller_; } | 270 TestAutofillDialogController* controller() { return controller_; } |
| 263 | 271 |
| 264 TestingProfile* profile() { return &profile_; } | 272 TestingProfile* profile() { return &profile_; } |
| 265 | 273 |
| 266 private: | 274 private: |
| 267 void FinishedCallback(const FormStructure* form_structure, | 275 void FinishedCallback(const FormStructure* form_structure, |
| 268 const std::string& google_transaction_id) {} | 276 const std::string& google_transaction_id) {} |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 501 EXPECT_TRUE(controller()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_CANCEL)); | 509 EXPECT_TRUE(controller()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_CANCEL)); |
| 502 | 510 |
| 503 SuggestionState suggestion_state = | 511 SuggestionState suggestion_state = |
| 504 controller()->SuggestionStateForSection(SECTION_CC_BILLING); | 512 controller()->SuggestionStateForSection(SECTION_CC_BILLING); |
| 505 EXPECT_TRUE(suggestion_state.extra_text.empty()); | 513 EXPECT_TRUE(suggestion_state.extra_text.empty()); |
| 506 | 514 |
| 507 controller()->OnDidGetFullWallet(CreateFullWalletWithVerifyCvv()); | 515 controller()->OnDidGetFullWallet(CreateFullWalletWithVerifyCvv()); |
| 508 | 516 |
| 509 EXPECT_FALSE( | 517 EXPECT_FALSE( |
| 510 NotificationsOfType(DialogNotification::REQUIRED_ACTION).empty()); | 518 NotificationsOfType(DialogNotification::REQUIRED_ACTION).empty()); |
| 511 const std::vector<DialogNotification>& notifications = | |
| 512 NotificationsOfType(DialogNotification::WALLET_USAGE_CONFIRMATION); | |
| 513 EXPECT_FALSE(notifications.front().interactive()); | |
| 514 | |
| 515 EXPECT_FALSE(controller()->SectionIsActive(SECTION_EMAIL)); | 519 EXPECT_FALSE(controller()->SectionIsActive(SECTION_EMAIL)); |
| 516 EXPECT_FALSE(controller()->SectionIsActive(SECTION_SHIPPING)); | 520 EXPECT_FALSE(controller()->SectionIsActive(SECTION_SHIPPING)); |
| 517 EXPECT_TRUE(controller()->SectionIsActive(SECTION_CC_BILLING)); | 521 EXPECT_TRUE(controller()->SectionIsActive(SECTION_CC_BILLING)); |
| 518 | 522 |
| 519 suggestion_state = | 523 suggestion_state = |
| 520 controller()->SuggestionStateForSection(SECTION_CC_BILLING); | 524 controller()->SuggestionStateForSection(SECTION_CC_BILLING); |
| 521 EXPECT_FALSE(suggestion_state.extra_text.empty()); | 525 EXPECT_FALSE(suggestion_state.extra_text.empty()); |
| 522 EXPECT_EQ( | 526 EXPECT_EQ( |
| 523 0, controller()->MenuModelForSection(SECTION_CC_BILLING)->GetItemCount()); | 527 0, controller()->MenuModelForSection(SECTION_CC_BILLING)->GetItemCount()); |
| 524 | 528 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 561 wallet_items->AddAddress(wallet::GetTestShippingAddress()); | 565 wallet_items->AddAddress(wallet::GetTestShippingAddress()); |
| 562 controller()->OnDidGetWalletItems(wallet_items.Pass()); | 566 controller()->OnDidGetWalletItems(wallet_items.Pass()); |
| 563 controller()->OnAccept(); | 567 controller()->OnAccept(); |
| 564 | 568 |
| 565 EXPECT_FALSE(controller()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK)); | 569 EXPECT_FALSE(controller()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK)); |
| 566 EXPECT_TRUE(controller()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_CANCEL)); | 570 EXPECT_TRUE(controller()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_CANCEL)); |
| 567 | 571 |
| 568 ui::MenuModel* account_menu = controller()->MenuModelForAccountChooser(); | 572 ui::MenuModel* account_menu = controller()->MenuModelForAccountChooser(); |
| 569 ASSERT_TRUE(account_menu); | 573 ASSERT_TRUE(account_menu); |
| 570 ASSERT_GE(2, account_menu->GetItemCount()); | 574 ASSERT_GE(2, account_menu->GetItemCount()); |
| 571 account_menu->ActivatedAt(0); | 575 account_menu->ActivatedAt(AccountChooserModel::kWalletItemId); |
| 572 account_menu->ActivatedAt(1); | 576 account_menu->ActivatedAt(AccountChooserModel::kAutofillItemId); |
| 573 | 577 |
| 574 EXPECT_TRUE(controller()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK)); | 578 EXPECT_TRUE(controller()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK)); |
| 575 EXPECT_TRUE(controller()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_CANCEL)); | 579 EXPECT_TRUE(controller()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_CANCEL)); |
| 576 } | 580 } |
| 577 | 581 |
| 578 TEST_F(AutofillDialogControllerTest, ErrorDuringVerifyCvv) { | 582 TEST_F(AutofillDialogControllerTest, ErrorDuringVerifyCvv) { |
| 579 SetUpWallet(); | 583 SetUpWallet(); |
| 580 | 584 |
| 581 EXPECT_CALL(*controller()->GetTestingWalletClient(), | 585 EXPECT_CALL(*controller()->GetTestingWalletClient(), |
| 582 GetFullWallet(_)).Times(1); | 586 GetFullWallet(_)).Times(1); |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 610 controller()->OnDidGetWalletItems(wallet_items.Pass()); | 614 controller()->OnDidGetWalletItems(wallet_items.Pass()); |
| 611 controller()->OnAccept(); | 615 controller()->OnAccept(); |
| 612 controller()->OnDidGetFullWallet(CreateFullWalletWithVerifyCvv()); | 616 controller()->OnDidGetFullWallet(CreateFullWalletWithVerifyCvv()); |
| 613 | 617 |
| 614 ASSERT_TRUE(controller()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK)); | 618 ASSERT_TRUE(controller()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK)); |
| 615 ASSERT_TRUE(controller()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_CANCEL)); | 619 ASSERT_TRUE(controller()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_CANCEL)); |
| 616 | 620 |
| 617 ui::MenuModel* account_menu = controller()->MenuModelForAccountChooser(); | 621 ui::MenuModel* account_menu = controller()->MenuModelForAccountChooser(); |
| 618 ASSERT_TRUE(account_menu); | 622 ASSERT_TRUE(account_menu); |
| 619 ASSERT_GE(2, account_menu->GetItemCount()); | 623 ASSERT_GE(2, account_menu->GetItemCount()); |
| 620 account_menu->ActivatedAt(0); | 624 account_menu->ActivatedAt(AccountChooserModel::kWalletItemId); |
| 621 account_menu->ActivatedAt(1); | 625 account_menu->ActivatedAt(AccountChooserModel::kAutofillItemId); |
| 622 | 626 |
| 623 EXPECT_TRUE(controller()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK)); | 627 EXPECT_TRUE(controller()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK)); |
| 624 EXPECT_TRUE(controller()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_CANCEL)); | 628 EXPECT_TRUE(controller()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_CANCEL)); |
| 625 } | 629 } |
| 626 | 630 |
| 631 TEST_F(AutofillDialogControllerTest, WalletErrorNotification) { | |
| 632 SetUpWallet(); | |
| 633 | |
| 634 controller()->OnWalletError(wallet::WalletClient::UNKNOWN_ERROR); | |
| 635 | |
| 636 EXPECT_EQ(1U, NotificationsOfType( | |
| 637 DialogNotification::WALLET_ERROR).size()); | |
| 638 | |
| 639 // No promos or usage confirmations should show if there was a Wallet error. | |
| 640 EXPECT_TRUE(NotificationsOfType( | |
| 641 DialogNotification::WALLET_SIGNIN_PROMO).empty()); | |
| 642 EXPECT_TRUE(NotificationsOfType( | |
| 643 DialogNotification::WALLET_USAGE_CONFIRMATION).empty()); | |
| 644 } | |
| 645 | |
| 646 TEST_F(AutofillDialogControllerTest, WalletDetailsExplanation) { | |
| 647 SetUpWallet(); | |
| 648 | |
| 649 scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems(); | |
| 650 wallet_items->AddInstrument(wallet::GetTestMaskedInstrument()); | |
| 651 wallet_items->AddAddress(wallet::GetTestShippingAddress()); | |
| 652 controller()->OnDidGetWalletItems(wallet_items.Pass()); | |
| 653 | |
| 654 // Explanatory messages and usage confirmations are mutually exclusive. | |
| 655 EXPECT_EQ(1U, NotificationsOfType( | |
| 656 DialogNotification::EXPLANATORY_MESSAGE).size()); | |
| 657 EXPECT_TRUE(NotificationsOfType( | |
| 658 DialogNotification::WALLET_USAGE_CONFIRMATION).empty()); | |
| 659 | |
| 660 // Switch to using Autofill, no explanatory message should show. | |
| 661 ui::MenuModel* account_menu = controller()->MenuModelForAccountChooser(); | |
| 662 account_menu->ActivatedAt(AccountChooserModel::kAutofillItemId); | |
| 663 EXPECT_TRUE(NotificationsOfType( | |
| 664 DialogNotification::EXPLANATORY_MESSAGE).empty()); | |
| 665 | |
| 666 // Switch to Wallet, pretend this isn't first run. No message should show. | |
| 667 account_menu->ActivatedAt(AccountChooserModel::kWalletItemId); | |
| 668 controller()->set_is_first_run(false); | |
| 669 EXPECT_TRUE(NotificationsOfType( | |
| 670 DialogNotification::EXPLANATORY_MESSAGE).empty()); | |
| 671 } | |
| 672 | |
| 673 TEST_F(AutofillDialogControllerTest, SaveDetailsInWallet) { | |
| 674 SetUpWallet(); | |
| 675 | |
| 676 scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems(); | |
| 677 wallet_items->AddInstrument(wallet::GetTestMaskedInstrument()); | |
| 678 controller()->OnDidGetWalletItems(wallet_items.Pass()); | |
| 679 | |
| 680 std::vector<DialogNotification> notifications = | |
| 681 NotificationsOfType(DialogNotification::WALLET_USAGE_CONFIRMATION); | |
| 682 EXPECT_EQ(1U, notifications.size()); | |
| 683 EXPECT_TRUE(notifications.front().checked()); | |
| 684 EXPECT_TRUE(notifications.front().interactive()); | |
| 685 | |
| 686 // Explanatory messages and usage confirmations are mutually exclusive. | |
| 687 EXPECT_TRUE(NotificationsOfType( | |
| 688 DialogNotification::EXPLANATORY_MESSAGE).empty()); | |
| 689 | |
| 690 // Using Autofill on second run, show an interactive, unchecked checkbox. | |
| 691 ui::MenuModel* account_model = controller()->MenuModelForAccountChooser(); | |
| 692 account_model->ActivatedAt(AccountChooserModel::kAutofillItemId); | |
| 693 controller()->set_is_first_run(false); | |
| 694 | |
| 695 notifications = | |
| 696 NotificationsOfType(DialogNotification::WALLET_USAGE_CONFIRMATION); | |
| 697 EXPECT_EQ(1U, notifications.size()); | |
| 698 EXPECT_FALSE(notifications.front().checked()); | |
| 699 EXPECT_TRUE(notifications.front().interactive()); | |
| 700 | |
| 701 // Notifications shouldn't be interactive while submitting. | |
| 702 account_model->ActivatedAt(AccountChooserModel::kWalletItemId); | |
| 703 controller()->OnAccept(); | |
| 704 EXPECT_FALSE(NotificationsOfType( | |
| 705 DialogNotification::WALLET_USAGE_CONFIRMATION).front().interactive()); | |
| 706 } | |
| 707 | |
|
Evan Stade
2013/04/10 04:13:09
could you add brief descriptions of what each test
Dan Beam
2013/04/10 04:51:59
Done.
| |
| 708 TEST_F(AutofillDialogControllerTest, NoWalletNotifications) { | |
| 709 SetUpWallet(); | |
| 710 controller()->set_is_first_run(false); | |
| 711 | |
| 712 scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems(); | |
| 713 wallet_items->AddInstrument(wallet::GetTestMaskedInstrument()); | |
| 714 wallet_items->AddAddress(wallet::GetTestShippingAddress()); | |
| 715 controller()->OnDidGetWalletItems(wallet_items.Pass()); | |
| 716 | |
| 717 EXPECT_TRUE(NotificationsOfType( | |
| 718 DialogNotification::EXPLANATORY_MESSAGE).empty()); | |
| 719 EXPECT_TRUE(NotificationsOfType( | |
| 720 DialogNotification::WALLET_USAGE_CONFIRMATION).empty()); | |
| 721 } | |
| 722 | |
| 627 } // namespace autofill | 723 } // namespace autofill |
| OLD | NEW |