blob: f79eeacbd6386e322469e12901169eaab9f1625d [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_CONTEXT_MENU_MANAGER_H_
#define CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_CONTEXT_MENU_MANAGER_H_
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/types/strong_alias.h"
#include "components/autofill/content/browser/content_autofill_driver.h"
#include "components/autofill/core/common/unique_ids.h"
#include "components/renderer_context_menu/render_view_context_menu_base.h"
#include "components/renderer_context_menu/render_view_context_menu_observer.h"
#include "content/public/browser/context_menu_params.h"
#include "ui/base/models/simple_menu_model.h"
namespace password_manager {
class ContentPasswordManagerDriver;
} // namespace password_manager
namespace autofill {
class AutofillField;
class AutofillPredictionImprovementsDelegate;
class PersonalDataManager;
// `AutofillContextMenuManager` is responsible for adding/executing Autofill
// related context menu items. `RenderViewContextMenu` is intended to own and
// control the lifetime of `AutofillContextMenuManager`.
// The options include:
// Provide Autofill feedback
// Fill in Form
class AutofillContextMenuManager : public RenderViewContextMenuObserver {
public:
// Represents command id used to denote a row in the context menu. The
// command ids are created when the items are added to the context menu during
// it's initialization.
using CommandId = base::StrongAlias<class CommandIdTag, int>;
AutofillContextMenuManager(PersonalDataManager* personal_data_manager,
RenderViewContextMenuBase* delegate,
ui::SimpleMenuModel* menu_model);
~AutofillContextMenuManager() override;
AutofillContextMenuManager(const AutofillContextMenuManager&) = delete;
AutofillContextMenuManager& operator=(const AutofillContextMenuManager&) =
delete;
// Adds items to the context menu.
// Note: This doesn't use `RenderViewContextMenuObserver::InitMenu()`, since
// Autofill context menu entries are conditioned on
// `ContextMenuContentType::ITEM_GROUP_AUTOFILL`.
void AppendItems();
// `RenderViewContextMenuObserver` overrides.
bool IsCommandIdSupported(int command_id) override;
bool IsCommandIdEnabled(int command_id) override;
void ExecuteCommand(int command_id) override;
// Setter for `params_` used for testing purposes.
void set_params_for_testing(content::ContextMenuParams params) {
params_ = params;
}
private:
// Conditionally adds the feedback manual fallback item if Autofill is
// available for the field.
void MaybeAddAutofillFeedbackItem();
// Conditionally adds the item to trigger filling with prediction
// improvements.
void MaybeAddAutofillPredictionImprovementsItem();
// Conditionally adds the address, payments and / or passwords Autofill manual
// fallbacks to the context menu model depending on whether there's data to
// suggest.
void MaybeAddAutofillManualFallbackItems();
// Checks if the plus address context menu entry can be shown for the
// currently focused field.
bool ShouldAddPlusAddressManualFallbackItem(
ContentAutofillDriver& autofill_driver);
// Returns if the item to trigger prediction improvements should be added.
bool ShouldAddPredictionImprovementsItem(
AutofillPredictionImprovementsDelegate* delegate,
const GURL& url);
// Checks if the manual fallback context menu entry can be shown for the
// currently focused field.
bool ShouldAddAddressManualFallbackItem(
ContentAutofillDriver& autofill_driver);
// Checks if the currently focused field is a password field and whether
// password filling is enabled.
bool ShouldAddPasswordsManualFallbackItem(
password_manager::ContentPasswordManagerDriver& password_manager_driver);
// Adds the passwords manual fallback context menu entries.
//
// Regardless of the state of the user, only one entry is displayed in the
// top-level context menu: "Passwords".
//
// If the user has passwords saved and cannot generate passwords, clicking on
// the "Passwords" entry behaves exactly like "Select password" (it will
// trigger password suggestions).
//
// In all the other cases, the "Passwords" entry doesn't do anything upon
// clicking, but hovering on it opens a sub-menu.
//
// In the sub-menu, if the user doesn't have passwords saved, the first entry
// is "No saved passwords". This entry is greyed out and doesn't do anything
// upon clicking. It is just informative. If the user has passwords saved,
// this entry is missing.
//
// The next entry in the sub-menu is either "Select password" (which triggers
// password suggestions) or "Import passwords" (which opens
// chrome://password-manager), depending on whether the user has passwords
// saved or not.
//
// If the user can also generate passwords for the current field, the final
// entry is "Suggest password...". Otherwise, this entry is missing.
void AddPasswordsManualFallbackItems(
password_manager::ContentPasswordManagerDriver& password_manager_driver);
void LogAddressManualFallbackContextMenuEntryShown(
ContentAutofillDriver& autofill_driver);
void LogPaymentsManualFallbackContextMenuEntryShown(
ContentAutofillDriver& autofill_driver);
// Out of all password entries, this method is only interested in the "select
// password" entry, because the rest of them don't trigger suggestions and are
// recorded by default separately (outside `AutofillContextMenuManager`).
void LogSelectPasswordManualFallbackContextMenuEntryShown(
password_manager::ContentPasswordManagerDriver& password_manager_drivern);
void LogAddressManualFallbackContextMenuEntryAccepted(
AutofillDriver& autofill_driver);
void LogPaymentsManualFallbackContextMenuEntryAccepted(
AutofillDriver& autofill_driver);
void LogSelectPasswordManualFallbackContextMenuEntryAccepted();
// Triggers the filling with prediction improvements flow.
void ExecutePredictionImprovementsCommand(
const LocalFrameToken& frame_token,
ContentAutofillDriver& autofill_driver);
// Triggers the feedback flow for Autofill command.
void ExecuteAutofillFeedbackCommand(const LocalFrameToken& frame_token,
AutofillManager& manager);
// Triggers Plus Address suggestions on the field that the context menu was
// opened on.
void ExecuteFallbackForPlusAddressesCommand(AutofillDriver& driver);
// Triggers Autofill payments suggestions on the field that the context menu
// was opened on.
void ExecuteFallbackForPaymentsCommand(AutofillDriver& driver);
// Triggers passwords suggestions on the field that the context menu was
// opened on.
void ExecuteFallbackForSelectPasswordCommand(AutofillDriver& driver);
// Triggers Autofill address suggestions on the field that the context menu
// was opened on.
void ExecuteFallbackForAddressesCommand(
ContentAutofillDriver& autofill_driver);
// Gets the `AutofillField` described by the `params_` from the
// `autofill_driver`'s manager.
AutofillField* GetAutofillField(AutofillDriver& autofill_driver) const;
// Dangling on linux-lacros-rel in:
// AutofillContextMenuManagerFeedbackUILacrosBrowserTest
// .CloseTabWhileUIIsOpenShouldNotCrash.
const raw_ptr<PersonalDataManager, DanglingUntriaged> personal_data_manager_;
const raw_ptr<ui::SimpleMenuModel> menu_model_;
const raw_ptr<RenderViewContextMenuBase> delegate_;
ui::SimpleMenuModel passwords_submenu_model_;
content::ContextMenuParams params_;
base::WeakPtrFactory<AutofillContextMenuManager> weak_ptr_factory_{this};
};
} // namespace autofill
#endif // CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_CONTEXT_MENU_MANAGER_H_