chrome: Add ability to hide toolbar and app menu contents (see issue #3280)

This change adds new CefCommandHandler callbacks for optionally hiding
specific Chrome toolbar icons, buttons and app menu items.

To test: Run `cefclient --enable-chrome-runtime --filter-chrome-commands`.
Most icons, buttons and app/context menu items will be hidden.
This commit is contained in:
Marshall Greenblatt 2023-03-06 18:21:57 -05:00
parent 798bc0e9cc
commit f8b9812cb4
15 changed files with 866 additions and 77 deletions

View File

@ -33,7 +33,7 @@
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=46817ef557307a55a9b7138134c4f5c32562f2d7$
// $hash=0cbb756a64d2aca1075480b5188b36cae533864d$
//
#ifndef CEF_INCLUDE_CAPI_CEF_COMMAND_HANDLER_CAPI_H_
@ -71,6 +71,46 @@ typedef struct _cef_command_handler_t {
struct _cef_browser_t* browser,
int command_id,
cef_window_open_disposition_t disposition);
///
/// Called to check if a Chrome app menu item should be visible. Values for
/// |command_id| can be found in the cef_command_ids.h file. Only called for
/// menu items that would be visible by default. Only used with the Chrome
/// runtime.
///
int(CEF_CALLBACK* is_chrome_app_menu_item_visible)(
struct _cef_command_handler_t* self,
struct _cef_browser_t* browser,
int command_id);
///
/// Called to check if a Chrome app menu item should be enabled. Values for
/// |command_id| can be found in the cef_command_ids.h file. Only called for
/// menu items that would be enabled by default. Only used with the Chrome
/// runtime.
///
int(CEF_CALLBACK* is_chrome_app_menu_item_enabled)(
struct _cef_command_handler_t* self,
struct _cef_browser_t* browser,
int command_id);
///
/// Called during browser creation to check if a Chrome page action icon
/// should be visible. Only called for icons that would be visible by default.
/// Only used with the Chrome runtime.
///
int(CEF_CALLBACK* is_chrome_page_action_icon_visible)(
struct _cef_command_handler_t* self,
cef_chrome_page_action_icon_type_t icon_type);
///
/// Called during browser creation to check if a Chrome toolbar button should
/// be visible. Only called for buttons that would be visible by default. Only
/// used with the Chrome runtime.
///
int(CEF_CALLBACK* is_chrome_toolbar_button_visible)(
struct _cef_command_handler_t* self,
cef_chrome_toolbar_button_type_t button_type);
} cef_command_handler_t;
#ifdef __cplusplus

View File

@ -42,13 +42,13 @@
// way that may cause binary incompatibility with other builds. The universal
// hash value will change if any platform is affected whereas the platform hash
// values will change only if that particular platform is affected.
#define CEF_API_HASH_UNIVERSAL "a41a1ba176d9a8cd7d8f15bc0d0c9c88f3c5a3a3"
#define CEF_API_HASH_UNIVERSAL "149694d7fffd78ef85e127229819c69e2189ef32"
#if defined(OS_WIN)
#define CEF_API_HASH_PLATFORM "b47745d2e8919e00416c26eb078fdde5ee546b9d"
#define CEF_API_HASH_PLATFORM "6f31babeb3f7d2723af55fbd32868284694e4015"
#elif defined(OS_MAC)
#define CEF_API_HASH_PLATFORM "d04c2a5ab471493c185eb7c7aa894bc4a79d5a7c"
#define CEF_API_HASH_PLATFORM "ff1bc603897dca8e100a1d4f9391ef4e49db02df"
#elif defined(OS_LINUX)
#define CEF_API_HASH_PLATFORM "d7d4cbffa4a798fea97e7b9f3610b5cb803d949e"
#define CEF_API_HASH_PLATFORM "7f1ef8d0456bdcaff80c4e15a9806c603f204455"
#endif
#ifdef __cplusplus

View File

@ -63,6 +63,52 @@ class CefCommandHandler : public virtual CefBaseRefCounted {
cef_window_open_disposition_t disposition) {
return false;
}
///
/// Called to check if a Chrome app menu item should be visible. Values for
/// |command_id| can be found in the cef_command_ids.h file. Only called for
/// menu items that would be visible by default. Only used with the Chrome
/// runtime.
///
/*--cef()--*/
virtual bool IsChromeAppMenuItemVisible(CefRefPtr<CefBrowser> browser,
int command_id) {
return true;
}
///
/// Called to check if a Chrome app menu item should be enabled. Values for
/// |command_id| can be found in the cef_command_ids.h file. Only called for
/// menu items that would be enabled by default. Only used with the Chrome
/// runtime.
///
/*--cef()--*/
virtual bool IsChromeAppMenuItemEnabled(CefRefPtr<CefBrowser> browser,
int command_id) {
return true;
}
///
/// Called during browser creation to check if a Chrome page action icon
/// should be visible. Only called for icons that would be visible by default.
/// Only used with the Chrome runtime.
///
/*--cef(optional_param=browser)--*/
virtual bool IsChromePageActionIconVisible(
cef_chrome_page_action_icon_type_t icon_type) {
return true;
}
///
/// Called during browser creation to check if a Chrome toolbar button
/// should be visible. Only called for buttons that would be visible by
/// default. Only used with the Chrome runtime.
///
/*--cef(optional_param=browser)--*/
virtual bool IsChromeToolbarButtonVisible(
cef_chrome_toolbar_button_type_t button_type) {
return true;
}
};
#endif // CEF_INCLUDE_CEF_COMMAND_HANDLER_H_

View File

@ -3251,7 +3251,7 @@ typedef enum {
} cef_text_field_commands_t;
///
/// Supported Chrome toolbar types.
/// Chrome toolbar types.
///
typedef enum {
CEF_CTT_NONE = 1,
@ -3259,6 +3259,51 @@ typedef enum {
CEF_CTT_LOCATION,
} cef_chrome_toolbar_type_t;
///
/// Chrome page action icon types. Should be kept in sync with Chromium's
/// PageActionIconType type.
///
typedef enum {
CEF_CPAIT_BOOKMARK_STAR = 0,
CEF_CPAIT_CLICK_TO_CALL,
CEF_CPAIT_COOKIE_CONTROLS,
CEF_CPAIT_FILE_SYSTEM_ACCESS,
CEF_CPAIT_FIND,
CEF_CPAIT_HIGH_EFFICIENCY,
CEF_CPAIT_INTENT_PICKER,
CEF_CPAIT_LOCAL_CARD_MIGRATION,
CEF_CPAIT_MANAGE_PASSWORDS,
CEF_CPAIT_PAYMENTS_OFFER_NOTIFICATION,
CEF_CPAIT_PRICE_TRACKING,
CEF_CPAIT_PWA_INSTALL,
CEF_CPAIT_QR_CODE_GENERATOR,
CEF_CPAIT_READER_MODE,
CEF_CPAIT_SAVE_AUTOFILL_ADDRESS,
CEF_CPAIT_SAVE_CARD,
CEF_CPAIT_SEND_TAB_TO_SELF,
CEF_CPAIT_SHARING_HUB,
CEF_CPAIT_SIDE_SEARCH,
CEF_CPAIT_SMS_REMOTE_FETCHER,
CEF_CPAIT_TRANSLATE,
CEF_CPAIT_VIRTUAL_CARD_ENROLL,
CEF_CPAIT_VIRTUAL_CARD_MANUAL_FALLBACK,
CEF_CPAIT_ZOOM,
CEF_CPAIT_SAVE_IBAN,
CEF_CPAIT_MAX_VALUE = CEF_CPAIT_SAVE_IBAN,
} cef_chrome_page_action_icon_type_t;
///
/// Chrome toolbar button types. Should be kept in sync with CEF's internal
/// ToolbarButtonType type.
///
typedef enum {
CEF_CTBT_CAST = 0,
CEF_CTBT_DOWNLOAD,
CEF_CTBT_SEND_TAB_TO_SELF,
CEF_CTBT_SIDE_PANEL,
CEF_CTBT_MAX_VALUE = CEF_CTBT_SIDE_PANEL,
} cef_chrome_toolbar_button_type_t;
///
/// Docking modes supported by CefWindow::AddOverlay.
///

View File

@ -9,6 +9,7 @@
#include <memory>
#include "base/memory/scoped_refptr.h"
#include "chrome/browser/ui/page_action/page_action_icon_type.h"
#include "content/public/browser/web_contents_delegate.h"
#include "ui/base/window_open_disposition.h"
@ -65,6 +66,32 @@ class BrowserDelegate : public content::WebContentsDelegate {
return false;
}
// Return true if the app menu item should be visible. ID values come from
// chrome/app/chrome_command_ids.h.
virtual bool IsAppMenuItemVisible(int command_id) { return true; }
// Return true if the app menu item should be enabled. ID values come from
// chrome/app/chrome_command_ids.h.
virtual bool IsAppMenuItemEnabled(int command_id) { return true; }
// Return true if the page action icon should be visible.
virtual bool IsPageActionIconVisible(PageActionIconType icon_type) {
return true;
}
enum class ToolbarButtonType {
kCast = 0,
kDownload,
kSendTabToSelf,
kSidePanel,
kMaxValue = kSidePanel,
};
// Return true if the toolbar button should be visible.
virtual bool IsToolbarButtonVisible(ToolbarButtonType button_type) {
return true;
}
// Same as RequestMediaAccessPermission but returning |callback| if the
// request is unhandled.
[[nodiscard]] virtual content::MediaResponseCallback

View File

@ -122,6 +122,60 @@ bool ChromeBrowserDelegate::HandleCommand(int command_id,
return false;
}
bool ChromeBrowserDelegate::IsAppMenuItemVisible(int command_id) {
if (auto browser = ChromeBrowserHostImpl::GetBrowserForBrowser(browser_)) {
if (auto client = browser->GetClient()) {
if (auto handler = client->GetCommandHandler()) {
return handler->IsChromeAppMenuItemVisible(browser.get(), command_id);
}
}
}
return true;
}
bool ChromeBrowserDelegate::IsAppMenuItemEnabled(int command_id) {
if (auto browser = ChromeBrowserHostImpl::GetBrowserForBrowser(browser_)) {
if (auto client = browser->GetClient()) {
if (auto handler = client->GetCommandHandler()) {
return handler->IsChromeAppMenuItemEnabled(browser.get(), command_id);
}
}
}
return true;
}
bool ChromeBrowserDelegate::IsPageActionIconVisible(
PageActionIconType icon_type) {
// Verify that our enum matches Chromium's values.
static_assert(static_cast<int>(CEF_CPAIT_MAX_VALUE) ==
static_cast<int>(PageActionIconType::kMaxValue),
"enum mismatch");
if (auto client = create_params_.client) {
if (auto handler = client->GetCommandHandler()) {
return handler->IsChromePageActionIconVisible(
static_cast<cef_chrome_page_action_icon_type_t>(icon_type));
}
}
return true;
}
bool ChromeBrowserDelegate::IsToolbarButtonVisible(
ToolbarButtonType button_type) {
// Verify that our enum matches BrowserDelegate's values.
static_assert(static_cast<int>(CEF_CTBT_MAX_VALUE) ==
static_cast<int>(ToolbarButtonType::kMaxValue),
"enum mismatch");
if (auto client = create_params_.client) {
if (auto handler = client->GetCommandHandler()) {
return handler->IsChromeToolbarButtonVisible(
static_cast<cef_chrome_toolbar_button_type_t>(button_type));
}
}
return true;
}
content::MediaResponseCallback
ChromeBrowserDelegate::RequestMediaAccessPermissionEx(
content::WebContents* web_contents,

View File

@ -56,6 +56,10 @@ class ChromeBrowserDelegate : public cef::BrowserDelegate {
bool ShowStatusBubble(bool show_by_default) override;
bool HandleCommand(int command_id,
WindowOpenDisposition disposition) override;
bool IsAppMenuItemVisible(int command_id) override;
bool IsAppMenuItemEnabled(int command_id) override;
bool IsPageActionIconVisible(PageActionIconType icon_type) override;
bool IsToolbarButtonVisible(ToolbarButtonType button_type) override;
[[nodiscard]] content::MediaResponseCallback RequestMediaAccessPermissionEx(
content::WebContents* web_contents,
const content::MediaStreamRequest& request,

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=bf815bb565ccf2570c6f6b881009fe7df20805f0$
// $hash=7b58140cd5e363a79adf4e420ceae009a7d10811$
//
#include "libcef_dll/cpptoc/command_handler_cpptoc.h"
@ -47,12 +47,114 @@ command_handler_on_chrome_command(struct _cef_command_handler_t* self,
return _retval;
}
int CEF_CALLBACK command_handler_is_chrome_app_menu_item_visible(
struct _cef_command_handler_t* self,
cef_browser_t* browser,
int command_id) {
shutdown_checker::AssertNotShutdown();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self) {
return 0;
}
// Verify param: browser; type: refptr_diff
DCHECK(browser);
if (!browser) {
return 0;
}
// Execute
bool _retval = CefCommandHandlerCppToC::Get(self)->IsChromeAppMenuItemVisible(
CefBrowserCToCpp::Wrap(browser), command_id);
// Return type: bool
return _retval;
}
int CEF_CALLBACK command_handler_is_chrome_app_menu_item_enabled(
struct _cef_command_handler_t* self,
cef_browser_t* browser,
int command_id) {
shutdown_checker::AssertNotShutdown();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self) {
return 0;
}
// Verify param: browser; type: refptr_diff
DCHECK(browser);
if (!browser) {
return 0;
}
// Execute
bool _retval = CefCommandHandlerCppToC::Get(self)->IsChromeAppMenuItemEnabled(
CefBrowserCToCpp::Wrap(browser), command_id);
// Return type: bool
return _retval;
}
int CEF_CALLBACK command_handler_is_chrome_page_action_icon_visible(
struct _cef_command_handler_t* self,
cef_chrome_page_action_icon_type_t icon_type) {
shutdown_checker::AssertNotShutdown();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self) {
return 0;
}
// Execute
bool _retval =
CefCommandHandlerCppToC::Get(self)->IsChromePageActionIconVisible(
icon_type);
// Return type: bool
return _retval;
}
int CEF_CALLBACK command_handler_is_chrome_toolbar_button_visible(
struct _cef_command_handler_t* self,
cef_chrome_toolbar_button_type_t button_type) {
shutdown_checker::AssertNotShutdown();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self) {
return 0;
}
// Execute
bool _retval =
CefCommandHandlerCppToC::Get(self)->IsChromeToolbarButtonVisible(
button_type);
// Return type: bool
return _retval;
}
} // namespace
// CONSTRUCTOR - Do not edit by hand.
CefCommandHandlerCppToC::CefCommandHandlerCppToC() {
GetStruct()->on_chrome_command = command_handler_on_chrome_command;
GetStruct()->is_chrome_app_menu_item_visible =
command_handler_is_chrome_app_menu_item_visible;
GetStruct()->is_chrome_app_menu_item_enabled =
command_handler_is_chrome_app_menu_item_enabled;
GetStruct()->is_chrome_page_action_icon_visible =
command_handler_is_chrome_page_action_icon_visible;
GetStruct()->is_chrome_toolbar_button_visible =
command_handler_is_chrome_toolbar_button_visible;
}
// DESTRUCTOR - Do not edit by hand.

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=af3697f4c41762086c8edff7f63a794e8bf95b25$
// $hash=f374fda38406905546bc5601c01764a9b437a7d0$
//
#include "libcef_dll/ctocpp/command_handler_ctocpp.h"
@ -46,6 +46,98 @@ bool CefCommandHandlerCToCpp::OnChromeCommand(
return _retval ? true : false;
}
NO_SANITIZE("cfi-icall")
bool CefCommandHandlerCToCpp::IsChromeAppMenuItemVisible(
CefRefPtr<CefBrowser> browser,
int command_id) {
shutdown_checker::AssertNotShutdown();
cef_command_handler_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, is_chrome_app_menu_item_visible)) {
return false;
}
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: browser; type: refptr_diff
DCHECK(browser.get());
if (!browser.get()) {
return false;
}
// Execute
int _retval = _struct->is_chrome_app_menu_item_visible(
_struct, CefBrowserCppToC::Wrap(browser), command_id);
// Return type: bool
return _retval ? true : false;
}
NO_SANITIZE("cfi-icall")
bool CefCommandHandlerCToCpp::IsChromeAppMenuItemEnabled(
CefRefPtr<CefBrowser> browser,
int command_id) {
shutdown_checker::AssertNotShutdown();
cef_command_handler_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, is_chrome_app_menu_item_enabled)) {
return false;
}
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: browser; type: refptr_diff
DCHECK(browser.get());
if (!browser.get()) {
return false;
}
// Execute
int _retval = _struct->is_chrome_app_menu_item_enabled(
_struct, CefBrowserCppToC::Wrap(browser), command_id);
// Return type: bool
return _retval ? true : false;
}
NO_SANITIZE("cfi-icall")
bool CefCommandHandlerCToCpp::IsChromePageActionIconVisible(
cef_chrome_page_action_icon_type_t icon_type) {
shutdown_checker::AssertNotShutdown();
cef_command_handler_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, is_chrome_page_action_icon_visible)) {
return false;
}
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
int _retval = _struct->is_chrome_page_action_icon_visible(_struct, icon_type);
// Return type: bool
return _retval ? true : false;
}
NO_SANITIZE("cfi-icall")
bool CefCommandHandlerCToCpp::IsChromeToolbarButtonVisible(
cef_chrome_toolbar_button_type_t button_type) {
shutdown_checker::AssertNotShutdown();
cef_command_handler_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, is_chrome_toolbar_button_visible)) {
return false;
}
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
int _retval = _struct->is_chrome_toolbar_button_visible(_struct, button_type);
// Return type: bool
return _retval ? true : false;
}
// CONSTRUCTOR - Do not edit by hand.
CefCommandHandlerCToCpp::CefCommandHandlerCToCpp() {}

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=1def18706fb8efd9d28a718b505905d366a0d057$
// $hash=ad0096887a1662a2cc3804248365e56fc20d6eaa$
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_COMMAND_HANDLER_CTOCPP_H_
@ -38,6 +38,14 @@ class CefCommandHandlerCToCpp
bool OnChromeCommand(CefRefPtr<CefBrowser> browser,
int command_id,
cef_window_open_disposition_t disposition) override;
bool IsChromeAppMenuItemVisible(CefRefPtr<CefBrowser> browser,
int command_id) override;
bool IsChromeAppMenuItemEnabled(CefRefPtr<CefBrowser> browser,
int command_id) override;
bool IsChromePageActionIconVisible(
cef_chrome_page_action_icon_type_t icon_type) override;
bool IsChromeToolbarButtonVisible(
cef_chrome_toolbar_button_type_t button_type) override;
};
#endif // CEF_LIBCEF_DLL_CTOCPP_COMMAND_HANDLER_CTOCPP_H_

View File

@ -40,6 +40,182 @@ index f91c359d9792a..9fe7a7faf33bc 100644
}
bool BrowserCommandController::IsWebAppOrCustomTab() const {
diff --git chrome/browser/ui/toolbar/app_menu_model.cc chrome/browser/ui/toolbar/app_menu_model.cc
index 655ce2353f106..e9dd7ed68b9c5 100644
--- chrome/browser/ui/toolbar/app_menu_model.cc
+++ chrome/browser/ui/toolbar/app_menu_model.cc
@@ -151,6 +151,57 @@ absl::optional<std::u16string> GetInstallPWAAppMenuItemName(Browser* browser) {
ui::EscapeMenuLabelAmpersands(app_name));
}
+#if BUILDFLAG(ENABLE_CEF)
+using IsVisibleCallback = base::RepeatingCallback<bool(int)>;
+
+void FilterMenuModel(ui::SimpleMenuModel* model,
+ const IsVisibleCallback& is_visible) {
+ absl::optional<size_t> last_separator;
+ size_t visible_ct = 0;
+ for (size_t i = 0; i < model->GetItemCount(); ++i) {
+ const auto type = model->GetTypeAt(i);
+ if (type == ui::MenuModel::TYPE_SEPARATOR) {
+ if (last_separator) {
+ // Remove multiple separators in a row. Prefer to remove a NORMAL
+ // separator if possible (as compared to zoom/edit controls which use
+ // UPPER/LOWER separators).
+ if (model->GetSeparatorTypeAt(*last_separator) ==
+ ui::NORMAL_SEPARATOR) {
+ model->RemoveItemAt(*last_separator);
+ i--;
+ last_separator = i;
+ } else {
+ model->RemoveItemAt(i);
+ i--;
+ }
+ } else if (visible_ct == 0) {
+ // Remove leading separator.
+ model->RemoveItemAt(i);
+ i--;
+ } else {
+ last_separator = i;
+ }
+ visible_ct = 0;
+ } else if (is_visible.Run(model->GetCommandIdAt(i))) {
+ last_separator = absl::nullopt;
+ visible_ct++;
+
+ if (type == ui::MenuModel::TYPE_SUBMENU) {
+ // Filter sub-menu.
+ auto sub_model =
+ static_cast<ui::SimpleMenuModel*>(model->GetSubmenuModelAt(i));
+ FilterMenuModel(sub_model, is_visible);
+ }
+ }
+ }
+
+ if (last_separator) {
+ // Remove trailing separator.
+ model->RemoveItemAt(*last_separator);
+ }
+}
+#endif // BUILDFLAG(ENABLE_CEF)
+
} // namespace
////////////////////////////////////////////////////////////////////////////////
@@ -756,7 +807,7 @@ bool AppMenuModel::IsCommandIdChecked(int command_id) const {
return false;
}
-bool AppMenuModel::IsCommandIdEnabled(int command_id) const {
+bool AppMenuModel::IsCommandIdEnabledInternal(int command_id) const {
GlobalError* error =
GlobalErrorServiceFactory::GetForProfile(browser_->profile())
->GetGlobalErrorByMenuItemCommandID(command_id);
@@ -771,7 +822,7 @@ bool AppMenuModel::IsCommandIdEnabled(int command_id) const {
}
}
-bool AppMenuModel::IsCommandIdVisible(int command_id) const {
+bool AppMenuModel::IsCommandIdVisibleInternal(int command_id) const {
switch (command_id) {
case IDC_PIN_TO_START_SCREEN:
return false;
@@ -794,6 +845,34 @@ bool AppMenuModel::IsCommandIdVisible(int command_id) const {
}
}
+bool AppMenuModel::IsCommandIdEnabled(int command_id) const {
+ if (!IsCommandIdEnabledInternal(command_id)) {
+ return false;
+ }
+
+#if BUILDFLAG(ENABLE_CEF)
+ if (browser_->cef_delegate()) {
+ return browser_->cef_delegate()->IsAppMenuItemEnabled(command_id);
+ }
+#endif
+
+ return true;
+}
+
+bool AppMenuModel::IsCommandIdVisible(int command_id) const {
+ if (!IsCommandIdVisibleInternal(command_id)) {
+ return false;
+ }
+
+#if BUILDFLAG(ENABLE_CEF)
+ if (browser_->cef_delegate()) {
+ return browser_->cef_delegate()->IsAppMenuItemVisible(command_id);
+ }
+#endif
+
+ return true;
+}
+
bool AppMenuModel::IsCommandIdAlerted(int command_id) const {
if ((command_id == IDC_RECENT_TABS_MENU) ||
(command_id == AppMenuModel::kMinRecentTabsCommandId)) {
@@ -899,9 +978,13 @@ void AppMenuModel::Build() {
bookmark_sub_menu_model_.get());
}
- AddSeparator(ui::LOWER_SEPARATOR);
- CreateZoomMenu();
- AddSeparator(ui::UPPER_SEPARATOR);
+ if (IsCommandIdVisible(IDC_ZOOM_MENU)) {
+ AddSeparator(ui::LOWER_SEPARATOR);
+ CreateZoomMenu();
+ AddSeparator(ui::UPPER_SEPARATOR);
+ } else {
+ AddSeparator(ui::NORMAL_SEPARATOR);
+ }
AddItemWithStringId(IDC_PRINT, IDS_PRINT);
@@ -965,9 +1048,14 @@ void AppMenuModel::Build() {
sub_menus_.back().get());
SetElementIdentifierAt(GetIndexOfCommandId(IDC_MORE_TOOLS_MENU).value(),
kMoreToolsMenuItem);
- AddSeparator(ui::LOWER_SEPARATOR);
- CreateCutCopyPasteMenu();
- AddSeparator(ui::UPPER_SEPARATOR);
+
+ if (IsCommandIdVisible(IDC_EDIT_MENU)) {
+ AddSeparator(ui::LOWER_SEPARATOR);
+ CreateCutCopyPasteMenu();
+ AddSeparator(ui::UPPER_SEPARATOR);
+ } else {
+ AddSeparator(ui::NORMAL_SEPARATOR);
+ }
AddItemWithStringId(IDC_OPTIONS, IDS_SETTINGS);
// The help submenu is only displayed on official Chrome builds. As the
@@ -1004,6 +1092,11 @@ void AppMenuModel::Build() {
}
#endif // !BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(ENABLE_CEF)
+ FilterMenuModel(this, base::BindRepeating(&AppMenuModel::IsCommandIdVisible,
+ base::Unretained(this)));
+#endif
+
uma_action_recorded_ = false;
}
diff --git chrome/browser/ui/toolbar/app_menu_model.h chrome/browser/ui/toolbar/app_menu_model.h
index fa3ceed419c16..522671662cbdf 100644
--- chrome/browser/ui/toolbar/app_menu_model.h
+++ chrome/browser/ui/toolbar/app_menu_model.h
@@ -208,6 +208,9 @@ class AppMenuModel : public ui::SimpleMenuModel,
// Appends a zoom menu (without separators).
void CreateZoomMenu();
+ bool IsCommandIdEnabledInternal(int command_id) const;
+ bool IsCommandIdVisibleInternal(int command_id) const;
+
private:
friend class ::MockAppMenuModel;
diff --git chrome/browser/ui/views/frame/browser_frame.cc chrome/browser/ui/views/frame/browser_frame.cc
index 090ad157308b7..d0534ffb8091c 100644
--- chrome/browser/ui/views/frame/browser_frame.cc
@ -418,6 +594,23 @@ index 5e059b9878fc2..c1f6fbcd40ec4 100644
}
ContentsWebView::~ContentsWebView() {
diff --git chrome/browser/ui/views/page_action/page_action_icon_controller.cc chrome/browser/ui/views/page_action/page_action_icon_controller.cc
index c26f017f45682..f9f875292c7d6 100644
--- chrome/browser/ui/views/page_action/page_action_icon_controller.cc
+++ chrome/browser/ui/views/page_action/page_action_icon_controller.cc
@@ -91,6 +91,12 @@ void PageActionIconController::Init(const PageActionIconParams& params,
};
for (PageActionIconType type : params.types_enabled) {
+#if BUILDFLAG(ENABLE_CEF)
+ if (params.browser && params.browser->cef_delegate() &&
+ !params.browser->cef_delegate()->IsPageActionIconVisible(type)) {
+ continue;
+ }
+#endif
switch (type) {
case PageActionIconType::kPaymentsOfferNotification:
add_page_action_icon(
diff --git chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
index f4a5c3ad8cc9c..4f9c1a111e7ce 100644
--- chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
@ -471,7 +664,7 @@ index f4a5c3ad8cc9c..4f9c1a111e7ce 100644
}
diff --git chrome/browser/ui/views/toolbar/toolbar_view.cc chrome/browser/ui/views/toolbar/toolbar_view.cc
index 65ba764446ced..dbe856f34caca 100644
index 65ba764446ced..140ff05e1b276 100644
--- chrome/browser/ui/views/toolbar/toolbar_view.cc
+++ chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -164,12 +164,13 @@ auto& GetViewCommandMap() {
@ -499,6 +692,65 @@ index 65ba764446ced..dbe856f34caca 100644
// Make sure the toolbar shows by default.
size_animation_.Reset(1);
@@ -224,6 +225,19 @@ void ToolbarView::Init() {
browser, command, ui::DispositionFromEventFlags(event.flags()));
};
+#if BUILDFLAG(ENABLE_CEF)
+ using ToolbarButtonType = cef::BrowserDelegate::ToolbarButtonType;
+ auto button_visible = [this](ToolbarButtonType type) {
+ if (this->browser_->cef_delegate()) {
+ return this->browser_->cef_delegate()->IsToolbarButtonVisible(type);
+ }
+ return true;
+ };
+ #define BUTTON_VISIBLE(type) button_visible(ToolbarButtonType::type)
+#else
+ #define BUTTON_VISIBLE(type) true
+#endif
+
std::unique_ptr<ToolbarButton> back = std::make_unique<BackForwardButton>(
BackForwardButton::Direction::kBack,
base::BindRepeating(callback, browser_, IDC_BACK), browser_);
@@ -248,8 +262,10 @@ void ToolbarView::Init() {
std::make_unique<ExtensionsToolbarContainer>(browser_);
}
std::unique_ptr<media_router::CastToolbarButton> cast;
- if (media_router::MediaRouterEnabled(browser_->profile()))
+ if (media_router::MediaRouterEnabled(browser_->profile()) &&
+ BUTTON_VISIBLE(kCast)) {
cast = media_router::CastToolbarButton::Create(browser_);
+ }
std::unique_ptr<MediaToolbarButtonView> media_button;
if (base::FeatureList::IsEnabled(media::kGlobalMediaControls)) {
@@ -258,21 +274,23 @@ void ToolbarView::Init() {
}
std::unique_ptr<DownloadToolbarButtonView> download_button;
- if (download::IsDownloadBubbleEnabled(browser_->profile())) {
+ if (download::IsDownloadBubbleEnabled(browser_->profile()) &&
+ BUTTON_VISIBLE(kDownload)) {
download_button =
std::make_unique<DownloadToolbarButtonView>(browser_view_);
}
std::unique_ptr<send_tab_to_self::SendTabToSelfToolbarIconView>
send_tab_to_self_button;
- if (!browser_->profile()->IsOffTheRecord()) {
+ if (!browser_->profile()->IsOffTheRecord() &&
+ BUTTON_VISIBLE(kSendTabToSelf)) {
send_tab_to_self_button =
std::make_unique<send_tab_to_self::SendTabToSelfToolbarIconView>(
browser_view_);
}
std::unique_ptr<SidePanelToolbarButton> side_panel_button;
- if (browser_view_->unified_side_panel()) {
+ if (browser_view_->unified_side_panel() && BUTTON_VISIBLE(kSidePanel)) {
side_panel_button = std::make_unique<SidePanelToolbarButton>(browser_);
}
diff --git chrome/browser/ui/views/toolbar/toolbar_view.h chrome/browser/ui/views/toolbar/toolbar_view.h
index 05dfd39061580..29c677a735672 100644
--- chrome/browser/ui/views/toolbar/toolbar_view.h

View File

@ -301,6 +301,133 @@ void OnTestSMRProcessMessageReceived(
frame->SendProcessMessage(PID_RENDERER, builder->Build());
}
bool IsAllowedPageActionIcon(cef_chrome_page_action_icon_type_t icon_type) {
// Only the specified icons will be allowed.
switch (icon_type) {
case CEF_CPAIT_FIND:
case CEF_CPAIT_ZOOM:
return true;
default:
break;
}
return false;
}
bool IsAllowedToolbarButton(cef_chrome_toolbar_button_type_t button_type) {
// All configurable buttons will be disabled.
return false;
}
bool IsAllowedAppMenuCommandId(int command_id) {
// Only the commands in this array will be allowed.
static const int kAllowedCommandIds[] = {
IDC_NEW_WINDOW,
IDC_NEW_INCOGNITO_WINDOW,
// Zoom buttons.
IDC_ZOOM_MENU,
IDC_ZOOM_PLUS,
IDC_ZOOM_NORMAL,
IDC_ZOOM_MINUS,
IDC_FULLSCREEN,
IDC_PRINT,
IDC_FIND,
// "More tools" sub-menu and contents.
IDC_MORE_TOOLS_MENU,
IDC_CLEAR_BROWSING_DATA,
IDC_MANAGE_EXTENSIONS,
IDC_PERFORMANCE,
IDC_TASK_MANAGER,
IDC_DEV_TOOLS,
// Edit buttons.
IDC_EDIT_MENU,
IDC_CUT,
IDC_COPY,
IDC_PASTE,
IDC_OPTIONS,
IDC_EXIT,
};
for (size_t i = 0; i < std::size(kAllowedCommandIds); ++i) {
if (command_id == kAllowedCommandIds[i]) {
return true;
}
}
return false;
}
bool IsAllowedContextMenuCommandId(int command_id) {
// Allow commands added by web content.
if (command_id >= IDC_CONTENT_CONTEXT_CUSTOM_FIRST &&
command_id <= IDC_CONTENT_CONTEXT_CUSTOM_LAST) {
return true;
}
// Allow commands added by extensions.
if (command_id >= IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST &&
command_id <= IDC_EXTENSIONS_CONTEXT_CUSTOM_LAST) {
return true;
}
// Only the commands in this array will be allowed.
static const int kAllowedCommandIds[] = {
// Page navigation.
IDC_BACK,
IDC_FORWARD,
IDC_RELOAD,
IDC_RELOAD_BYPASSING_CACHE,
IDC_RELOAD_CLEARING_CACHE,
IDC_STOP,
// Printing.
IDC_PRINT,
// Edit controls.
IDC_CONTENT_CONTEXT_CUT,
IDC_CONTENT_CONTEXT_COPY,
IDC_CONTENT_CONTEXT_PASTE,
IDC_CONTENT_CONTEXT_PASTE_AND_MATCH_STYLE,
IDC_CONTENT_CONTEXT_DELETE,
IDC_CONTENT_CONTEXT_SELECTALL,
IDC_CONTENT_CONTEXT_UNDO,
IDC_CONTENT_CONTEXT_REDO,
};
for (size_t i = 0; i < std::size(kAllowedCommandIds); ++i) {
if (command_id == kAllowedCommandIds[i]) {
return true;
}
}
return false;
}
void FilterContextMenuModel(CefRefPtr<CefMenuModel> model) {
// Evaluate from the bottom to the top because we'll be removing menu items.
for (size_t x = model->GetCount(); x > 0; --x) {
const auto i = x - 1;
const auto type = model->GetTypeAt(i);
if (type == MENUITEMTYPE_SUBMENU) {
// Filter sub-menu and remove if empty.
auto sub_model = model->GetSubMenuAt(i);
FilterContextMenuModel(sub_model);
if (sub_model->GetCount() == 0) {
model->RemoveAt(i);
}
} else if (type == MENUITEMTYPE_SEPARATOR) {
// A separator shouldn't be the first or last element in the menu, and
// there shouldn't be multiple in a row.
if (i == 0 || i == model->GetCount() - 1 ||
model->GetTypeAt(i + 1) == MENUITEMTYPE_SEPARATOR) {
model->RemoveAt(i);
}
} else if (!IsAllowedContextMenuCommandId(model->GetCommandIdAt(i))) {
model->RemoveAt(i);
}
}
}
} // namespace
class ClientDownloadImageCallback : public CefDownloadImageCallback {
@ -343,6 +470,8 @@ ClientHandler::ClientHandler(Delegate* delegate,
mouse_cursor_change_disabled_ =
command_line->HasSwitch(switches::kMouseCursorChangeDisabled);
offline_ = command_line->HasSwitch(switches::kOffline);
filter_chrome_commands_ =
command_line->HasSwitch(switches::kFilterChromeCommands);
#if defined(OS_LINUX)
// Optionally use the client-provided GTK dialogs.
@ -442,10 +571,20 @@ bool ClientHandler::OnChromeCommand(CefRefPtr<CefBrowser> browser,
CEF_REQUIRE_UI_THREAD();
DCHECK(MainContext::Get()->UseChromeRuntime());
if (!with_controls_ &&
(disposition != WOD_CURRENT_TAB || !IsAllowedCommandId(command_id))) {
// Block everything that doesn't target the current tab or isn't an
// allowed command ID.
const bool allowed = IsAllowedAppMenuCommandId(command_id) ||
IsAllowedContextMenuCommandId(command_id);
bool block = false;
if (filter_chrome_commands_) {
// Block all commands that aren't specifically allowed.
block = !allowed;
} else if (!with_controls_) {
// If controls are hidden, block all commands that don't target the current
// tab or aren't specifically allowed.
block = disposition != WOD_CURRENT_TAB || !allowed;
}
if (block) {
LOG(INFO) << "Blocking command " << command_id << " with disposition "
<< disposition;
return true;
@ -455,6 +594,36 @@ bool ClientHandler::OnChromeCommand(CefRefPtr<CefBrowser> browser,
return false;
}
bool ClientHandler::IsChromeAppMenuItemVisible(CefRefPtr<CefBrowser> browser,
int command_id) {
CEF_REQUIRE_UI_THREAD();
DCHECK(MainContext::Get()->UseChromeRuntime());
if (!filter_chrome_commands_) {
return true;
}
return IsAllowedAppMenuCommandId(command_id);
}
bool ClientHandler::IsChromePageActionIconVisible(
cef_chrome_page_action_icon_type_t icon_type) {
CEF_REQUIRE_UI_THREAD();
DCHECK(MainContext::Get()->UseChromeRuntime());
if (!filter_chrome_commands_) {
return true;
}
return IsAllowedPageActionIcon(icon_type);
}
bool ClientHandler::IsChromeToolbarButtonVisible(
cef_chrome_toolbar_button_type_t button_type) {
CEF_REQUIRE_UI_THREAD();
DCHECK(MainContext::Get()->UseChromeRuntime());
if (!filter_chrome_commands_) {
return true;
}
return IsAllowedToolbarButton(button_type);
}
void ClientHandler::OnBeforeContextMenu(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefContextMenuParams> params,
@ -462,9 +631,9 @@ void ClientHandler::OnBeforeContextMenu(CefRefPtr<CefBrowser> browser,
CEF_REQUIRE_UI_THREAD();
const bool use_chrome_runtime = MainContext::Get()->UseChromeRuntime();
if (use_chrome_runtime && !with_controls_) {
if (use_chrome_runtime && (!with_controls_ || filter_chrome_commands_)) {
// Remove all disallowed menu items.
FilterMenuModel(model);
FilterContextMenuModel(model);
}
if ((params->GetTypeFlags() & (CM_TYPEFLAG_PAGE | CM_TYPEFLAG_FRAME)) != 0) {
@ -1438,61 +1607,4 @@ void ClientHandler::SetOfflineState(CefRefPtr<CefBrowser> browser,
/*message_id=*/0, "Network.emulateNetworkConditions", params);
}
void ClientHandler::FilterMenuModel(CefRefPtr<CefMenuModel> model) {
// Evaluate from the bottom to the top because we'll be removing menu items.
for (size_t x = model->GetCount(); x > 0; --x) {
const auto i = x - 1;
const auto type = model->GetTypeAt(i);
if (type == MENUITEMTYPE_SUBMENU) {
// Filter sub-menu and remove if empty.
auto sub_model = model->GetSubMenuAt(i);
FilterMenuModel(sub_model);
if (sub_model->GetCount() == 0) {
model->RemoveAt(i);
}
} else if (type == MENUITEMTYPE_SEPARATOR) {
// A separator shouldn't be the first or last element in the menu, and
// there shouldn't be multiple in a row.
if (i == 0 || i == model->GetCount() - 1 ||
model->GetTypeAt(i + 1) == MENUITEMTYPE_SEPARATOR) {
model->RemoveAt(i);
}
} else if (!IsAllowedCommandId(model->GetCommandIdAt(i))) {
model->RemoveAt(i);
}
}
}
bool ClientHandler::IsAllowedCommandId(int command_id) {
// Only the commands in this array will be allowed.
static const int kAllowedCommandIds[] = {
// Page navigation.
IDC_BACK,
IDC_FORWARD,
IDC_RELOAD,
IDC_RELOAD_BYPASSING_CACHE,
IDC_RELOAD_CLEARING_CACHE,
IDC_STOP,
// Printing.
IDC_PRINT,
// Edit controls.
IDC_CONTENT_CONTEXT_CUT,
IDC_CONTENT_CONTEXT_COPY,
IDC_CONTENT_CONTEXT_PASTE,
IDC_CONTENT_CONTEXT_PASTE_AND_MATCH_STYLE,
IDC_CONTENT_CONTEXT_DELETE,
IDC_CONTENT_CONTEXT_SELECTALL,
IDC_CONTENT_CONTEXT_UNDO,
IDC_CONTENT_CONTEXT_REDO,
};
for (size_t i = 0; i < std::size(kAllowedCommandIds); ++i) {
if (command_id == kAllowedCommandIds[i]) {
return true;
}
}
return false;
}
} // namespace client

View File

@ -139,6 +139,12 @@ class ClientHandler : public CefClient,
bool OnChromeCommand(CefRefPtr<CefBrowser> browser,
int command_id,
cef_window_open_disposition_t disposition) override;
bool IsChromeAppMenuItemVisible(CefRefPtr<CefBrowser> browser,
int command_id) override;
bool IsChromePageActionIconVisible(
cef_chrome_page_action_icon_type_t icon_type) override;
bool IsChromeToolbarButtonVisible(
cef_chrome_toolbar_button_type_t button_type) override;
// CefContextMenuHandler methods
void OnBeforeContextMenu(CefRefPtr<CefBrowser> browser,
@ -371,10 +377,6 @@ class ClientHandler : public CefClient,
void SetOfflineState(CefRefPtr<CefBrowser> browser, bool offline);
// Filter menu and keyboard shortcut commands.
void FilterMenuModel(CefRefPtr<CefMenuModel> model);
bool IsAllowedCommandId(int command_id);
// THREAD SAFE MEMBERS
// The following members may be accessed from any thread.
@ -396,6 +398,9 @@ class ClientHandler : public CefClient,
// True if the browser is currently offline.
bool offline_;
// True if the Chrome toolbar and menu contents/commands should be filtered.
bool filter_chrome_commands_;
// True if Favicon images should be downloaded.
bool download_favicon_images_ = false;

View File

@ -29,6 +29,7 @@ const char kSharedTextureEnabled[] = "shared-texture-enabled";
const char kExternalBeginFrameEnabled[] = "external-begin-frame-enabled";
const char kMouseCursorChangeDisabled[] = "mouse-cursor-change-disabled";
const char kOffline[] = "offline";
const char kFilterChromeCommands[] = "filter-chrome-commands";
const char kRequestContextPerBrowser[] = "request-context-per-browser";
const char kRequestContextSharedCache[] = "request-context-shared-cache";
const char kBackgroundColor[] = "background-color";

View File

@ -23,6 +23,7 @@ extern const char kSharedTextureEnabled[];
extern const char kExternalBeginFrameEnabled[];
extern const char kMouseCursorChangeDisabled[];
extern const char kOffline[];
extern const char kFilterChromeCommands[];
extern const char kRequestContextPerBrowser[];
extern const char kRequestContextSharedCache[];
extern const char kBackgroundColor[];