Reland "[Autofill] Simplify ContentAutofillDriver initialization"
This is a reland of commit 3b90869541da848d1791a4ca8b44bc0fd4af8347
The CL did not cause the breakage. The tests seem to be
failing quite consistently on ci/mac12-arm64-rel-tests. The
first failure [1] does include the reverted CL, but the
failures continue after the revert [2].
I suspect [3] is the culprit.
[1] https://ci.chromium.org/ui/p/chromium/builders/ci/mac12-arm64-rel-tests/18253/blamelist
[2] https://ci.chromium.org/ui/p/chromium/builders/ci/mac12-arm64-rel-tests/18262/blamelist
[3] https://chromium-review.googlesource.com/c/chromium/src/+/5224247
Original change's description:
> [Autofill] Simplify ContentAutofillDriver initialization
>
> The DriverInitHooks have two jobs:
> (1) create a {Browser,Android}AutofillManager;
> (2) call some setters on AutofillAgent.
>
> Since the introduction of ContentAutofillClient, the DriverInitHook
> can be conveniently turned into a member function of the client.
>
> This CL introduces *two* new methods in CAC:
> (1) CreateManager(), to be called by CAD's constructor.
> (2) InitAgent(), to be called by the CAD factory.
>
> The point in time they're called is important:
> - CreateManager() is called before OnContentAutofillDriverCreated(),
> which is necessary for TestAutofillManagerInjector;
> - InitAgent() is called after OnContentAutofillDriverCreated(),
> which avoids trouble with double binding mojo remotes when
> TestAutofillDriverInjector creates a new driver.
>
> Alternatives I considered are:
> - Calling CreateManager() from the factory. This would avoid the
> potential problem of the manager calling into the driver during
> the driver's construction. Rejected because this requires
> CAD::set_autofill_manager(), and since driver and manager
> have to point to each other, there will always be some kind of
> chicken-egg problem.
> - Calling InitAgent() from CAD's constructor. Rejected because
> - tests that mock an AutofillAgent would attempt to bind *two*
> remotes, which isn't allowed;
> - unbinding and rebinding remotes
> - makes writing tests harder;
> - seems not to work for the renderer -> browser remote.
> - Calling CreateManager() and InitAgent() or only InitAgent() from
> a virtual CAD::Init() function, which is be called by the CAD
> factory. Tests would override Init() and only call CreateDriver(),
> not InitAgent(). Rejected because that'd make writing tests harder.
>
> The DriverInitHook model worked similarly, but it probably worked
> out of luck: the DriverInitHooks didn't actually call
> GetAutofillAgent() in most tests, which happened to avoid the
> double bind in all relevant tests.
>
> Bug: 1200511
> Change-Id: I339a8b0e7531a76395e5e50dba16f77e3385f56a
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5224630
> Reviewed-by: Jan Keitel <[email protected]>
> Commit-Queue: Christoph Schwering <[email protected]>
> Cr-Commit-Position: refs/heads/main@{#1252040}
Bug: 1200511
Change-Id: Ib923916a0bd31c920ee089569584c1728289731d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5237331
Commit-Queue: Christoph Schwering <[email protected]>
Auto-Submit: Christoph Schwering <[email protected]>
Reviewed-by: Muyao Xu <[email protected]>
Owners-Override: Muyao Xu <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1252350}
diff --git a/chrome/browser/autofill/BUILD.gn b/chrome/browser/autofill/BUILD.gn
index a44c8274..4cff643d 100644
--- a/chrome/browser/autofill/BUILD.gn
+++ b/chrome/browser/autofill/BUILD.gn
@@ -129,6 +129,8 @@
sources = [
"autofill_uitest_util.cc",
"autofill_uitest_util.h",
+ "mock_autofill_agent.cc",
+ "mock_autofill_agent.h",
"mock_autofill_popup_controller.cc",
"mock_autofill_popup_controller.h",
"mock_manual_filling_controller.cc",
@@ -139,6 +141,7 @@
"//chrome/browser/autofill:autofill",
"//chrome/browser/profiles:profile",
"//components/autofill/content/browser:browser",
+ "//components/autofill/content/common/mojom",
"//components/autofill/core/browser:test_support",
"//content/test:test_support",
"//testing/gmock",
diff --git a/chrome/browser/autofill/mock_autofill_agent.cc b/chrome/browser/autofill/mock_autofill_agent.cc
new file mode 100644
index 0000000..afe0878
--- /dev/null
+++ b/chrome/browser/autofill/mock_autofill_agent.cc
@@ -0,0 +1,30 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/autofill/mock_autofill_agent.h"
+
+#include "content/public/browser/render_frame_host.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
+
+namespace autofill {
+
+MockAutofillAgent::MockAutofillAgent() = default;
+MockAutofillAgent::~MockAutofillAgent() = default;
+
+void MockAutofillAgent::BindForTesting(content::RenderFrameHost* rfh) {
+ blink::AssociatedInterfaceProvider* remote_interfaces =
+ rfh->GetRemoteAssociatedInterfaces();
+ remote_interfaces->OverrideBinderForTesting(
+ mojom::AutofillAgent::Name_,
+ base::BindRepeating(&MockAutofillAgent::BindPendingReceiver,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void MockAutofillAgent::BindPendingReceiver(
+ mojo::ScopedInterfaceEndpointHandle handle) {
+ receivers_.Add(this, mojo::PendingAssociatedReceiver<mojom::AutofillAgent>(
+ std::move(handle)));
+}
+
+} // namespace autofill
diff --git a/chrome/browser/autofill/mock_autofill_agent.h b/chrome/browser/autofill/mock_autofill_agent.h
new file mode 100644
index 0000000..aa385c0
--- /dev/null
+++ b/chrome/browser/autofill/mock_autofill_agent.h
@@ -0,0 +1,99 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_AUTOFILL_MOCK_AUTOFILL_AGENT_H_
+#define CHROME_BROWSER_AUTOFILL_MOCK_AUTOFILL_AGENT_H_
+
+#include "base/memory/weak_ptr.h"
+#include "components/autofill/content/common/mojom/autofill_agent.mojom.h"
+#include "mojo/public/cpp/bindings/associated_receiver_set.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace content {
+class RenderFrameHost;
+}
+
+namespace autofill {
+
+class MockAutofillAgent : public mojom::AutofillAgent {
+ public:
+ MockAutofillAgent();
+ MockAutofillAgent(const MockAutofillAgent&) = delete;
+ MockAutofillAgent& operator=(const MockAutofillAgent&) = delete;
+ ~MockAutofillAgent() override;
+
+ void BindForTesting(content::RenderFrameHost* rfh);
+ void BindPendingReceiver(mojo::ScopedInterfaceEndpointHandle handle);
+
+ MOCK_METHOD(void, TriggerFormExtraction, (), (override));
+ MOCK_METHOD(void,
+ TriggerFormExtractionWithResponse,
+ (base::OnceCallback<void(bool)>),
+ (override));
+ MOCK_METHOD(
+ void,
+ ExtractForm,
+ (FormRendererId form,
+ base::OnceCallback<void(const std::optional<FormData>&)> callback),
+ (override));
+ MOCK_METHOD(void,
+ ApplyFormAction,
+ (mojom::ActionType action_type,
+ mojom::ActionPersistence action_persistence,
+ const FormData::FillData& form),
+ (override));
+ MOCK_METHOD(void,
+ ApplyFieldAction,
+ (mojom::ActionPersistence action_persistence,
+ mojom::TextReplacement text_replacement,
+ FieldRendererId field,
+ const std::u16string& value),
+ (override));
+ MOCK_METHOD(void,
+ FieldTypePredictionsAvailable,
+ (const std::vector<FormDataPredictions>& forms),
+ (override));
+ MOCK_METHOD(void, ClearSection, (), (override));
+ MOCK_METHOD(void, ClearPreviewedForm, (), (override));
+ MOCK_METHOD(void,
+ TriggerSuggestions,
+ (FieldRendererId field_id,
+ AutofillSuggestionTriggerSource trigger_source),
+ (override));
+ MOCK_METHOD(void,
+ SetSuggestionAvailability,
+ (FieldRendererId field,
+ mojom::AutofillSuggestionAvailability suggestion_availability),
+ (override));
+ MOCK_METHOD(void,
+ AcceptDataListSuggestion,
+ (FieldRendererId field, const ::std::u16string& value),
+ (override));
+ MOCK_METHOD(void,
+ PreviewPasswordSuggestion,
+ (const ::std::u16string& username,
+ const ::std::u16string& password),
+ (override));
+ MOCK_METHOD(void,
+ PreviewPasswordGenerationSuggestion,
+ (const ::std::u16string& password),
+ (override));
+ MOCK_METHOD(void, SetUserGestureRequired, (bool required), (override));
+ MOCK_METHOD(void, SetSecureContextRequired, (bool required), (override));
+ MOCK_METHOD(void, SetFocusRequiresScroll, (bool require), (override));
+ MOCK_METHOD(void, SetQueryPasswordSuggestion, (bool query), (override));
+ MOCK_METHOD(void, EnableHeavyFormDataScraping, (), (override));
+ MOCK_METHOD(void,
+ GetPotentialLastFourCombinationsForStandaloneCvc,
+ (base::OnceCallback<void(const std::vector<std::string>&)>),
+ (override));
+
+ private:
+ mojo::AssociatedReceiverSet<mojom::AutofillAgent> receivers_;
+ base::WeakPtrFactory<MockAutofillAgent> weak_ptr_factory_{this};
+};
+
+} // namespace autofill
+
+#endif // CHROME_BROWSER_AUTOFILL_MOCK_AUTOFILL_AGENT_H_
diff --git a/chrome/browser/fast_checkout/fast_checkout_client_impl_unittest.cc b/chrome/browser/fast_checkout/fast_checkout_client_impl_unittest.cc
index aaad224..eba165d 100644
--- a/chrome/browser/fast_checkout/fast_checkout_client_impl_unittest.cc
+++ b/chrome/browser/fast_checkout/fast_checkout_client_impl_unittest.cc
@@ -678,14 +678,9 @@
web_contents()->GetPrimaryMainFrame(),
autofill::ContentAutofillClient::FromWebContents(web_contents())
->GetAutofillDriverFactory());
- auto browser_autofill_manager =
- std::make_unique<autofill::BrowserAutofillManager>(
- autofill_driver.get(),
- autofill::ContentAutofillClient::FromWebContents(web_contents()),
- "en-US");
- autofill::BrowserAutofillManager* autofill_manager =
- browser_autofill_manager.get();
- autofill_driver->set_autofill_manager(std::move(browser_autofill_manager));
+ autofill::BrowserAutofillManager& autofill_manager =
+ static_cast<autofill::BrowserAutofillManager&>(
+ autofill_driver->GetAutofillManager());
// `FastCheckoutClientImpl::autofill_manager_` is `nullptr` initially.
EXPECT_FALSE(fast_checkout_client()->autofill_manager_);
@@ -694,7 +689,7 @@
// Starting the run successfully.
EXPECT_TRUE(fast_checkout_client()->TryToStart(
GURL(kUrl), autofill::FormData(), autofill::FormFieldData(),
- autofill_manager->GetWeakPtr()));
+ autofill_manager.GetWeakPtr()));
OnAfterAskForValuesToFill();
// `FastCheckoutClientImpl::autofill_manager_` is not `nullptr` anymore.
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.cc b/chrome/browser/ui/autofill/chrome_autofill_client.cc
index 156f9c1..2acba35 100644
--- a/chrome/browser/ui/autofill/chrome_autofill_client.cc
+++ b/chrome/browser/ui/autofill/chrome_autofill_client.cc
@@ -181,11 +181,26 @@
namespace autofill {
namespace {
+
AutoselectFirstSuggestion ShouldAutofillPopupAutoselectFirstSuggestion(
AutofillSuggestionTriggerSource source) {
return AutoselectFirstSuggestion(
source == AutofillSuggestionTriggerSource::kTextFieldDidReceiveKeyDown);
}
+
+bool ShouldEnableHeavyFormDataScraping(const version_info::Channel channel) {
+ switch (channel) {
+ case version_info::Channel::CANARY:
+ case version_info::Channel::DEV:
+ return true;
+ case version_info::Channel::STABLE:
+ case version_info::Channel::BETA:
+ case version_info::Channel::UNKNOWN:
+ return false;
+ }
+ NOTREACHED_NORETURN();
+}
+
} // namespace
// static
@@ -1322,11 +1337,7 @@
}
ChromeAutofillClient::ChromeAutofillClient(content::WebContents* web_contents)
- : ContentAutofillClient(
- web_contents,
- base::BindRepeating(&BrowserDriverInitHook,
- this,
- g_browser_process->GetApplicationLocale())),
+ : ContentAutofillClient(web_contents),
content::WebContentsObserver(web_contents),
log_manager_(
// TODO(crbug.com/928595): Replace the closure with a callback to the
@@ -1415,4 +1426,19 @@
}
#endif
+std::unique_ptr<AutofillManager> ChromeAutofillClient::CreateManager(
+ base::PassKey<ContentAutofillDriver> pass_key,
+ ContentAutofillDriver& driver) {
+ return std::make_unique<BrowserAutofillManager>(
+ &driver, this, g_browser_process->GetApplicationLocale());
+}
+
+void ChromeAutofillClient::InitAgent(
+ base::PassKey<ContentAutofillDriverFactory> pass_key,
+ const mojo::AssociatedRemote<mojom::AutofillAgent>& agent) {
+ if (ShouldEnableHeavyFormDataScraping(GetChannel())) {
+ agent->EnableHeavyFormDataScraping();
+ }
+}
+
} // namespace autofill
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.h b/chrome/browser/ui/autofill/chrome_autofill_client.h
index c73ed43..3b0c5a1 100644
--- a/chrome/browser/ui/autofill/chrome_autofill_client.h
+++ b/chrome/browser/ui/autofill/chrome_autofill_client.h
@@ -289,6 +289,14 @@
return autofill_progress_dialog_controller_.get();
}
+ // ContentAutofillClient:
+ std::unique_ptr<AutofillManager> CreateManager(
+ base::PassKey<ContentAutofillDriver> pass_key,
+ ContentAutofillDriver& driver) override;
+ void InitAgent(
+ base::PassKey<ContentAutofillDriverFactory> pass_key,
+ const mojo::AssociatedRemote<mojom::AutofillAgent>& agent) override;
+
protected:
explicit ChromeAutofillClient(content::WebContents* web_contents);
#if BUILDFLAG(IS_ANDROID)
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client_unittest.cc b/chrome/browser/ui/autofill/chrome_autofill_client_unittest.cc
index 66cd909..fe747da 100644
--- a/chrome/browser/ui/autofill/chrome_autofill_client_unittest.cc
+++ b/chrome/browser/ui/autofill/chrome_autofill_client_unittest.cc
@@ -10,6 +10,7 @@
#include "base/test/scoped_feature_list.h"
#include "build/branding_buildflags.h"
#include "build/build_config.h"
+#include "chrome/browser/autofill/mock_autofill_agent.h"
#include "chrome/browser/autofill/personal_data_manager_factory.h"
#include "chrome/browser/fast_checkout/fast_checkout_client_impl.h"
#include "chrome/browser/plus_addresses/plus_address_service_factory.h"
@@ -27,8 +28,11 @@
#include "components/plus_addresses/features.h"
#include "components/prefs/pref_service.h"
#include "components/unified_consent/pref_names.h"
+#include "mojo/public/cpp/bindings/associated_receiver_set.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#if BUILDFLAG(IS_ANDROID)
#include "chrome/browser/ui/android/autofill/autofill_cvc_save_message_delegate.h"
@@ -76,11 +80,9 @@
};
#endif
-// Exposes the protected constructor.
class TestChromeAutofillClient : public ChromeAutofillClient {
public:
- explicit TestChromeAutofillClient(content::WebContents* web_contents)
- : ChromeAutofillClient(web_contents) {}
+ using ChromeAutofillClient::ChromeAutofillClient;
#if BUILDFLAG(IS_ANDROID)
MockFastCheckoutClient* GetFastCheckoutClient() override {
@@ -98,7 +100,6 @@
}
MockFastCheckoutClient fast_checkout_client_;
- base::test::ScopedFeatureList scoped_feature_list_;
#endif
};
@@ -135,14 +136,6 @@
return personal_data_manager_;
}
- TestContentAutofillDriver* autofill_driver() {
- return test_autofill_driver_injector_[web_contents()];
- }
-
- TestBrowserAutofillManager* autofill_manager() {
- return test_autofill_manager_injector_[web_contents()];
- }
-
#if !BUILDFLAG(IS_ANDROID)
MockSaveCardBubbleController& save_card_bubble_controller() {
return static_cast<MockSaveCardBubbleController&>(
@@ -170,13 +163,8 @@
}
raw_ptr<TestPersonalDataManager> personal_data_manager_ = nullptr;
- TestAutofillClientInjector<TestChromeAutofillClient>
+ TestAutofillClientInjector<testing::NiceMock<TestChromeAutofillClient>>
test_autofill_client_injector_;
- TestAutofillDriverInjector<TestContentAutofillDriver>
- test_autofill_driver_injector_;
- TestAutofillManagerInjector<TestBrowserAutofillManager>
- test_autofill_manager_injector_;
-
base::OnceCallback<void()> setup_flags_;
};