blob: 9830285e99a174df0dcfd0bd4682718434567b0c [file] [log] [blame]
// Copyright 2018 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 CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_ACCESSORY_CONTROLLER_H_
#define CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_ACCESSORY_CONTROLLER_H_
#include <map>
#include <memory>
#include <utility>
#include <vector>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
#include "components/autofill/core/common/filling_status.h"
#include "components/autofill/core/common/password_generation_util.h"
#include "content/public/browser/web_contents_user_data.h"
#include "ui/gfx/native_widget_types.h"
#include "url/gurl.h"
namespace autofill {
struct PasswordForm;
} // namespace autofill
namespace password_manager {
class PasswordManagerDriver;
} // namespace password_manager
class PasswordAccessoryViewInterface;
class PasswordGenerationDialogViewInterface;
// The controller for the view located below the keyboard accessory.
// Upon creation, it creates (and owns) a corresponding PasswordAccessoryView.
// This view will be provided with data and will notify this controller about
// interactions (like requesting to fill a password suggestions).
//
// Create it for a WebContents instance by calling:
// PasswordAccessoryController::CreateForWebContents(web_contents);
// After that, it's attached to the |web_contents| instance and can be retrieved
// by calling:
// PasswordAccessoryController::FromWebContents(web_contents);
// Any further calls to |CreateForWebContents| will be a noop.
//
// TODO(fhorschig): This class currently only supports credentials originating
// from the main frame. Supporting iframes is intended: https://crbug.com/854150
class PasswordAccessoryController
: public content::WebContentsUserData<PasswordAccessoryController> {
public:
using CreateDialogFactory = base::RepeatingCallback<std::unique_ptr<
PasswordGenerationDialogViewInterface>(PasswordAccessoryController*)>;
~PasswordAccessoryController() override;
// Saves credentials for an origin so that they can be used in the sheet.
void SavePasswordsForOrigin(
const std::map<base::string16, const autofill::PasswordForm*>&
best_matches,
const url::Origin& origin);
// Notifies the view that automatic password generation status changed.
void OnAutomaticGenerationStatusChanged(
bool available,
const base::Optional<
autofill::password_generation::PasswordGenerationUIData>& ui_data,
const base::WeakPtr<password_manager::PasswordManagerDriver>& driver);
// Called by the UI code to request that |textToFill| is to be filled into the
// currently focused field.
void OnFillingTriggered(bool is_password, const base::string16& textToFill);
// Called by the UI code because a user triggered the |selectedOption|.
void OnOptionSelected(const base::string16& selectedOption) const;
// Called by the UI code to signal that the user requested password
// generation. This should prompt a modal dialog with the generated password.
void OnGenerationRequested();
// Called from the modal dialog if the user accepted the generated password.
void GeneratedPasswordAccepted(const base::string16& password);
// Called from the modal dialog if the user rejected the generated password.
void GeneratedPasswordRejected();
// Called from the modal dialog when the user taps on the link contained
// in the explanation text that leads to the saved passwords.
void OnSavedPasswordsLinkClicked();
// Compeletes a filling attempt by recording metrics, giving feedback to the
// user and dismissing the accessory sheet.
void OnFilledIntoFocusedField(autofill::FillingStatus status);
// Makes sure, that all shown suggestions are appropriate for the currently
// focused field.
void RefreshSuggestionsForField(bool is_fillable, bool is_password_field);
// The web page view containing the focused field.
gfx::NativeView container_view() const;
gfx::NativeWindow native_window() const;
// Like |CreateForWebContents|, it creates the controller and attaches it to
// the given |web_contents|. Additionally, it allows inject a fake/mock view.
static void CreateForWebContentsForTesting(
content::WebContents* web_contents,
std::unique_ptr<PasswordAccessoryViewInterface> test_view,
CreateDialogFactory create_dialog_callback);
#if defined(UNIT_TEST)
// Returns the held view for testing.
PasswordAccessoryViewInterface* view() const { return view_.get(); }
#endif // defined(UNIT_TEST)
private:
// Data including the form and field for which generation was requested,
// their signatures and the maximum password size.
struct GenerationElementData;
// Data for a credential pair that is transformed into a suggestion.
struct SuggestionElementData;
// Required for construction via |CreateForWebContents|:
explicit PasswordAccessoryController(content::WebContents* contents);
friend class content::WebContentsUserData<PasswordAccessoryController>;
// Constructor that allows to inject a mock or fake view.
PasswordAccessoryController(
content::WebContents* web_contents,
std::unique_ptr<PasswordAccessoryViewInterface> view,
CreateDialogFactory create_dialog_callback);
// Creates the view items based on the |origin_suggestions_| and sends them to
// the view. If |is_password_field| is false, password suggestions won't be
// interactive.
void SendViewItems(bool is_password_field);
// Contains the last set of credentials by origin.
std::map<url::Origin, std::vector<SuggestionElementData>> origin_suggestions_;
// The tab for which this class is scoped.
content::WebContents* web_contents_;
// Data for the generation element used to generate the password.
std::unique_ptr<GenerationElementData> generation_element_data_;
// Password manager driver for the target frame used for password generation.
base::WeakPtr<password_manager::PasswordManagerDriver> target_frame_driver_;
// Modal dialog view meant to display the generated password.
std::unique_ptr<PasswordGenerationDialogViewInterface> dialog_view_;
// Remembers whether the last focused field was a password field. That way,
// the reconstructed elements have the correct type.
bool last_focused_field_was_for_passwords_ = false;
// Hold the native instance of the view. Must be last declared and initialized
// member so the view can be created in the constructor with a fully set up
// controller instance.
std::unique_ptr<PasswordAccessoryViewInterface> view_;
// Creation callback for the modal dialog view meant to facilitate testing.
CreateDialogFactory create_dialog_factory_;
base::WeakPtrFactory<PasswordAccessoryController> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(PasswordAccessoryController);
};
#endif // CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_ACCESSORY_CONTROLLER_H_