| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // 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 <vector> |
| |
| #include "base/macros.h" |
| #include "base/memory/linked_ptr.h" |
| #include "components/autofill/content/common/autofill_agent.mojom.h" |
| #include "components/autofill/content/common/autofill_driver.mojom.h" |
| #include "components/autofill/content/renderer/renderer_save_password_progress_logger.h" |
| #include "content/public/renderer/render_frame_observer.h" |
| #include "mojo/public/cpp/bindings/associated_binding.h" |
| #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h" |
| #include "third_party/blink/public/web/web_input_element.h" |
| #include "url/gurl.h" |
| |
| namespace autofill { |
| |
| struct PasswordForm; |
| struct PasswordFormGenerationData; |
| class PasswordAutofillAgent; |
| |
| // 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() override; |
| |
| void BindRequest(mojom::PasswordGenerationAgentAssociatedRequest request); |
| |
| // mojom::PasswordGenerationAgent: |
| void FormNotBlacklisted(const PasswordForm& form) override; |
| void GeneratedPasswordAccepted(const base::string16& password) override; |
| void FoundFormsEligibleForGeneration( |
| const std::vector<PasswordFormGenerationData>& forms) override; |
| // Sets |generation_element_| to the focused password field and shows a |
| // generation popup at this field. |
| void UserTriggeredGeneratePassword() 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. |
| bool TextDidChangeInTextField(const blink::WebInputElement& element); |
| |
| // Returns true if the newly focused node caused the generation UI to show. |
| bool FocusedNodeHasChanged(const blink::WebNode& node); |
| |
| // Called when new form controls are inserted. |
| void OnDynamicFormsSeen(); |
| |
| // Called right before PasswordAutofillAgent filled |password_element|. |
| void OnFieldAutofilled(const blink::WebInputElement& password_element); |
| |
| #if defined(UNIT_TEST) |
| // This method requests the autofill::mojom::PasswordManagerClient which binds |
| // requests the binding if it wasn't bound yet. |
| void RequestPasswordManagerClientForTesting() { GetPasswordManagerClient(); } |
| #endif |
| |
| protected: |
| // Returns true if the document for |render_frame()| is one that we should |
| // consider analyzing. Virtual so that it can be overriden during testing. |
| virtual bool ShouldAnalyzeDocument(); |
| |
| // Use to force enable during testing. |
| void set_enabled(bool enabled) { enabled_ = enabled; } |
| |
| private: |
| struct AccountCreationFormData { |
| linked_ptr<PasswordForm> form; |
| std::vector<blink::WebInputElement> password_elements; |
| |
| AccountCreationFormData( |
| linked_ptr<PasswordForm> form, |
| std::vector<blink::WebInputElement> password_elements); |
| AccountCreationFormData(const AccountCreationFormData& other); |
| ~AccountCreationFormData(); |
| }; |
| |
| typedef std::vector<AccountCreationFormData> AccountCreationFormDataList; |
| |
| // RenderFrameObserver: |
| void DidCommitProvisionalLoad(bool is_same_document_navigation, |
| ui::PageTransition transition) override; |
| void DidFinishDocumentLoad() override; |
| void DidFinishLoad() override; |
| void OnDestruct() override; |
| |
| const mojom::PasswordManagerDriverAssociatedPtr& GetPasswordManagerDriver(); |
| |
| const mojom::PasswordManagerClientAssociatedPtr& GetPasswordManagerClient(); |
| |
| // Helper function that will try and populate |password_elements_| and |
| // |possible_account_creation_form_|. |
| void FindPossibleGenerationForm(); |
| |
| // Helper function to decide if |passwords_| contains password fields for |
| // an account creation form. Sets |generation_element_| to the field that |
| // we want to trigger the generation UI on. |
| void DetermineGenerationElement(); |
| |
| // 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 SetUpUserTriggeredGeneration(); |
| |
| // This is called whenever automatic generation could be offered. |
| // If manual generation was already requested, automatic generation will |
| // not be offered. |
| void MaybeOfferAutomaticGeneration(); |
| |
| // Signals the browser that it should offer or rescind automatic password |
| // generation depending whether the user has just focused a form field |
| // suitable for generation or has changed focus from such a field. |
| void AutomaticGenerationStatusChanged(bool available); |
| |
| // Show UI for editing a generated password at |generation_element_|. |
| void ShowEditingPopup(); |
| |
| // Signals the browser that generation was rejected. This happens when the |
| // user types more characters than the maximum offer size into the password |
| // field. Upon receiving this message, the browser can choose to hide the |
| // generation UI or not, depending on the platform. |
| void GenerationRejectedByTyping(); |
| |
| // Stops treating a password as generated. |
| void PasswordNoLongerGenerated(); |
| |
| // Runs HTML parsing based classifier and saves its outcome to proto. |
| // TODO(crbug.com/621442): Remove client-side form classifier when server-side |
| // classifier is ready. |
| void RunFormClassifierAndSaveVote(const blink::WebFormElement& web_form, |
| const PasswordForm& form); |
| |
| void LogMessage(autofill::SavePasswordProgressLogger::StringID message_id); |
| void LogBoolean(autofill::SavePasswordProgressLogger::StringID message_id, |
| bool truth_value); |
| void LogNumber(autofill::SavePasswordProgressLogger::StringID message_id, |
| int number); |
| |
| // Creates a password form to presave a generated password. It copies behavior |
| // of CreatePasswordFormFromWebForm/FromUnownedInputElements, but takes |
| // |password_value| from |generation_element_| and empties |username_value|. |
| // If a form creating is failed, returns an empty unique_ptr. |
| std::unique_ptr<PasswordForm> CreatePasswordFormToPresave(); |
| |
| // Stores forms that are candidates for account creation. |
| AccountCreationFormDataList possible_account_creation_forms_; |
| |
| // Stores the origins of the password forms confirmed not to be blacklisted |
| // by the browser. A form can be blacklisted if a user chooses "never save |
| // passwords for this site". |
| std::vector<GURL> not_blacklisted_password_form_origins_; |
| |
| // Stores each password form for which the Autofill server classifies one of |
| // the form's fields as an ACCOUNT_CREATION_PASSWORD or NEW_PASSWORD. These |
| // forms will not be sent if the feature is disabled. |
| std::vector<autofill::PasswordFormGenerationData> generation_enabled_forms_; |
| |
| // Data for form which generation is allowed on. |
| std::unique_ptr<AccountCreationFormData> generation_form_data_; |
| |
| // Element where we want to trigger password generation UI. |
| blink::WebInputElement generation_element_; |
| |
| // Password element that had focus last. Since Javascript could change focused |
| // element after the user triggered a generation request, it is better to save |
| // the last focused password element. |
| blink::WebInputElement last_focused_password_element_; |
| |
| // If the password field at |generation_element_| contains a generated |
| // password. |
| bool password_is_generated_; |
| |
| // True if the last password generation was manually triggered. |
| bool is_manually_triggered_; |
| |
| // True if a password was generated and the user edited it. Used for UMA |
| // stats. |
| bool password_edited_; |
| |
| // True if the generation popup was shown during this navigation. Used to |
| // track UMA stats per page visit rather than per display, since the former |
| // is more interesting. |
| // TODO(crbug.com/845458): Remove this or change the description of the |
| // logged event as calling AutomaticgenerationStatusChanged will no longer |
| // imply that a popup is shown. This could instead be logged with the |
| // metrics collected on the browser process. |
| bool generation_popup_shown_; |
| |
| // True if the editing popup was shown during this navigation. Used to track |
| // UMA stats per page rather than per display, since the former is more |
| // interesting. |
| bool editing_popup_shown_; |
| |
| // If this feature is enabled. Controlled by Finch. |
| bool enabled_; |
| |
| // True iff the generation element should be marked with special HTML |
| // attribute (only for experimental purposes). |
| bool mark_generation_element_; |
| |
| // Unowned pointer. Used to notify PassowrdAutofillAgent when values |
| // in password fields are updated. |
| PasswordAutofillAgent* password_agent_; |
| |
| mojom::PasswordManagerClientAssociatedPtr password_manager_client_; |
| |
| mojo::AssociatedBinding<mojom::PasswordGenerationAgent> binding_; |
| |
| DISALLOW_COPY_AND_ASSIGN(PasswordGenerationAgent); |
| }; |
| |
| } // namespace autofill |
| |
| #endif // COMPONENTS_AUTOFILL_CONTENT_RENDERER_PASSWORD_GENERATION_AGENT_H_ |