cef/patch/patches/chrome_browser_context_menu...

421 lines
18 KiB
Diff

diff --git chrome/browser/renderer_context_menu/render_view_context_menu.cc chrome/browser/renderer_context_menu/render_view_context_menu.cc
index de0d60b248414..7eae5ff63383a 100644
--- chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -359,6 +359,18 @@ base::OnceCallback<void(RenderViewContextMenu*)>* GetMenuShownCallback() {
return callback.get();
}
+RenderViewContextMenu::MenuCreatedCallback* GetMenuCreatedCallback() {
+ static base::NoDestructor<RenderViewContextMenu::MenuCreatedCallback>
+ callback;
+ return callback.get();
+}
+
+RenderViewContextMenu::MenuShowHandlerCallback* GetMenuShowHandlerCallback() {
+ static base::NoDestructor<RenderViewContextMenu::MenuShowHandlerCallback>
+ callback;
+ return callback.get();
+}
+
enum class UmaEnumIdLookupType {
GeneralEnumId,
ContextSpecificEnumId,
@@ -620,6 +632,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);
@@ -879,6 +895,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_);
}
@@ -1354,6 +1378,12 @@ void RenderViewContextMenu::InitMenu() {
autofill::SuggestionHidingReason::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 {
@@ -3590,6 +3620,26 @@ void RenderViewContextMenu::RegisterExecutePluginActionCallbackForTesting(
execute_plugin_action_callback_ = std::move(cb);
}
+// static
+void RenderViewContextMenu::RegisterMenuCreatedCallback(
+ MenuCreatedCallback cb) {
+ *GetMenuCreatedCallback() = cb;
+}
+
+// static
+void RenderViewContextMenu::RegisterMenuShowHandlerCallback(
+ MenuShowHandlerCallback cb) {
+ *GetMenuShowHandlerCallback() = cb;
+}
+
+bool RenderViewContextMenu::UseShowHandler() {
+ auto* cb = GetMenuShowHandlerCallback();
+ if (!cb->is_null() && cb->Run(this)) {
+ return true;
+ }
+ return false;
+}
+
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 d9f97fbdced53..60a01f70592a3 100644
--- chrome/browser/renderer_context_menu/render_view_context_menu.h
+++ chrome/browser/renderer_context_menu/render_view_context_menu.h
@@ -157,7 +157,21 @@ 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);
+
+ // Registers a callback that will be called each time before context menu is
+ // shown. The callback should return true if the show has handled.
+ using MenuShowHandlerCallback = base::RepeatingCallback<
+ bool(RenderViewContextMenu*)>;
+ static void RegisterMenuShowHandlerCallback(MenuShowHandlerCallback cb);
+
protected:
+ bool UseShowHandler();
+
Profile* GetProfile() const;
// This may return nullptr (e.g. for WebUI dialogs). Virtual to allow tests to
@@ -479,6 +493,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/cocoa/renderer_context_menu/render_view_context_menu_mac_cocoa.h chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_cocoa.h
index cb51224f9892c..b5a3946999d8f 100644
--- chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_cocoa.h
+++ chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_cocoa.h
@@ -29,6 +29,7 @@ class RenderViewContextMenuMacCocoa : public RenderViewContextMenuMac {
// RenderViewContextMenu:
void Show() override;
+ bool IsRunning() override;
private:
// RenderViewContextMenuViewsMac:
diff --git chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_cocoa.mm chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_cocoa.mm
index b130e9768c2d6..3e46b2fe18d0a 100644
--- chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_cocoa.mm
+++ chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_cocoa.mm
@@ -68,6 +68,10 @@ RenderViewContextMenuMacCocoa::~RenderViewContextMenuMacCocoa() {
}
void RenderViewContextMenuMacCocoa::Show() {
+ if (UseShowHandler()) {
+ return;
+ }
+
views::Widget* widget = views::Widget::GetTopLevelWidgetForNativeView(
source_web_contents_->GetNativeView());
@@ -93,6 +97,10 @@ void RenderViewContextMenuMacCocoa::Show() {
views::ElementTrackerViews::GetContextForWidget(widget));
}
+bool RenderViewContextMenuMacCocoa::IsRunning() {
+ return menu_controller_ && [menu_controller_ isMenuOpen];
+}
+
void RenderViewContextMenuMacCocoa::CancelToolkitMenu() {
[menu_controller_ cancel];
}
diff --git chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_remote_cocoa.h chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_remote_cocoa.h
index fb86992cee93f..fe674fe471cc4 100644
--- chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_remote_cocoa.h
+++ chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_remote_cocoa.h
@@ -27,6 +27,7 @@ class RenderViewContextMenuMacRemoteCocoa : public RenderViewContextMenuMac {
// RenderViewContextMenu:
void Show() override;
+ bool IsRunning() override;
private:
// RenderViewContextMenuViewsMac:
diff --git chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_remote_cocoa.mm chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_remote_cocoa.mm
index 9f6c5fd44f206..dc50bc909897f 100644
--- chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_remote_cocoa.mm
+++ chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_remote_cocoa.mm
@@ -42,6 +42,10 @@ void RenderViewContextMenuMacRemoteCocoa::Show() {
target_view_id_);
}
+bool RenderViewContextMenuMacRemoteCocoa::IsRunning() {
+ return runner_ && runner_->IsRunning();
+}
+
void RenderViewContextMenuMacRemoteCocoa::CancelToolkitMenu() {
runner_->Cancel();
}
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 c88a77a0b49e2..31b7224a36ae8 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) {
@@ -385,6 +388,10 @@ void RenderViewContextMenuViews::AppendPlatformEditableItems() {
}
void RenderViewContextMenuViews::Show() {
+ if (UseShowHandler()) {
+ return;
+ }
+
if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode))
return;
@@ -427,6 +434,11 @@ void RenderViewContextMenuViews::Show() {
}
}
+bool RenderViewContextMenuViews::IsRunning() {
+ return static_cast<ToolkitDelegateViews*>(toolkit_delegate())
+ ->IsMenuRunning();
+}
+
views::Widget* RenderViewContextMenuViews::GetTopLevelWidget() {
return views::Widget::GetTopLevelWidgetForNativeView(GetActiveNativeView());
}
diff --git chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.h chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.h
index 55ba34c417e4a..e92f668868e74 100644
--- chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.h
+++ chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.h
@@ -45,6 +45,7 @@ class RenderViewContextMenuViews : public RenderViewContextMenu {
// RenderViewContextMenuBase implementation.
void Show() override;
+ bool IsRunning() override;
protected:
RenderViewContextMenuViews(content::RenderFrameHost& render_frame_host,
diff --git chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.cc chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.cc
index eb855deeb6040..3ff97b28fa4c6 100644
--- chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.cc
+++ chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.cc
@@ -91,6 +91,10 @@ void ChromeWebContentsViewDelegateViews::ShowMenu(
context_menu_->Show();
}
+bool ChromeWebContentsViewDelegateViews::IsMenuRunning() {
+ return context_menu_ && context_menu_->IsRunning();
+}
+
void ChromeWebContentsViewDelegateViews::ShowContextMenu(
content::RenderFrameHost& render_frame_host,
const content::ContextMenuParams& params) {
diff --git chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.h chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.h
index 97c98c8738965..96c142806d7b2 100644
--- chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.h
+++ chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.h
@@ -55,6 +55,7 @@ class ChromeWebContentsViewDelegateViews
content::RenderFrameHost& render_frame_host,
const content::ContextMenuParams& params) override;
void ShowMenu(std::unique_ptr<RenderViewContextMenuBase> menu) override;
+ bool IsMenuRunning() override;
private:
// The context menu is reset every time we show it, but we keep a pointer to
diff --git chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views_mac.h chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views_mac.h
index 07e5b3613a2df..293282690bd5a 100644
--- chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views_mac.h
+++ chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views_mac.h
@@ -55,6 +55,7 @@ class ChromeWebContentsViewDelegateViewsMac
content::RenderFrameHost& render_frame_host,
const content::ContextMenuParams& params) override;
void ShowMenu(std::unique_ptr<RenderViewContextMenuBase> menu) override;
+ bool IsMenuRunning() override;
private:
content::RenderWidgetHostView* GetActiveRenderWidgetHostView() const;
diff --git chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views_mac.mm chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views_mac.mm
index 0e2cf71973741..e8d9c38b49b6c 100644
--- chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views_mac.mm
+++ chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views_mac.mm
@@ -131,6 +131,10 @@ void ChromeWebContentsViewDelegateViewsMac::ShowMenu(
context_menu_->Show();
}
+bool ChromeWebContentsViewDelegateViewsMac::IsMenuRunning() {
+ return context_menu_ && context_menu_->IsRunning();
+}
+
content::RenderWidgetHostView*
ChromeWebContentsViewDelegateViewsMac::GetActiveRenderWidgetHostView() const {
return web_contents_->GetTopLevelRenderWidgetHostView();
diff --git components/renderer_context_menu/context_menu_delegate.h components/renderer_context_menu/context_menu_delegate.h
index 042428f77f4ad..e4efd98ca45d5 100644
--- components/renderer_context_menu/context_menu_delegate.h
+++ components/renderer_context_menu/context_menu_delegate.h
@@ -45,6 +45,8 @@ class ContextMenuDelegate {
// Displays the context menu.
virtual void ShowMenu(std::unique_ptr<RenderViewContextMenuBase> menu) = 0;
+ virtual bool IsMenuRunning() = 0;
+
private:
raw_ptr<content::WebContents> web_contents_ = nullptr;
};
diff --git components/renderer_context_menu/render_view_context_menu_base.cc components/renderer_context_menu/render_view_context_menu_base.cc
index 8e45cecb17039..e40115e23ee82 100644
--- components/renderer_context_menu/render_view_context_menu_base.cc
+++ components/renderer_context_menu/render_view_context_menu_base.cc
@@ -374,6 +374,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 57b288bc885e6..9909899e3b5fe 100644
--- components/renderer_context_menu/render_view_context_menu_base.h
+++ components/renderer_context_menu/render_view_context_menu_base.h
@@ -85,8 +85,13 @@ class RenderViewContextMenuBase : public ui::SimpleMenuModel::Delegate,
// Programmatically closes the context menu.
void Cancel();
+ virtual bool IsRunning() = 0;
+
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 +100,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|.
diff --git components/renderer_context_menu/views/toolkit_delegate_views.cc components/renderer_context_menu/views/toolkit_delegate_views.cc
index 823f044316527..85439bf7ad2eb 100644
--- components/renderer_context_menu/views/toolkit_delegate_views.cc
+++ components/renderer_context_menu/views/toolkit_delegate_views.cc
@@ -30,6 +30,10 @@ void ToolkitDelegateViews::RunMenuAt(views::Widget* parent,
anchor_position, type);
}
+bool ToolkitDelegateViews::IsMenuRunning() const {
+ return menu_runner_ && menu_runner_->IsRunning();
+}
+
void ToolkitDelegateViews::Init(ui::SimpleMenuModel* menu_model) {
menu_adapter_ = std::make_unique<views::MenuModelAdapter>(menu_model);
std::unique_ptr<views::MenuItemView> menu_view = menu_adapter_->CreateMenu();
diff --git components/renderer_context_menu/views/toolkit_delegate_views.h components/renderer_context_menu/views/toolkit_delegate_views.h
index eacdc12813204..9084effdaa121 100644
--- components/renderer_context_menu/views/toolkit_delegate_views.h
+++ components/renderer_context_menu/views/toolkit_delegate_views.h
@@ -39,6 +39,7 @@ class ToolkitDelegateViews : public RenderViewContextMenuBase::ToolkitDelegate {
const gfx::Point& point,
ui::MenuSourceType type);
views::MenuItemView* menu_view() { return menu_view_; }
+ bool IsMenuRunning() const;
protected:
// ToolkitDelegate: