| // Copyright 2013 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_RENDERER_PASSWORD_GENERATION_AGENT_H_ |
| #define COMPONENTS_AUTOFILL_CONTENT_RENDERER_PASSWORD_GENERATION_AGENT_H_ |
| |
| #include <stddef.h> |
| |
| #include <map> |
| #include <memory> |
| #include <utility> |
| |
| #include "base/memory/raw_ptr.h" |
| #include "components/autofill/content/common/mojom/autofill_agent.mojom.h" |
| #include "components/autofill/content/common/mojom/autofill_driver.mojom.h" |
| #include "components/autofill/content/renderer/renderer_save_password_progress_logger.h" |
| #include "components/autofill/core/common/unique_ids.h" |
| #include "content/public/renderer/render_frame_observer.h" |
| #include "mojo/public/cpp/bindings/associated_receiver.h" |
| #include "mojo/public/cpp/bindings/associated_remote.h" |
| #include "mojo/public/cpp/bindings/pending_associated_receiver.h" |
| #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h" |
| #include "third_party/blink/public/web/web_input_element.h" |
| |
| namespace autofill { |
| |
| class PasswordAutofillAgent; |
| class SynchronousFormCache; |
| |
| // This class is responsible for controlling communication for password |
| // generation between the browser (which shows the popup and generates |
| // passwords) and WebKit (shows the generation icon in the password field). |
| class PasswordGenerationAgent : public content::RenderFrameObserver, |
| public mojom::PasswordGenerationAgent { |
| public: |
| // Maximum number of characters typed by user while the generation is still |
| // offered. When the (kMaximumCharsForGenerationOffer + 1)-th character is |
| // typed, the generation becomes unavailable. |
| static const size_t kMaximumCharsForGenerationOffer = 5; |
| |
| // User can edit the generated password. If the length falls below this value, |
| // the password is no longer considered generated. |
| static const size_t kMinimumLengthForEditedPassword = 4; |
| |
| PasswordGenerationAgent(content::RenderFrame* render_frame, |
| PasswordAutofillAgent* password_agent, |
| blink::AssociatedInterfaceRegistry* registry); |
| |
| PasswordGenerationAgent(const PasswordGenerationAgent&) = delete; |
| PasswordGenerationAgent& operator=(const PasswordGenerationAgent&) = delete; |
| |
| ~PasswordGenerationAgent() override; |
| |
| void BindPendingReceiver( |
| mojo::PendingAssociatedReceiver<mojom::PasswordGenerationAgent> |
| pending_receiver); |
| |
| // mojom::PasswordGenerationAgent: |
| void GeneratedPasswordAccepted(const std::u16string& password) override; |
| void GeneratedPasswordRejected() override; |
| void FoundFormEligibleForGeneration( |
| const PasswordFormGenerationData& form) override; |
| // Sets |generation_element_| to the focused password field and responds back |
| // if the generation was triggered successfully. |
| void TriggeredGeneratePassword( |
| TriggeredGeneratePasswordCallback callback) override; |
| void FocusNextFieldAfterPasswords() override; |
| |
| // Returns true if the field being changed is one where a generated password |
| // is being offered. Updates the state of the popup if necessary. `form_cache` |
| // can be used to optimize form extractions occurring synchronously after this |
| // function call. |
| bool TextDidChangeInTextField(const blink::WebInputElement& element, |
| const SynchronousFormCache& form_cache); |
| |
| // Returns true if the newly focused node caused the generation UI to show. |
| bool ShowPasswordGenerationSuggestions( |
| const blink::WebInputElement& element, |
| const SynchronousFormCache& form_cache); |
| |
| // Event forwarded by AutofillAgent from WebAutofillClient, informing that |
| // the text field editing has ended, which means that the field is not |
| // focused anymore. This is required for Android, where moving focus |
| // to a non-focusable element doesn't result in |FocusedNodeHasChanged| |
| // being called. |
| void DidEndTextFieldEditing(const blink::WebInputElement& element); |
| |
| // Event forwarded by AutofillAgent from WebAutofillClient, informing that the |
| // text field was cleared. For password fields this means that they are no |
| // longer generated and should be masked. |
| void TextFieldCleared(const blink::WebInputElement& element); |
| |
| // Called right before PasswordAutofillAgent filled |password_element|. |
| void OnFieldAutofilled(const blink::WebInputElement& password_element); |
| |
| // Returns true iff the currently handled 'blur' event is fake and should be |
| // ignored. |
| bool ShouldIgnoreBlur() const; |
| |
| #if defined(UNIT_TEST) |
| // This method requests the mojom::PasswordManagerClient which binds |
| // requests the binding if it wasn't bound yet. |
| void RequestPasswordManagerClientForTesting() { |
| GetPasswordGenerationDriver(); |
| } |
| #endif |
| |
| bool IsPrerendering() const; |
| |
| // Previews the generation suggestion for the current generation element. |
| void PreviewGenerationSuggestion(const std::u16string& password); |
| |
| // Clears the previewed field if it was previously previewed. |
| void ClearPreviewedForm(); |
| |
| private: |
| class DeferringPasswordGenerationDriver; |
| |
| // Contains information about generation status for an element for the |
| // lifetime of the possible interaction. |
| struct GenerationItemInfo; |
| |
| // RenderFrameObserver: |
| void DidCommitProvisionalLoad(ui::PageTransition transition) override; |
| void DidChangeScrollOffset() override; |
| void OnDestruct() override; |
| |
| mojom::PasswordManagerDriver& GetPasswordManagerDriver(); |
| |
| // Callers should not store the returned value longer than a function scope. |
| mojom::PasswordGenerationDriver& GetPasswordGenerationDriver(); |
| |
| // Helper function which takes care of the form processing and collecting the |
| // information which is required to show the generation popup. Returns true if |
| // all required information is collected. |
| bool SetUpTriggeredGeneration(); |
| |
| // This is called whenever automatic generation could be offered, and returns |
| // true if generation was offered. |
| // If manual generation was already requested, automatic generation is not |
| // offered. |
| bool MaybeOfferAutomaticGeneration(); |
| |
| // Signals the browser that it should offer automatic password generation |
| // as a result of the user focusing a password field eligible for generation. |
| void AutomaticGenerationAvailable(); |
| |
| #if !BUILDFLAG(IS_ANDROID) |
| // Show UI for editing a generated password at |generation_element_|. |
| void ShowEditingPopup(const SynchronousFormCache& form_cache); |
| #endif // !BUILDFLAG(IS_ANDROID) |
| |
| // Stops treating a password as generated. |
| void PasswordNoLongerGenerated(); |
| |
| // Creates |current_generation_item_| for |element| if |element| is a |
| // generation enabled element. If |current_generation_item_| is already |
| // created for |element| it is not recreated. |
| void MaybeCreateCurrentGenerationItem( |
| blink::WebInputElement element, |
| FieldRendererId confirmation_password_renderer_id, |
| const SynchronousFormCache& form_cache); |
| |
| void LogMessage(SavePasswordProgressLogger::StringID message_id); |
| void LogBoolean(SavePasswordProgressLogger::StringID message_id, |
| bool truth_value); |
| |
| // Creates a FormData to presave a generated password. It copies behavior |
| // of CreateFromDataFromWebForm/FromUnownedInputElements. If a form |
| // creating is failed, returns an empty unique_ptr. `form_cache` can be used |
| // to optimize form extractions occurring synchronously after this function |
| // call. |
| std::optional<FormData> CreateFormDataToPresave( |
| const SynchronousFormCache& form_cache); |
| |
| // Contains the current element where generation is offered at the moment. It |
| // can be either automatic or manual password generation. |
| std::unique_ptr<GenerationItemInfo> current_generation_item_; |
| |
| // Contains correspondence between generation enabled element and data for |
| // generation. |
| std::map<FieldRendererId, PasswordFormGenerationData> |
| generation_enabled_fields_; |
| |
| // True iff the generation element should be marked with special HTML |
| // attribute (only for experimental purposes). |
| const bool mark_generation_element_; |
| |
| // Unowned pointer. Used to notify PassowrdAutofillAgent when values |
| // in password fields are updated. |
| const raw_ptr<PasswordAutofillAgent> password_agent_; |
| |
| mojo::AssociatedRemote<mojom::PasswordGenerationDriver> |
| password_generation_client_; |
| |
| // Used for deferring messages while prerendering. |
| std::unique_ptr<DeferringPasswordGenerationDriver> |
| deferring_password_generation_driver_; |
| |
| mojo::AssociatedReceiver<mojom::PasswordGenerationAgent> receiver_{this}; |
| }; |
| |
| } // namespace autofill |
| |
| #endif // COMPONENTS_AUTOFILL_CONTENT_RENDERER_PASSWORD_GENERATION_AGENT_H_ |