mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
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:
@@ -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
|
||||
|
Reference in New Issue
Block a user