• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1diff --git chrome/browser/renderer_context_menu/render_view_context_menu.cc chrome/browser/renderer_context_menu/render_view_context_menu.cc
2index 13ad2a7529bb..0b003c26815e 100644
3--- chrome/browser/renderer_context_menu/render_view_context_menu.cc
4+++ chrome/browser/renderer_context_menu/render_view_context_menu.cc
5@@ -254,6 +254,13 @@ base::OnceCallback<void(RenderViewContextMenu*)>* GetMenuShownCallback() {
6   return callback.get();
7 }
8
9+
10+RenderViewContextMenu::MenuCreatedCallback* GetMenuCreatedCallback() {
11+  static base::NoDestructor<RenderViewContextMenu::MenuCreatedCallback>
12+      callback;
13+  return callback.get();
14+}
15+
16 enum class UmaEnumIdLookupType {
17   GeneralEnumId,
18   ContextSpecificEnumId,
19@@ -463,6 +470,10 @@ int FindUMAEnumValueForCommand(int id, UmaEnumIdLookupType type) {
20   if (ContextMenuMatcher::IsExtensionsCustomCommandId(id))
21     return 1;
22
23+  // Match the MENU_ID_USER_FIRST to MENU_ID_USER_LAST range from cef_types.h.
24+  if (id >= 26500 && id <= 28500)
25+    return 1;
26+
27   id = CollapseCommandsForUMA(id);
28   const auto& map = GetIdcToUmaMap(type);
29   auto it = map.find(id);
30@@ -618,6 +629,14 @@ RenderViewContextMenu::RenderViewContextMenu(
31   }
32   set_content_type(
33       ContextMenuContentTypeFactory::Create(source_web_contents_, params));
34+
35+  auto* cb = GetMenuCreatedCallback();
36+  if (!cb->is_null()) {
37+    first_observer_ = cb->Run(this);
38+    if (first_observer_) {
39+      observers_.AddObserver(first_observer_.get());
40+    }
41+  }
42 }
43
44 RenderViewContextMenu::~RenderViewContextMenu() = default;
45@@ -973,6 +992,12 @@ void RenderViewContextMenu::InitMenu() {
46   // menu, meaning that each menu item added/removed in this function will cause
47   // it to visibly jump on the screen (see b/173569669).
48   AppendQuickAnswersItems();
49+
50+  if (first_observer_) {
51+    // Do this last so that the observer can optionally modify previously
52+    // created items.
53+    first_observer_->InitMenu(params_);
54+  }
55 }
56
57 Profile* RenderViewContextMenu::GetProfile() const {
58@@ -2594,6 +2619,12 @@ void RenderViewContextMenu::RegisterMenuShownCallbackForTesting(
59   *GetMenuShownCallback() = std::move(cb);
60 }
61
62+// static
63+void RenderViewContextMenu::RegisterMenuCreatedCallback(
64+    MenuCreatedCallback cb) {
65+  *GetMenuCreatedCallback() = cb;
66+}
67+
68 ProtocolHandlerRegistry::ProtocolHandlerList
69 RenderViewContextMenu::GetHandlersForLinkUrl() {
70   ProtocolHandlerRegistry::ProtocolHandlerList handlers =
71diff --git chrome/browser/renderer_context_menu/render_view_context_menu.h chrome/browser/renderer_context_menu/render_view_context_menu.h
72index 5178db60ba64..845461049e54 100644
73--- chrome/browser/renderer_context_menu/render_view_context_menu.h
74+++ chrome/browser/renderer_context_menu/render_view_context_menu.h
75@@ -91,6 +91,12 @@ class RenderViewContextMenu : public RenderViewContextMenuBase {
76   static void RegisterMenuShownCallbackForTesting(
77       base::OnceCallback<void(RenderViewContextMenu*)> cb);
78
79+  // Registers a callback that will be called each time a context menu is
80+  // created.
81+  using MenuCreatedCallback = base::RepeatingCallback<
82+      std::unique_ptr<RenderViewContextMenuObserver>(RenderViewContextMenu*)>;
83+  static void RegisterMenuCreatedCallback(MenuCreatedCallback cb);
84+
85  protected:
86   Profile* GetProfile() const;
87
88@@ -265,6 +271,9 @@ class RenderViewContextMenu : public RenderViewContextMenuBase {
89   ui::SimpleMenuModel protocol_handler_submenu_model_;
90   ProtocolHandlerRegistry* protocol_handler_registry_;
91
92+  // An observer returned via MenuCreatedCallback that will be called first.
93+  std::unique_ptr<RenderViewContextMenuObserver> first_observer_;
94+
95   // An observer that handles spelling suggestions, "Add to dictionary", and
96   // "Use enhanced spell check" items.
97   std::unique_ptr<SpellingMenuObserver> spelling_suggestions_menu_observer_;
98diff --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
99index feec153dcc14..0959c1020bad 100644
100--- chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.cc
101+++ chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.cc
102@@ -136,6 +136,9 @@ void RenderViewContextMenuViews::RunMenuAt(views::Widget* parent,
103 bool RenderViewContextMenuViews::GetAcceleratorForCommandId(
104     int command_id,
105     ui::Accelerator* accel) const {
106+  if (RenderViewContextMenu::GetAcceleratorForCommandId(command_id, accel))
107+    return true;
108+
109   // There are no formally defined accelerators we can query so we assume
110   // that Ctrl+C, Ctrl+V, Ctrl+X, Ctrl-A, etc do what they normally do.
111   switch (command_id) {
112diff --git components/renderer_context_menu/render_view_context_menu_base.cc components/renderer_context_menu/render_view_context_menu_base.cc
113index 62100403d27f..54182e7d97e3 100644
114--- components/renderer_context_menu/render_view_context_menu_base.cc
115+++ components/renderer_context_menu/render_view_context_menu_base.cc
116@@ -375,6 +375,17 @@ bool RenderViewContextMenuBase::IsCommandIdChecked(int id) const {
117   return false;
118 }
119
120+bool RenderViewContextMenuBase::GetAcceleratorForCommandId(
121+    int id,
122+    ui::Accelerator* accelerator) const {
123+  for (auto& observer : observers_) {
124+    if (observer.IsCommandIdSupported(id))
125+      return observer.GetAccelerator(id, accelerator);
126+  }
127+
128+  return false;
129+}
130+
131 void RenderViewContextMenuBase::ExecuteCommand(int id, int event_flags) {
132   command_executed_ = true;
133   RecordUsedItem(id);
134diff --git components/renderer_context_menu/render_view_context_menu_base.h components/renderer_context_menu/render_view_context_menu_base.h
135index 52002b190fde..ce3277e9f935 100644
136--- components/renderer_context_menu/render_view_context_menu_base.h
137+++ components/renderer_context_menu/render_view_context_menu_base.h
138@@ -81,6 +81,9 @@ class RenderViewContextMenuBase : public ui::SimpleMenuModel::Delegate,
139
140   const ui::SimpleMenuModel& menu_model() const { return menu_model_; }
141   const content::ContextMenuParams& params() const { return params_; }
142+  content::WebContents* source_web_contents() const {
143+    return source_web_contents_;
144+  }
145
146   // Returns true if the specified command id is known and valid for
147   // this menu. If the command is known |enabled| is set to indicate
148@@ -89,6 +92,9 @@ class RenderViewContextMenuBase : public ui::SimpleMenuModel::Delegate,
149
150   // SimpleMenuModel::Delegate implementation.
151   bool IsCommandIdChecked(int command_id) const override;
152+  bool GetAcceleratorForCommandId(
153+      int command_id,
154+      ui::Accelerator* accelerator) const override;
155   void ExecuteCommand(int command_id, int event_flags) override;
156   void OnMenuWillShow(ui::SimpleMenuModel* source) override;
157   void MenuClosed(ui::SimpleMenuModel* source) override;
158@@ -119,6 +125,9 @@ class RenderViewContextMenuBase : public ui::SimpleMenuModel::Delegate,
159   content::WebContents* GetWebContents() const override;
160   content::BrowserContext* GetBrowserContext() const override;
161
162+  // May return nullptr if the frame was deleted while the menu was open.
163+  content::RenderFrameHost* GetRenderFrameHost() const;
164+
165  protected:
166   friend class RenderViewContextMenuTest;
167   friend class RenderViewContextMenuPrefsTest;
168@@ -156,9 +165,6 @@ class RenderViewContextMenuBase : public ui::SimpleMenuModel::Delegate,
169   // TODO(oshima): Remove this.
170   virtual void AppendPlatformEditableItems() {}
171
172-  // May return nullptr if the frame was deleted while the menu was open.
173-  content::RenderFrameHost* GetRenderFrameHost() const;
174-
175   bool IsCustomItemChecked(int id) const;
176   bool IsCustomItemEnabled(int id) const;
177
178diff --git components/renderer_context_menu/render_view_context_menu_observer.cc components/renderer_context_menu/render_view_context_menu_observer.cc
179index 2e2d05f91c64..85b256b2be9b 100644
180--- components/renderer_context_menu/render_view_context_menu_observer.cc
181+++ components/renderer_context_menu/render_view_context_menu_observer.cc
182@@ -15,3 +15,8 @@ bool RenderViewContextMenuObserver::IsCommandIdChecked(int command_id) {
183 bool RenderViewContextMenuObserver::IsCommandIdEnabled(int command_id) {
184   return false;
185 }
186+
187+bool RenderViewContextMenuObserver::GetAccelerator(int command_id,
188+                                                   ui::Accelerator* accel) {
189+  return false;
190+}
191diff --git components/renderer_context_menu/render_view_context_menu_observer.h components/renderer_context_menu/render_view_context_menu_observer.h
192index b360a8eb4e82..6f9023a62904 100644
193--- components/renderer_context_menu/render_view_context_menu_observer.h
194+++ components/renderer_context_menu/render_view_context_menu_observer.h
195@@ -11,6 +11,10 @@ namespace content {
196 struct ContextMenuParams;
197 }
198
199+namespace ui {
200+class Accelerator;
201+}
202+
203 // The interface used for implementing context-menu items. The following
204 // instruction describe how to implement a context-menu item with this
205 // interface.
206@@ -100,6 +104,8 @@ class RenderViewContextMenuObserver {
207   virtual bool IsCommandIdChecked(int command_id);
208   virtual bool IsCommandIdEnabled(int command_id);
209
210+  virtual bool GetAccelerator(int command_id, ui::Accelerator* accel);
211+
212   // Called when a user selects the specified context-menu item. This is
213   // only called when the observer returns true for IsCommandIdSupported()
214   // for that |command_id|.
215