blob: 7129d04853b04aa837b545128a666d49b1384acb [file] [log] [blame]
// Copyright (c) 2012 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_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_MANAGER_H_
#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_MANAGER_H_
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "base/callback.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/observer_list.h"
#include "base/strings/string16.h"
#include "build/build_config.h"
#include "components/autofill/core/common/password_form.h"
#include "components/autofill/core/common/password_form_fill_data.h"
#include "components/autofill/core/common/signatures_util.h"
#include "components/password_manager/core/browser/form_parsing/password_field_prediction.h"
#include "components/password_manager/core/browser/form_submission_observer.h"
#include "components/password_manager/core/browser/login_model.h"
#include "components/password_manager/core/browser/password_form_manager.h"
#include "components/password_manager/core/browser/password_manager_metrics_recorder.h"
class PrefRegistrySimple;
namespace user_prefs {
class PrefRegistrySyncable;
}
namespace autofill {
struct FormData;
class FormStructure;
}
namespace password_manager {
class BrowserSavePasswordProgressLogger;
class PasswordManagerClient;
class PasswordManagerDriver;
class PasswordFormManager;
class NewPasswordFormManager;
// Per-tab password manager. Handles creation and management of UI elements,
// receiving password form data from the renderer and managing the password
// database through the PasswordStore. The PasswordManager is a LoginModel
// for purposes of supporting HTTP authentication dialogs.
class PasswordManager : public LoginModel, public FormSubmissionObserver {
public:
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
static void RegisterLocalPrefs(PrefRegistrySimple* registry);
explicit PasswordManager(PasswordManagerClient* client);
~PasswordManager() override;
// Called by a PasswordFormManager when it decides a HTTP auth dialog can be
// autofilled.
void AutofillHttpAuth(
const std::map<base::string16, const autofill::PasswordForm*>&
best_matches,
const autofill::PasswordForm& preferred_match) const;
// LoginModel implementation.
void AddObserverAndDeliverCredentials(
LoginModelObserver* observer,
const autofill::PasswordForm& observed_form) override;
void RemoveObserver(LoginModelObserver* observer) override;
void GenerationAvailableForForm(const autofill::PasswordForm& form);
// Presaves the form with generated password. |driver| is needed to find the
// matched form manager.
void OnPresaveGeneratedPassword(PasswordManagerDriver* driver,
const autofill::PasswordForm& form);
// Stops treating a password as generated. |driver| is needed to find the
// matched form manager.
void OnPasswordNoLongerGenerated(PasswordManagerDriver* driver,
const autofill::PasswordForm& form);
// Update the generation element and whether generation was triggered
// manually.
void SetGenerationElementAndReasonForForm(
PasswordManagerDriver* driver,
const autofill::PasswordForm& form,
const base::string16& generation_element,
bool is_manually_triggered);
// TODO(isherman): This should not be public, but is currently being used by
// the LoginPrompt code.
// When a form is submitted, we prepare to save the password but wait
// until we decide the user has successfully logged in. This is step 1
// of 2 (see SavePassword).
// |driver| is optional and if it's given it should be a driver that
// corresponds to a frame from which |form| comes from.
void ProvisionallySavePassword(const autofill::PasswordForm& form,
const PasswordManagerDriver* driver);
// FormSubmissionObserver:
void DidNavigateMainFrame(bool form_may_be_submitted) override;
// Handles password forms being parsed.
void OnPasswordFormsParsed(PasswordManagerDriver* driver,
const std::vector<autofill::PasswordForm>& forms);
// Handles password forms being rendered.
void OnPasswordFormsRendered(
PasswordManagerDriver* driver,
const std::vector<autofill::PasswordForm>& visible_forms,
bool did_stop_loading);
// Handles a password form being submitted.
void OnPasswordFormSubmitted(PasswordManagerDriver* driver,
const autofill::PasswordForm& password_form);
// Handles a password form being submitted, assumes that submission is
// successful and does not do any checks on success of submission.
// For example, this is called if |password_form| was filled
// upon in-page navigation. This often means history.pushState being
// called from JavaScript.
void OnPasswordFormSubmittedNoChecks(
PasswordManagerDriver* driver,
const autofill::PasswordForm& password_form);
// Handles a request to show manual fallback for password saving, i.e. the
// omnibox icon with the anchored hidden prompt.
void ShowManualFallbackForSaving(PasswordManagerDriver* driver,
const autofill::PasswordForm& password_form);
// Handles a request to hide manual fallback for password saving.
void HideManualFallbackForSaving();
void ProcessAutofillPredictions(
PasswordManagerDriver* driver,
const std::vector<autofill::FormStructure*>& forms);
// Causes all |pending_login_managers_| to query the password store again.
// Results in updating the fill information on the page.
void UpdateFormManagers();
// Cleans the state by removing all the PasswordFormManager instances and
// visible forms.
void DropFormManagers();
// Returns true if password element is detected on the current page.
bool IsPasswordFieldDetectedOnPage();
PasswordManagerClient* client() { return client_; }
#if defined(UNIT_TEST)
// TODO(crbug.com/639786): Replace using this by quering the factory for
// mocked PasswordFormManagers.
const std::vector<std::unique_ptr<PasswordFormManager>>&
pending_login_managers() const {
return pending_login_managers_;
}
const PasswordFormManager* provisional_save_manager() const {
return provisional_save_manager_.get();
}
const std::vector<std::unique_ptr<NewPasswordFormManager>>& form_managers()
const {
return form_managers_;
}
PasswordFormManagerInterface* GetSubmittedManagerForTest() const {
return GetSubmittedManager();
}
#endif
// Reports the priority of a PasswordGenerationRequirementsSpec for a
// generated password. See
// PasswordFormMetricsRecorder::ReportSpecPriorityForGeneratedPassword.
void ReportSpecPriorityForGeneratedPassword(
const autofill::PasswordForm& password_form,
uint32_t spec_priority);
// Reports the success from the renderer's PasswordAutofillAgent to fill
// credentials into a site. This may be called multiple times, but only
// the first result will be recorded for each PasswordFormManager.
void LogFirstFillingResult(PasswordManagerDriver* driver,
uint32_t form_renderer_id,
int32_t result);
private:
FRIEND_TEST_ALL_PREFIXES(
PasswordManagerTest,
ShouldBlockPasswordForSameOriginButDifferentSchemeTest);
// Clones |matched_manager| and keeps it as |provisional_save_manager_|.
// |form| is saved provisionally to |provisional_save_manager_|.
void ProvisionallySaveManager(const autofill::PasswordForm& form,
PasswordFormManager* matched_manager,
BrowserSavePasswordProgressLogger* logger);
// Returns true if there is a form manager for a submitted form and this form
// manager contains the submitted credentials suitable for automatic save
// prompt, not for manual fallback only.
bool IsAutomaticSavePromptAvailable();
// Returns true if there already exists a provisionally saved password form
// from the same origin as |form|, but with a different and secure scheme.
// This prevents a potential attack where users can be tricked into saving
// unwanted credentials, see http://crbug.com/571580 for details.
bool ShouldBlockPasswordForSameOriginButDifferentScheme(
const autofill::PasswordForm& form) const;
// Called when the login was deemed successful. It handles the special case
// when the provisionally saved password is a sync credential, and otherwise
// asks the user about saving the password or saves it directly, as
// appropriate.
void OnLoginSuccessful();
// Helper function called inside OnLoginSuccessful() to save password hash
// data from |submitted_manager| for password reuse detection purpose.
void MaybeSavePasswordHash(
const PasswordFormManagerInterface& submitted_manager);
// Checks for every form in |forms| whether |pending_login_managers_| already
// contain a manager for that form. If not, adds a manager for each such form.
void CreatePendingLoginManagers(
PasswordManagerDriver* driver,
const std::vector<autofill::PasswordForm>& forms);
// Checks for every form in |forms| whether |form_managers_| already contain a
// manager for that form. If not, adds a manager for each such form.
void CreateFormManagers(PasswordManagerDriver* driver,
const std::vector<autofill::PasswordForm>& forms);
// Create NewPasswordFormManager for |form|, adds the newly created one to
// |form_managers_| and returns it.
NewPasswordFormManager* CreateFormManager(PasswordManagerDriver* driver,
const autofill::FormData& forms);
// Passes |form| to NewPasswordFormManager that manages it for using it after
// detecting submission success for saving. |driver| is needed to determine
// the match. If the function is called multiple times, only the form from the
// last call is provisionally saved. Multiple calls is possible because it is
// called on any user keystroke. If there is no NewPasswordFormManager that
// manages |form|, the new one is created.
// Returns manager which manages |form|.
NewPasswordFormManager* ProvisionallySaveForm(const autofill::FormData& form,
PasswordManagerDriver* driver);
// Returns the best match in |pending_login_managers_| for |form|. May return
// nullptr if no match exists.
PasswordFormManager* GetMatchingPendingManager(
const autofill::PasswordForm& form);
// Returns the form manager that corresponds to the submitted form. It might
// be nullptr if there is no submitted form.
// TODO(https://crbug.com/831123): Remove when the old PasswordFormManager is
// gone.
PasswordFormManagerInterface* GetSubmittedManager() const;
private:
// Returns the form manager that corresponds to the submitted form. It also
// sets |submitted_form_manager_| to nullptr.
// TODO(https://crbug.com/831123): Remove when the old PasswordFormManager is
// gone.
std::unique_ptr<PasswordFormManagerForUI> MoveOwnedSubmittedManager();
// Records provisional save failure using current |client_| and
// |main_frame_url_|.
void RecordProvisionalSaveFailure(
PasswordManagerMetricsRecorder::ProvisionalSaveFailure failure,
const GURL& form_origin,
BrowserSavePasswordProgressLogger* logger);
scoped_refptr<PasswordFormMetricsRecorder>
GetMetricRecorderFromNewPasswordFormManager(
const autofill::FormData& form,
const PasswordManagerDriver* driver);
// Returns the manager which manages |form|. |driver| is needed to determine
// the match. Returns nullptr when no matched manager is found.
PasswordFormManagerInterface* GetMatchedManager(
const PasswordManagerDriver* driver,
const autofill::PasswordForm& form);
// Note about how a PasswordFormManager can transition from
// pending_login_managers_ to provisional_save_manager_ and the infobar.
//
// 1. form "seen"
// | new
// | ___ Infobar
// pending_login -- form submit --> provisional_save ___/
// ^ | \___ (update DB)
// | fail
// |-----------<------<---------| !new
//
// When a form is "seen" on a page, a PasswordFormManager is created
// and stored in this collection until user navigates away from page.
std::vector<std::unique_ptr<PasswordFormManager>> pending_login_managers_;
// When the user submits a password/credential, this contains the
// PasswordFormManager for the form in question until we deem the login
// attempt to have succeeded (as in valid credentials). If it fails, we
// send the PasswordFormManager back to the pending_login_managers_ set.
// Scoped in case PasswordManager gets deleted (e.g tab closes) between the
// time a user submits a login form and gets to the next page.
std::unique_ptr<PasswordFormManager> provisional_save_manager_;
// NewPasswordFormManager transition schemes:
// 1. HTML submission with navigation afterwads.
// form "seen"
// |
// form_managers -- submit --> (is_submitted = true) -- navigation --
//
// __ Prompt.
// owned_submitted_form_manager --> (successful submission) __ Automatic save.
//
// 2.Other submssions detection types (XHR, frame detached, in-page
// navigation etc) without navigation.
// form "seen"
// |
// form_managers -- successful submission (success is detected in the Render)
// ____ Prompt.
// --> (is_submitted = true) ---- Automatic save.
// Contains one NewPasswordFormManager per each form on the page.
// When a form is "seen" on a page, a NewPasswordFormManager is created
// and stored in this collection until user navigates away from page.
std::vector<std::unique_ptr<NewPasswordFormManager>> form_managers_;
// Corresponds to the submitted form, after navigion away before submission
// success detection is finished.
std::unique_ptr<NewPasswordFormManager> owned_submitted_form_manager_;
// The embedder-level client. Must outlive this class.
PasswordManagerClient* const client_;
// Observers to be notified of LoginModel events. This is mutable to allow
// notification in const member functions.
mutable base::ObserverList<LoginModelObserver>::Unchecked observers_;
// Records all visible forms seen during a page load, in all frames of the
// page. When the page stops loading, the password manager checks if one of
// the recorded forms matches the login form from the previous page
// (to see if the login was a failure), and clears the vector.
std::vector<autofill::PasswordForm> all_visible_forms_;
// Server predictions for the forms on the page.
std::map<autofill::FormSignature, FormPredictions> predictions_;
// The user-visible URL from the last time a password was provisionally saved.
GURL main_frame_url_;
const bool is_new_form_parsing_for_saving_enabled_;
// If true, it turns off using PasswordFormManager in PasswordManager.
const bool is_only_new_parser_enabled_;
DISALLOW_COPY_AND_ASSIGN(PasswordManager);
};
} // namespace password_manager
#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_MANAGER_H_