Commit 57719f70 authored by Friedrich Horschig's avatar Friedrich Horschig Committed by Commit Bot

[Mfill Android] Observer PersonalDataManager to update addresses

The address controller will be asked to provide addresses only once when
it is initialized. After that, it needs to push any changes made to
profiles whenever they change.
For that purpose, observe the PersonalDataManager as soon as it was used
for the first time.

Bug: 967380
Change-Id: Ia6b1ad02edce92b31e5d4951f06ae8933be3fed7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1631594
Commit-Queue: Friedrich [CET] <fhorschig@chromium.org>
Reviewed-by: default avatarVasilii Sukhanov <vasilii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#663819}
parent fe24d671
...@@ -77,7 +77,10 @@ std::vector<FooterCommand> CreateManageAddressesFooter() { ...@@ -77,7 +77,10 @@ std::vector<FooterCommand> CreateManageAddressesFooter() {
} // namespace } // namespace
AddressAccessoryControllerImpl::~AddressAccessoryControllerImpl() = default; AddressAccessoryControllerImpl::~AddressAccessoryControllerImpl() {
if (personal_data_manager_)
personal_data_manager_->RemoveObserver(this);
}
// static // static
bool AddressAccessoryController::AllowedForWebContents( bool AddressAccessoryController::AllowedForWebContents(
...@@ -141,44 +144,42 @@ void AddressAccessoryControllerImpl::RefreshSuggestions() { ...@@ -141,44 +144,42 @@ void AddressAccessoryControllerImpl::RefreshSuggestions() {
UserInfosForProfiles(profiles), CreateManageAddressesFooter())); UserInfosForProfiles(profiles), CreateManageAddressesFooter()));
} }
void AddressAccessoryControllerImpl::OnPersonalDataChanged() {
RefreshSuggestions();
}
// static // static
void AddressAccessoryControllerImpl::CreateForWebContentsForTesting( void AddressAccessoryControllerImpl::CreateForWebContentsForTesting(
content::WebContents* web_contents, content::WebContents* web_contents,
base::WeakPtr<ManualFillingController> mf_controller, base::WeakPtr<ManualFillingController> mf_controller) {
autofill::PersonalDataManager* personal_data_manager) {
DCHECK(web_contents) << "Need valid WebContents to attach controller to!"; DCHECK(web_contents) << "Need valid WebContents to attach controller to!";
DCHECK(!FromWebContents(web_contents)) << "Controller already attached!"; DCHECK(!FromWebContents(web_contents)) << "Controller already attached!";
DCHECK(mf_controller); DCHECK(mf_controller);
web_contents->SetUserData( web_contents->SetUserData(UserDataKey(),
UserDataKey(),
base::WrapUnique(new AddressAccessoryControllerImpl( base::WrapUnique(new AddressAccessoryControllerImpl(
web_contents, std::move(mf_controller), personal_data_manager))); web_contents, std::move(mf_controller))));
} }
AddressAccessoryControllerImpl::AddressAccessoryControllerImpl( AddressAccessoryControllerImpl::AddressAccessoryControllerImpl(
content::WebContents* web_contents) content::WebContents* web_contents)
: web_contents_(web_contents), : AddressAccessoryControllerImpl(web_contents, nullptr) {}
personal_data_manager_for_testing_(nullptr) {}
// Additional creation functions in unit tests only: // Additional creation functions in unit tests only:
AddressAccessoryControllerImpl::AddressAccessoryControllerImpl( AddressAccessoryControllerImpl::AddressAccessoryControllerImpl(
content::WebContents* web_contents, content::WebContents* web_contents,
base::WeakPtr<ManualFillingController> mf_controller, base::WeakPtr<ManualFillingController> mf_controller)
autofill::PersonalDataManager* personal_data_manager)
: web_contents_(web_contents), : web_contents_(web_contents),
mf_controller_(std::move(mf_controller)), mf_controller_(std::move(mf_controller)),
personal_data_manager_for_testing_(personal_data_manager) {} personal_data_manager_(nullptr) {}
std::vector<AutofillProfile*> AddressAccessoryControllerImpl::GetProfiles() { std::vector<AutofillProfile*> AddressAccessoryControllerImpl::GetProfiles() {
const autofill::PersonalDataManager* data_manager = if (!personal_data_manager_) {
personal_data_manager_for_testing_; personal_data_manager_ =
if (!data_manager) autofill::PersonalDataManagerFactory::GetForProfile(
data_manager = autofill::PersonalDataManagerFactory::GetForProfile(
Profile::FromBrowserContext(web_contents_->GetBrowserContext())); Profile::FromBrowserContext(web_contents_->GetBrowserContext()));
if (!data_manager) personal_data_manager_->AddObserver(this);
return {}; // No data available yet or anymore! }
return data_manager->GetProfilesToSuggest(); return personal_data_manager_->GetProfilesToSuggest();
} }
base::WeakPtr<ManualFillingController> base::WeakPtr<ManualFillingController>
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "chrome/browser/autofill/address_accessory_controller.h" #include "chrome/browser/autofill/address_accessory_controller.h"
#include "components/autofill/core/browser/personal_data_manager_observer.h"
#include "content/public/browser/web_contents_user_data.h" #include "content/public/browser/web_contents_user_data.h"
#include "url/gurl.h" #include "url/gurl.h"
...@@ -26,6 +27,7 @@ class PersonalDataManager; ...@@ -26,6 +27,7 @@ class PersonalDataManager;
// contents of one of its frames. // contents of one of its frames.
class AddressAccessoryControllerImpl class AddressAccessoryControllerImpl
: public AddressAccessoryController, : public AddressAccessoryController,
public PersonalDataManagerObserver,
public content::WebContentsUserData<AddressAccessoryControllerImpl> { public content::WebContentsUserData<AddressAccessoryControllerImpl> {
public: public:
~AddressAccessoryControllerImpl() override; ~AddressAccessoryControllerImpl() override;
...@@ -37,13 +39,15 @@ class AddressAccessoryControllerImpl ...@@ -37,13 +39,15 @@ class AddressAccessoryControllerImpl
// AddressAccessoryController: // AddressAccessoryController:
void RefreshSuggestions() override; void RefreshSuggestions() override;
// PersonalDataManagerObserver:
void OnPersonalDataChanged() override;
// Like |CreateForWebContents|, it creates the controller and attaches it to // Like |CreateForWebContents|, it creates the controller and attaches it to
// the given |web_contents|. Additionally, it allows inject a manual filling // the given |web_contents|. Additionally, it allows inject a manual filling
// controller. // controller.
static void CreateForWebContentsForTesting( static void CreateForWebContentsForTesting(
content::WebContents* web_contents, content::WebContents* web_contents,
base::WeakPtr<ManualFillingController> mf_controller, base::WeakPtr<ManualFillingController> mf_controller);
autofill::PersonalDataManager* personal_data_manager);
private: private:
friend class content::WebContentsUserData<AddressAccessoryControllerImpl>; friend class content::WebContentsUserData<AddressAccessoryControllerImpl>;
...@@ -53,11 +57,10 @@ class AddressAccessoryControllerImpl ...@@ -53,11 +57,10 @@ class AddressAccessoryControllerImpl
std::vector<autofill::AutofillProfile*> GetProfiles(); std::vector<autofill::AutofillProfile*> GetProfiles();
// Constructor that allows to inject a mock or fake view. // Constructor that allows to inject a mock filling controller.
AddressAccessoryControllerImpl( AddressAccessoryControllerImpl(
content::WebContents* web_contents, content::WebContents* web_contents,
base::WeakPtr<ManualFillingController> mf_controller, base::WeakPtr<ManualFillingController> mf_controller);
autofill::PersonalDataManager* personal_data_manager);
// Lazy-initializes and returns the ManualFillingController for the current // Lazy-initializes and returns the ManualFillingController for the current
// |web_contents_|. The lazy initialization allows injecting mocks for tests. // |web_contents_|. The lazy initialization allows injecting mocks for tests.
...@@ -69,8 +72,8 @@ class AddressAccessoryControllerImpl ...@@ -69,8 +72,8 @@ class AddressAccessoryControllerImpl
// The password accessory controller object to forward client requests to. // The password accessory controller object to forward client requests to.
base::WeakPtr<ManualFillingController> mf_controller_; base::WeakPtr<ManualFillingController> mf_controller_;
// The data manager used to retrieve the profiles in tests. // The data manager used to retrieve the profiles.
const autofill::PersonalDataManager* personal_data_manager_for_testing_; autofill::PersonalDataManager* personal_data_manager_;
WEB_CONTENTS_USER_DATA_KEY_DECL(); WEB_CONTENTS_USER_DATA_KEY_DECL();
......
...@@ -9,12 +9,13 @@ ...@@ -9,12 +9,13 @@
#include <ostream> #include <ostream>
#include <string> #include <string>
#include <vector> #include <vector>
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/test/mock_callback.h" #include "base/test/mock_callback.h"
#include "chrome/browser/autofill/mock_manual_filling_controller.h" #include "chrome/browser/autofill/mock_manual_filling_controller.h"
#include "chrome/browser/autofill/personal_data_manager_factory.h"
#include "chrome/grit/generated_resources.h" #include "chrome/grit/generated_resources.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "chrome/test/base/testing_profile.h"
#include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/test_personal_data_manager.h" #include "components/autofill/core/browser/test_personal_data_manager.h"
#include "components/strings/grit/components_strings.h" #include "components/strings/grit/components_strings.h"
...@@ -52,6 +53,13 @@ AccessorySheetData::Builder AddressAccessorySheetDataBuilder( ...@@ -52,6 +53,13 @@ AccessorySheetData::Builder AddressAccessorySheetDataBuilder(
AccessoryAction::MANAGE_ADDRESSES); AccessoryAction::MANAGE_ADDRESSES);
} }
std::unique_ptr<KeyedService> BuildTestPersonalDataManager(
content::BrowserContext* context) {
auto personal_data_manager = std::make_unique<TestPersonalDataManager>();
personal_data_manager->SetAutofillProfileEnabled(true);
return personal_data_manager;
}
} // namespace } // namespace
class AddressAccessoryControllerTest : public ChromeRenderViewHostTestHarness { class AddressAccessoryControllerTest : public ChromeRenderViewHostTestHarness {
...@@ -60,22 +68,27 @@ class AddressAccessoryControllerTest : public ChromeRenderViewHostTestHarness { ...@@ -60,22 +68,27 @@ class AddressAccessoryControllerTest : public ChromeRenderViewHostTestHarness {
void SetUp() override { void SetUp() override {
ChromeRenderViewHostTestHarness::SetUp(); ChromeRenderViewHostTestHarness::SetUp();
personal_data_manager_.SetAutofillProfileEnabled(true); PersonalDataManagerFactory::GetInstance()->SetTestingFactory(
GetBrowserContext(),
base::BindRepeating(&BuildTestPersonalDataManager));
AddressAccessoryControllerImpl::CreateForWebContentsForTesting( AddressAccessoryControllerImpl::CreateForWebContentsForTesting(
web_contents(), mock_manual_filling_controller_.AsWeakPtr(), web_contents(), mock_manual_filling_controller_.AsWeakPtr());
&personal_data_manager_);
} }
void TearDown() override { personal_data_manager_.ClearProfiles(); } void TearDown() override { personal_data_manager()->ClearProfiles(); }
AddressAccessoryController* controller() { AddressAccessoryController* controller() {
return AddressAccessoryControllerImpl::FromWebContents(web_contents()); return AddressAccessoryControllerImpl::FromWebContents(web_contents());
} }
TestPersonalDataManager* personal_data_manager() {
return static_cast<TestPersonalDataManager*>(
PersonalDataManagerFactory::GetForProfile(profile()));
}
protected: protected:
StrictMock<MockManualFillingController> mock_manual_filling_controller_; StrictMock<MockManualFillingController> mock_manual_filling_controller_;
autofill::TestPersonalDataManager personal_data_manager_;
}; };
TEST_F(AddressAccessoryControllerTest, IsNotRecreatedForSameWebContents) { TEST_F(AddressAccessoryControllerTest, IsNotRecreatedForSameWebContents) {
...@@ -89,10 +102,9 @@ TEST_F(AddressAccessoryControllerTest, IsNotRecreatedForSameWebContents) { ...@@ -89,10 +102,9 @@ TEST_F(AddressAccessoryControllerTest, IsNotRecreatedForSameWebContents) {
TEST_F(AddressAccessoryControllerTest, RefreshSuggestionsCallsUI) { TEST_F(AddressAccessoryControllerTest, RefreshSuggestionsCallsUI) {
AutofillProfile canadian = test::GetFullValidProfileForCanada(); AutofillProfile canadian = test::GetFullValidProfileForCanada();
personal_data_manager_.AddProfile(canadian); personal_data_manager()->AddProfile(canadian);
autofill::AccessorySheetData result(autofill::AccessoryTabType::PASSWORDS, AccessorySheetData result(AccessoryTabType::PASSWORDS, base::string16());
base::string16());
EXPECT_CALL(mock_manual_filling_controller_, EXPECT_CALL(mock_manual_filling_controller_,
RefreshSuggestionsForField( RefreshSuggestionsForField(
mojom::FocusedFieldType::kFillableTextField, _)) mojom::FocusedFieldType::kFillableTextField, _))
...@@ -128,8 +140,7 @@ TEST_F(AddressAccessoryControllerTest, RefreshSuggestionsCallsUI) { ...@@ -128,8 +140,7 @@ TEST_F(AddressAccessoryControllerTest, RefreshSuggestionsCallsUI) {
} }
TEST_F(AddressAccessoryControllerTest, ProvidesEmptySuggestionsMessage) { TEST_F(AddressAccessoryControllerTest, ProvidesEmptySuggestionsMessage) {
autofill::AccessorySheetData result(autofill::AccessoryTabType::PASSWORDS, AccessorySheetData result(AccessoryTabType::PASSWORDS, base::string16());
base::string16());
EXPECT_CALL(mock_manual_filling_controller_, EXPECT_CALL(mock_manual_filling_controller_,
RefreshSuggestionsForField( RefreshSuggestionsForField(
mojom::FocusedFieldType::kFillableTextField, _)) mojom::FocusedFieldType::kFillableTextField, _))
...@@ -141,4 +152,47 @@ TEST_F(AddressAccessoryControllerTest, ProvidesEmptySuggestionsMessage) { ...@@ -141,4 +152,47 @@ TEST_F(AddressAccessoryControllerTest, ProvidesEmptySuggestionsMessage) {
AddressAccessorySheetDataBuilder(addresses_empty_str()).Build()); AddressAccessorySheetDataBuilder(addresses_empty_str()).Build());
} }
TEST_F(AddressAccessoryControllerTest, TriggersRefreshWhenDataChanges) {
AccessorySheetData result(AccessoryTabType::PASSWORDS, base::string16());
EXPECT_CALL(mock_manual_filling_controller_,
RefreshSuggestionsForField(
mojom::FocusedFieldType::kFillableTextField, _))
.WillRepeatedly(SaveArg<1>(&result));
// A refresh without data stores an empty sheet and registers an observer.
controller()->RefreshSuggestions();
ASSERT_EQ(result,
AddressAccessorySheetDataBuilder(addresses_empty_str()).Build());
// When new data is added, a refresh is automatically triggered.
AutofillProfile email = test::GetIncompleteProfile2();
personal_data_manager()->AddProfile(email);
ASSERT_EQ(result, AddressAccessorySheetDataBuilder(base::string16())
.AddUserInfo()
/*name first:*/
.AppendSimpleField(base::string16())
/*name middle:*/
.AppendSimpleField(base::string16())
/*name last:*/
.AppendSimpleField(base::string16())
/*company name:*/
.AppendSimpleField(base::string16())
/*address line1:*/
.AppendSimpleField(base::string16())
/*address line2:*/
.AppendSimpleField(base::string16())
/*address zip:*/
.AppendSimpleField(base::string16())
/*address city:*/
.AppendSimpleField(base::string16())
/*address state:*/
.AppendSimpleField(base::string16())
/*address country:*/
.AppendSimpleField(base::string16())
/*phone number:*/.AppendSimpleField(base::string16())
.AppendSimpleField(
email.GetRawInfo(ServerFieldType::EMAIL_ADDRESS))
.Build());
}
} // namespace autofill } // namespace autofill
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment