| // Copyright 2014 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef COMPONENTS_AUTOFILL_CONTENT_BROWSER_CONTENT_AUTOFILL_DRIVER_H_ |
| #define COMPONENTS_AUTOFILL_CONTENT_BROWSER_CONTENT_AUTOFILL_DRIVER_H_ |
| |
| #include <map> |
| #include <optional> |
| #include <string> |
| #include <vector> |
| |
| #include "base/containers/flat_map.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/raw_ref.h" |
| #include "base/types/optional_ref.h" |
| #include "components/autofill/content/browser/content_autofill_client.h" |
| #include "components/autofill/content/common/mojom/autofill_agent.mojom.h" |
| #include "components/autofill/content/common/mojom/autofill_driver.mojom.h" |
| #include "components/autofill/core/browser/foundations/autofill_driver.h" |
| #include "components/autofill/core/browser/foundations/autofill_manager.h" |
| #include "components/autofill/core/common/form_data.h" |
| #include "components/autofill/core/common/mojom/autofill_types.mojom-shared.h" |
| #include "content/public/browser/render_frame_host.h" |
| #include "content/public/browser/render_widget_host.h" |
| #include "mojo/public/cpp/bindings/associated_receiver.h" |
| #include "mojo/public/cpp/bindings/associated_remote.h" |
| #include "mojo/public/cpp/bindings/pending_receiver.h" |
| |
| namespace autofill { |
| |
| class ContentAutofillDriverFactory; |
| class AutofillDriverRouter; |
| |
| // ContentAutofillDriver drives the Autofill flow in the browser process based |
| // on communication from the renderer and from the external world. |
| // |
| // Each ContentAutofillDriver is associated with exactly one RenderFrameHost |
| // and communicates with exactly one AutofillAgent throughout its entire |
| // lifetime. |
| // |
| // This RenderFrameHost owns all forms and fields in the renderer-browser |
| // communication: |
| // - ContentAutofillDriver may assume that forms and fields received in the |
| // mojom::AutofillDriver events are owned by that RenderFrameHost. |
| // - Conversely, the forms and fields which ContentAutofillDriver passes to |
| // mojom::AutofillAgent events must be owned by that RenderFrameHost. |
| // |
| // Events in AutofillDriver and mojom::AutofillDriver are passed on to |
| // AutofillDriverRouter, which has one instance per WebContents. The naming |
| // pattern is that for all of these events, there are two functions: |
| // |
| // 1. ReturnType ContentAutofillDriver::Foo(Args...) |
| // 2. ReturnType AutofillDriverRouter::Foo(RoutedCallback, Args...) |
| // |
| // The first function calls the second, and the second calls the callback. |
| // That callback takes a target AutofillDriver, which may be different from the |
| // first function's ContentAutofillDriver. |
| // |
| // Consider the following pseudo-HTML: |
| // <!-- frame name "ABC" --> |
| // <form> |
| // <input> <!-- renderer_id = 12 --> |
| // <input> <!-- renderer_id = 34 --> |
| // <iframe name="DEF"> |
| // <input> <!-- renderer_id = 56 --> |
| // <input> <!-- renderer_id = 78 --> |
| // </iframe> |
| // </form> |
| // In this case, the frame "ABC" holds a form with fields |
| // FormFieldData{.host_frame = ABC, .renderer_id = 12, ...}, |
| // FormFieldData{.host_frame = ABC, .renderer_id = 34, ...}, |
| // and the frame "DEF" holds a form with fields |
| // FormFieldData{.host_frame = DEF, .renderer_id = 56, ...}, |
| // FormFieldData{.host_frame = DEF, .renderer_id = 78, ...}. |
| // The SendFieldsEligibleForManualFillingToRenderer() event, for example, is |
| // initiated by ABC's AutofillManager by calling |
| // abc_driver->SendFieldsEligibleForManualFillingToRenderer({ |
| // FieldGlobalId{.host_frame = ABC, .renderer_id = 12}, |
| // FieldGlobalId{.host_frame = ABC, .renderer_id = 34}, |
| // FieldGlobalId{.host_frame = DEF, .renderer_id = 56}, |
| // FieldGlobalId{.host_frame = DEF, .renderer_id = 78} |
| // }). |
| // |abc_driver| forwards the event to the router by calling |
| // router->SendFieldsEligibleForManualFillingToRenderer(abc_driver, { |
| // FieldGlobalId{.host_frame = ABC, .renderer_id = 12}, |
| // FieldGlobalId{.host_frame = ABC, .renderer_id = 34}, |
| // FieldGlobalId{.host_frame = DEF, .renderer_id = 56}, |
| // FieldGlobalId{.host_frame = DEF, .renderer_id = 78} |
| // }, callback). |
| // The router splits the groups the fields by their host frame token and routes |
| // the calls to the respective frame's drivers: |
| // callback(abc_driver, { |
| // FieldRendererId{.renderer_id = 12}, |
| // FieldRendererId{.renderer_id = 34}, |
| // }); |
| // callback(def_driver, { |
| // FieldRendererId{.renderer_id = 56}, |
| // FieldRendererId{.renderer_id = 78} |
| // }); |
| // These callbacks call the agents in the renderer processes: |
| // abc_agent->SetFieldsEligibleForManualFilling({ |
| // FieldRendererId{.renderer_id = 12}, |
| // FieldRendererId{.renderer_id = 34}, |
| // }); |
| // def_agent->SetFieldsEligibleForManualFilling({ |
| // FieldRendererId{.renderer_id = 56}, |
| // FieldRendererId{.renderer_id = 78} |
| // }); |
| // |
| // See AutofillDriverRouter for further details. |
| class ContentAutofillDriver : public AutofillDriver, |
| public mojom::AutofillDriver { |
| public: |
| class ContentAutofillDriverFactoryPassKey { |
| private: |
| friend class ContentAutofillDriverFactory; |
| friend class ContentAutofillDriverTestApi; |
| ContentAutofillDriverFactoryPassKey() = default; |
| }; |
| |
| // Gets the driver for |render_frame_host|. |
| // If |render_frame_host| is currently being deleted, this may be nullptr. |
| static ContentAutofillDriver* GetForRenderFrameHost( |
| content::RenderFrameHost* render_frame_host); |
| |
| // Part of the initialization may be embedder-specific, implemented in |
| // ContentAutofillClient::CreateManager(). |
| ContentAutofillDriver(content::RenderFrameHost* render_frame_host, |
| ContentAutofillDriverFactory* owner); |
| ContentAutofillDriver(const ContentAutofillDriver&) = delete; |
| ContentAutofillDriver& operator=(const ContentAutofillDriver&) = delete; |
| ~ContentAutofillDriver() override; |
| |
| // Clears the driver's and the manager's stored forms and other state, |
| // *except* for the LifecycleState, which is controlled by the |
| // AutofillDriverFactory. Called on certain types of navigations. |
| void Reset(ContentAutofillDriverFactoryPassKey pass_key); |
| |
| content::RenderFrameHost* render_frame_host() { return &*render_frame_host_; } |
| const content::RenderFrameHost* render_frame_host() const { |
| return &*render_frame_host_; |
| } |
| |
| // Expose the events that originate from the browser and renderer processes, |
| // respectively. |
| // |
| // The purpose of not exposing these events directly in ContentAutofillDriver |
| // is to make the caller aware of the event's intended source. This is |
| // relevant because renderer forms and browser forms have distinct properties: |
| // certain fields are not set in renderer form (see SetFrameAndFormMetaData() |
| // for details) and, if they are part of a frame-transcending form, they are |
| // not flattened yet (see AutofillDriverRouter for details). |
| autofill::AutofillDriver& browser_events() { return *this; } |
| mojom::AutofillDriver& renderer_events() { return *this; } |
| |
| void BindPendingReceiver( |
| mojo::PendingAssociatedReceiver<mojom::AutofillDriver> pending_receiver); |
| const mojo::AssociatedRemote<mojom::AutofillAgent>& GetAutofillAgent(); |
| |
| // autofill::AutofillDriver: |
| // These are the non-event functions from autofill::AutofillDriver. The events |
| // are defined in the private part below. |
| LocalFrameToken GetFrameToken() const override; |
| std::optional<LocalFrameToken> Resolve(FrameToken query) override; |
| ContentAutofillDriver* GetParent() override; |
| ContentAutofillClient& GetAutofillClient() override; |
| AutofillManager& GetAutofillManager() override; |
| ukm::SourceId GetPageUkmSourceId() const override; |
| bool IsActive() const override; |
| bool HasSharedAutofillPermission() const override; |
| bool CanShowAutofillUi() const override; |
| std::optional<net::IsolationInfo> GetIsolationInfo() override; |
| |
| private: |
| friend class ContentAutofillDriverTestApi; |
| |
| // Communication falls into two groups: |
| // |
| // (1) Browser -> renderer (autofill::AutofillDriver): |
| // These events are triggered by an AutofillManager or similar and are |
| // passed to one or multiple AutofillAgents. They fall into four groups: |
| // (1a) Broadcast events are sent to all AutofillAgents. |
| // (1b) Routed events are sent to a single or sometimes multiple selected |
| // AutofillAgents, which might not be this driver's AutofillAgent. |
| // (1c) Main-frame events are sent to the driver's main frame's |
| // AutofillAgent. |
| // (1d) Unrouted events are sent to this driver's AutofillAgent. |
| // (2) Renderer -> browser (mojom::AutofillDriver): |
| // These events are triggered by an AutofillAgent and are passed to one or |
| // multiple AutofillManagers. They fall into two groups: |
| // (2a) Broadcast events are sent to all AutofillManagers. |
| // (2b) Routed events are sent to a single AutofillManager, which might |
| // not be this driver's AutofillManager. |
| // |
| // These events are private to avoid accidental use in the browser process. |
| // Groups (1) and (2) can be accessed explicitly through browser_events() and |
| // renderer_events(), respectively. |
| // |
| // Keep the events of each group in alphabetic order. |
| |
| // Group (1a): browser -> renderer events, broadcast (see comment above). |
| // autofill::AutofillDriver: |
| void ExposeDomNodeIdsInAllFrames() override; |
| void TriggerFormExtractionInAllFrames( |
| base::OnceCallback<void(bool success)> form_extraction_finished_callback) |
| override; |
| void RendererShouldClearPreviewedForm() override; |
| |
| // Group (1b): browser -> renderer events, routed (see comment above). |
| // autofill::AutofillDriver: |
| base::flat_set<FieldGlobalId> ApplyFormAction( |
| mojom::FormActionType action_type, |
| mojom::ActionPersistence action_persistence, |
| base::span<const FormFieldData> data, |
| const url::Origin& triggered_origin, |
| const base::flat_map<FieldGlobalId, FieldType>& field_type_map, |
| const Section& section_for_clear_form_on_ios) override; |
| void ApplyFieldAction(mojom::FieldActionType action_type, |
| mojom::ActionPersistence action_persistence, |
| const FieldGlobalId& field_id, |
| const std::u16string& value) override; |
| void DispatchEmailVerifiedEvent( |
| FieldGlobalId field_id, |
| const std::string& presentation_token) override; |
| void ExtractForm(FormGlobalId form, |
| BrowserFormHandler final_handler) override; |
| void RendererShouldAcceptDataListSuggestion( |
| const FieldGlobalId& field_id, |
| const std::u16string& value) override; |
| void RendererShouldSetSuggestionAvailability( |
| const FieldGlobalId& field_id, |
| mojom::AutofillSuggestionAvailability suggestion_availability) override; |
| void RendererShouldTriggerSuggestions( |
| const FieldGlobalId& field_id, |
| AutofillSuggestionTriggerSource trigger_source) override; |
| void SendTypePredictionsToRenderer(const FormStructure& form) override; |
| |
| // Group (1c): browser -> renderer events, directed to this driver's main |
| // frame's agent (see comment above). |
| // autofill::AutofillDriver: |
| void GetFourDigitCombinationsFromDom( |
| base::OnceCallback<void(const std::vector<std::string>&)> |
| potential_matches) override; |
| // TODO(crbug.com/356442446): This event is currently routed to the main frame |
| // but it should be broadcasted to all RenderFrames when we want to collect |
| // the final checkout amount from all frames. |
| void ExtractLabeledTextNodeValue( |
| const std::u16string& value_regex, |
| const std::u16string& label_regex, |
| uint32_t number_of_ancestor_levels_to_search, |
| base::OnceCallback<void(const std::string& amount)> response_callback) |
| override; |
| |
| // Group (1d): browser -> renderer events, unrouted (see comment above). |
| // autofill::AutofillDriver: |
| void TriggerFormExtractionInDriverFrame( |
| AutofillDriverRouterAndFormForestPassKey pass_key) override; |
| |
| // Group (2a): renderer -> browser events, broadcast (see comment above). |
| // mojom::AutofillDriver: |
| void DidEndTextFieldEditing() override; |
| void FocusOnNonFormField() override; |
| void HidePopup() override; |
| |
| // Group (2b): renderer -> browser events, routed (see comment above). |
| // mojom::AutofillDriver: |
| void AskForValuesToFill(const FormData& form, |
| FieldRendererId field_id, |
| const gfx::Rect& caret_bounds, |
| AutofillSuggestionTriggerSource trigger_source, |
| const std::optional<PasswordSuggestionRequest>& |
| password_request) override; |
| void DidAutofillForm(const FormData& form, |
| base::TimeTicks timestamp) override; |
| void FocusOnFormField(const FormData& form, |
| FieldRendererId field_id) override; |
| void FormsSeen(const std::vector<FormData>& updated_forms, |
| const std::vector<FormRendererId>& removed_forms) override; |
| void FormSubmitted(const FormData& form, |
| mojom::SubmissionSource submission_source) override; |
| void JavaScriptChangedAutofilledValue( |
| const FormData& form, |
| FieldRendererId field_id, |
| const std::u16string& old_value) override; |
| void SelectControlSelectionChanged(const FormData& form, |
| FieldRendererId field_id) override; |
| void SelectFieldOptionsDidChange(const FormData& form) override; |
| void CaretMovedInFormField(const FormData& form, |
| FieldRendererId field_id, |
| const gfx::Rect& caret_bounds) override; |
| void TextFieldValueChanged(const FormData& form, |
| FieldRendererId field_id, |
| base::TimeTicks timestamp) override; |
| void TextFieldDidScroll(const FormData& form, |
| FieldRendererId field_id) override; |
| |
| void LiftForTest(FormData& form); |
| |
| // The router must only route among ContentAutofillDrivers because |
| // ContentAutofillDriver casts AutofillDrivers to ContentAutofillDrivers. |
| AutofillDriverRouter& router(); |
| |
| // The frame/document to which this driver is associated. Outlives `this`. |
| // RFH is corresponds to neither a frame nor a document: it may survive |
| // navigations that documents don't, but it may not survive cross-origin |
| // navigations. |
| const raw_ref<content::RenderFrameHost> render_frame_host_; |
| |
| // The factory that created this driver. Outlives `this`. |
| const raw_ref<ContentAutofillDriverFactory> owner_; |
| |
| mojo::AssociatedReceiver<mojom::AutofillDriver> receiver_{this}; |
| |
| mojo::AssociatedRemote<mojom::AutofillAgent> autofill_agent_; |
| |
| std::unique_ptr<AutofillManager> autofill_manager_ = nullptr; |
| }; |
| |
| } // namespace autofill |
| |
| #endif // COMPONENTS_AUTOFILL_CONTENT_BROWSER_CONTENT_AUTOFILL_DRIVER_H_ |