| diff --git chrome/browser/renderer_context_menu/render_view_context_menu.cc chrome/browser/renderer_context_menu/render_view_context_menu.cc |
| index b4a12d129fa52..a8caaab873d3c 100644 |
| --- chrome/browser/renderer_context_menu/render_view_context_menu.cc |
| +++ chrome/browser/renderer_context_menu/render_view_context_menu.cc |
| @@ -345,6 +345,13 @@ base::OnceCallback<void(RenderViewContextMenu*)>* GetMenuShownCallback() { |
| return callback.get(); |
| } |
| |
| + |
| +RenderViewContextMenu::MenuCreatedCallback* GetMenuCreatedCallback() { |
| + static base::NoDestructor<RenderViewContextMenu::MenuCreatedCallback> |
| + callback; |
| + return callback.get(); |
| +} |
| + |
| enum class UmaEnumIdLookupType { |
| GeneralEnumId, |
| ContextSpecificEnumId, |
| @@ -594,6 +601,10 @@ int FindUMAEnumValueForCommand(int id, UmaEnumIdLookupType type) { |
| if (ContextMenuMatcher::IsExtensionsCustomCommandId(id)) |
| return 1; |
| |
| + // Match the MENU_ID_USER_FIRST to MENU_ID_USER_LAST range from cef_types.h. |
| + if (id >= 26500 && id <= 28500) |
| + return 1; |
| + |
| id = CollapseCommandsForUMA(id); |
| const auto& map = GetIdcToUmaMap(type); |
| auto it = map.find(id); |
| @@ -817,6 +828,14 @@ RenderViewContextMenu::RenderViewContextMenu( |
| pdf_ocr_submenu_model_ = std::make_unique<ui::SimpleMenuModel>(this); |
| #endif // BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) |
| |
| + auto* cb = GetMenuCreatedCallback(); |
| + if (!cb->is_null()) { |
| + first_observer_ = cb->Run(this); |
| + if (first_observer_) { |
| + observers_.AddObserver(first_observer_.get()); |
| + } |
| + } |
| + |
| observers_.AddObserver(&autofill_context_menu_manager_); |
| } |
| |
| @@ -1280,6 +1299,12 @@ void RenderViewContextMenu::InitMenu() { |
| autofill::PopupHidingReason::kContextMenuOpened); |
| } |
| } |
| + |
| + if (first_observer_) { |
| + // Do this last so that the observer can optionally modify previously |
| + // created items. |
| + first_observer_->InitMenu(params_); |
| + } |
| } |
| |
| Profile* RenderViewContextMenu::GetProfile() const { |
| @@ -3315,6 +3340,12 @@ void RenderViewContextMenu::RegisterExecutePluginActionCallbackForTesting( |
| execute_plugin_action_callback_ = std::move(cb); |
| } |
| |
| +// static |
| +void RenderViewContextMenu::RegisterMenuCreatedCallback( |
| + MenuCreatedCallback cb) { |
| + *GetMenuCreatedCallback() = cb; |
| +} |
| + |
| custom_handlers::ProtocolHandlerRegistry::ProtocolHandlerList |
| RenderViewContextMenu::GetHandlersForLinkUrl() { |
| custom_handlers::ProtocolHandlerRegistry::ProtocolHandlerList handlers = |
| diff --git chrome/browser/renderer_context_menu/render_view_context_menu.h chrome/browser/renderer_context_menu/render_view_context_menu.h |
| index 2d38d86a07d98..3f16e2bf696c1 100644 |
| --- chrome/browser/renderer_context_menu/render_view_context_menu.h |
| +++ chrome/browser/renderer_context_menu/render_view_context_menu.h |
| @@ -152,6 +152,12 @@ class RenderViewContextMenu |
| } |
| #endif |
| |
| + // Registers a callback that will be called each time a context menu is |
| + // created. |
| + using MenuCreatedCallback = base::RepeatingCallback< |
| + std::unique_ptr<RenderViewContextMenuObserver>(RenderViewContextMenu*)>; |
| + static void RegisterMenuCreatedCallback(MenuCreatedCallback cb); |
| + |
| protected: |
| Profile* GetProfile() const; |
| |
| @@ -441,6 +447,9 @@ class RenderViewContextMenu |
| // built. |
| bool is_protocol_submenu_valid_ = false; |
| |
| + // An observer returned via MenuCreatedCallback that will be called first. |
| + std::unique_ptr<RenderViewContextMenuObserver> first_observer_; |
| + |
| // An observer that handles spelling suggestions, "Add to dictionary", and |
| // "Use enhanced spell check" items. |
| std::unique_ptr<SpellingMenuObserver> spelling_suggestions_menu_observer_; |
| diff --git chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.cc chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.cc |
| index 18283c801689e..9838c25d6e584 100644 |
| --- chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.cc |
| +++ chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.cc |
| @@ -149,6 +149,9 @@ void RenderViewContextMenuViews::RunMenuAt(views::Widget* parent, |
| bool RenderViewContextMenuViews::GetAcceleratorForCommandId( |
| int command_id, |
| ui::Accelerator* accel) const { |
| + if (RenderViewContextMenu::GetAcceleratorForCommandId(command_id, accel)) |
| + return true; |
| + |
| // There are no formally defined accelerators we can query so we assume |
| // that Ctrl+C, Ctrl+V, Ctrl+X, Ctrl-A, etc do what they normally do. |
| switch (command_id) { |
| diff --git components/renderer_context_menu/render_view_context_menu_base.cc components/renderer_context_menu/render_view_context_menu_base.cc |
| index 965a283dea477..74c1ee8258485 100644 |
| --- components/renderer_context_menu/render_view_context_menu_base.cc |
| +++ components/renderer_context_menu/render_view_context_menu_base.cc |
| @@ -382,6 +382,17 @@ bool RenderViewContextMenuBase::IsCommandIdChecked(int id) const { |
| return false; |
| } |
| |
| +bool RenderViewContextMenuBase::GetAcceleratorForCommandId( |
| + int id, |
| + ui::Accelerator* accelerator) const { |
| + for (auto& observer : observers_) { |
| + if (observer.IsCommandIdSupported(id)) |
| + return observer.GetAccelerator(id, accelerator); |
| + } |
| + |
| + return false; |
| +} |
| + |
| void RenderViewContextMenuBase::ExecuteCommand(int id, int event_flags) { |
| command_executed_ = true; |
| RecordUsedItem(id); |
| diff --git components/renderer_context_menu/render_view_context_menu_base.h components/renderer_context_menu/render_view_context_menu_base.h |
| index b5995389e5107..26ef1e2ff42c7 100644 |
| --- components/renderer_context_menu/render_view_context_menu_base.h |
| +++ components/renderer_context_menu/render_view_context_menu_base.h |
| @@ -87,6 +87,9 @@ class RenderViewContextMenuBase : public ui::SimpleMenuModel::Delegate, |
| |
| const ui::SimpleMenuModel& menu_model() const { return menu_model_; } |
| const content::ContextMenuParams& params() const { return params_; } |
| + content::WebContents* source_web_contents() const { |
| + return source_web_contents_; |
| + } |
| |
| // Returns true if the specified command id is known and valid for |
| // this menu. If the command is known |enabled| is set to indicate |
| @@ -95,6 +98,9 @@ class RenderViewContextMenuBase : public ui::SimpleMenuModel::Delegate, |
| |
| // SimpleMenuModel::Delegate implementation. |
| bool IsCommandIdChecked(int command_id) const override; |
| + bool GetAcceleratorForCommandId( |
| + int command_id, |
| + ui::Accelerator* accelerator) const override; |
| void ExecuteCommand(int command_id, int event_flags) override; |
| void OnMenuWillShow(ui::SimpleMenuModel* source) override; |
| void MenuClosed(ui::SimpleMenuModel* source) override; |
| diff --git components/renderer_context_menu/render_view_context_menu_observer.cc components/renderer_context_menu/render_view_context_menu_observer.cc |
| index 9fdda1636003d..538bd05a41296 100644 |
| --- components/renderer_context_menu/render_view_context_menu_observer.cc |
| +++ components/renderer_context_menu/render_view_context_menu_observer.cc |
| @@ -15,3 +15,8 @@ bool RenderViewContextMenuObserver::IsCommandIdChecked(int command_id) { |
| bool RenderViewContextMenuObserver::IsCommandIdEnabled(int command_id) { |
| return false; |
| } |
| + |
| +bool RenderViewContextMenuObserver::GetAccelerator(int command_id, |
| + ui::Accelerator* accel) { |
| + return false; |
| +} |
| diff --git components/renderer_context_menu/render_view_context_menu_observer.h components/renderer_context_menu/render_view_context_menu_observer.h |
| index 0527c57abd51c..70bebcbb50461 100644 |
| --- components/renderer_context_menu/render_view_context_menu_observer.h |
| +++ components/renderer_context_menu/render_view_context_menu_observer.h |
| @@ -11,6 +11,10 @@ namespace content { |
| struct ContextMenuParams; |
| } |
| |
| +namespace ui { |
| +class Accelerator; |
| +} |
| + |
| // The interface used for implementing context-menu items. The following |
| // instruction describe how to implement a context-menu item with this |
| // interface. |
| @@ -100,6 +104,8 @@ class RenderViewContextMenuObserver { |
| virtual bool IsCommandIdChecked(int command_id); |
| virtual bool IsCommandIdEnabled(int command_id); |
| |
| + virtual bool GetAccelerator(int command_id, ui::Accelerator* accel); |
| + |
| // Called when a user selects the specified context-menu item. This is |
| // only called when the observer returns true for IsCommandIdSupported() |
| // for that |command_id|. |