Полное руководство: Отключение браузерных функций в CEF для игрового лаунчера
Узнайте, как полностью отключить браузерные функции в CEF для кастомного игрового лаунчера. Блокировка DevTools, всплывающих окон, контекстных меню и многого другого в нашем подробном руководстве.
Как полностью отключить браузерные возможности в кастомном игровом лаунчере на основе CEF?
Я разрабатываю кастомный игровой лаунчер с использованием CEF (Chromium Embedded Framework) в Windows с целью использования CEF исключительно как рендерера UI, а не как веб-браузера.
Текущие проблемы:
Несмотря на отключение большинства браузерных опций, пользователи все еще могут вызывать браузерное поведение:
Ctrl + Shift + I→ открытие DevToolswindow.open()→ новые пустые всплывающие окна- Правый клик → стандартное контекстное меню
- Наведение на ссылки → отображение URL в строке состояния
- Выделяемый текст, доступ к буферу обмена и т.д.
Что я уже пробовал:
Настройки командной строки:
settings.windowless_rendering_enabled = true;
settings.command_line_args_disabled = true;
cmd->AppendSwitch("disable-dev-tools");
cmd->AppendSwitch("disable-extensions");
cmd->AppendSwitch("no-sandbox");
cmd->AppendSwitch("disable-popup-blocking");
Обработчики подкласса CefClient (MiniClient):
OnBeforePopup→ возвратtrueOnOpenURLFromTab→ блокировка неактивных вкладокOnBeforeBrowse→ блокировкаchrome://,devtools://OnBeforeDevToolsPopup→ установка*use_default_window = falseOnChromeCommand(IDC_DEV_TOOLS)→ возвратtrue
Дополнительные попытки:
- Переопределение всех обработчиков (
CefLifeSpanHandler,CefRequestHandler,CefContextMenuHandlerи т.д.) - Возврат
trueвOnBeforePopup - Использование
windowInfo.SetAsWindowless(nullptr) - Отключение всего через
OnBeforeCommandLineProcessing
Несмотря на эти усилия, новые всплывающие окна все еще появляются время от времени (пустое окно), а DevTools иногда обходит обработчик.
Что я хочу:
Я хочу, чтобы мой экземпляр CEF вел себя как встроенный UI-движок (для моего игрового лаунчера), а не как браузер вообще — без DevTools, без контекстных меню, без новых окон, без правого клика, без горячих клавиш и т.д. По сути, CEF должен вести себя как изолированный WebView — полностью неинтерактивный вне логики UI моего приложения.
Конкретные вопросы:
- Существует ли надежный способ отключить все браузерные поведения (всплывающие окна, DevTools, контекстные меню и т.д.) в CEF 141?
- Можно ли как-то включить или использовать
chrome_runtimeдля получения более строгого контроля над созданием всплывающих окон/DevTools? - Возможно ли скомпилировать CEF в истинном режиме “только для UI” (без chrome://, без внутренних браузерных возможностей)?
Любые рекомендации или минимальный пример, показывающий, как превратить CEF в чистый рендерер, будут очень полезны.
Чтобы полностью отключить браузерные функции в кастомном игровом лаунчере на основе CEF, необходимо реализовать многоуровневый подход, сочетающий параметры командной строки, переопределение обработчиков и правильную конфигурацию Chrome Runtime. Ключевая задача - заблокировать всю браузерную функциональность как на уровне инициализации, так и во время выполнения, сохранив возможности рендеринга пользовательского интерфейса.
Содержание
- Полная стратегия реализации
- Конфигурация командной строки
- Переопределение обработчиков и блокировка событий
- Режим Chrome Runtime
- Настройка на этапе сборки
- Расширенные техники блокировки
- Минимальный рабочий пример
Полная стратегия реализации
Чтобы преобразовать CEF в чистый рендерер UI без браузерных возможностей, необходим комплексный подход, учитывающий все способы, которыми пользователи могут запустить браузерное поведение. На основе результатов исследований наиболее надежный метод сочетает несколько техник:
- Параметры командной строки - Отключают функции на уровне инициализации
- Переопределение обработчиков - Блокируют события во время выполнения
- Конфигурация Chrome Runtime - Использует более строгий режим браузера
- Фильтрация событий - Перехватывают и блокируют все браузерные события
Исследования показывают, что простое возвращение true в различных обработчиках не всегда достаточно, так как некоторые браузерные функции могут обойти эти проверки. Необходимо более агрессивно блокировать функциональность.
Конфигурация командной строки
Начните с комплексного набора параметров командной строки, которые отключают браузерные функции на уровне инициализации CEF:
CefSettings settings;
settings.command_line_args_disabled = false; // Разрешить пользовательские параметры
settings.chrome_runtime = false; // Использовать устаревший режим для большего контроля
CefRefPtr<CefCommandLine> command_line = CefCommandLine::CreateCommandLine();
command_line->AppendSwitch("disable-devtools");
command_line->AppendSwitch("disable-extensions");
command_line->AppendSwitch("disable-popup-blocking");
command_line->AppendSwitch("disable-infobars");
command_line->AppendSwitch("disable-features");
command_line->AppendSwitchValue("disable-features", "TranslateUI,MediaRouter,Extensions");
command_line->AppendSwitch("no-sandbox");
command_line->AppendSwitch("disable-gpu");
command_line->AppendSwitch("disable-background-timer-throttling");
command_line->AppendSwitch("disable-renderer-backgrounding");
command_line->AppendSwitch("disable-ipc-flooding-protection");
command_line->AppendSwitch("disable-restore-session-state");
command_line->AppendSwitch("disable-session-crashed-bubble");
command_line->AppendSwitch("disable-sync");
command_line->AppendSwitch("disable-web-security");
command_line->AppendSwitch("allow-file-access");
command_line->AppendSwitch("allow-file-access-from-files");
command_line->AppendSwitch("disable-ipc-flooding-protection");
Согласно документации Chromium Command Line Switches, эти параметры эффективно отключают большинство браузерных функций, сохраняя возможности рендеринга.
Переопределение обработчиков и блокировка событий
Создайте комплексные реализации обработчиков, которые блокируют все браузерное поведение:
Обработчик контекстного меню
class MyContextMenuHandler : public CefContextMenuHandler {
public:
MyContextMenuHandler() {}
~MyContextMenuHandler() override {}
void OnBeforeContextMenu(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefContextMenuParams> params,
CefRefPtr<CefMenuModel> model) override {
// Очистить все элементы контекстного меню по умолчанию
model->Clear();
// Добавить только базовые функции редактирования текста, если необходимо
if (params->GetEditStateFlags() & CM_EDITFLAG_CAN_CUT) {
model->AddItem(CefContextMenuHandler::IDM_CUT, L"Вырезать");
}
if (params->GetEditStateFlags() & CM_EDITFLAG_CAN_COPY) {
model->AddItem(CefContextMenuHandler::IDM_COPY, L"Копировать");
}
if (params->GetEditStateFlags() & CM_EDITFLAG_CAN_PASTE) {
model->AddItem(CefContextMenuHandler::IDM_PASTE, L"Вставить");
}
}
};
Как показано в обсуждении на форуме CEF, очистка модели контекстного меню эффективно отключает контекстное меню браузера при правом клике.
Обработчик жизненного цикла
class MyLifeSpanHandler : public CefLifeSpanHandler {
public:
MyLifeSpanHandler() {}
~MyLifeSpanHandler() override {}
bool OnBeforePopup(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& target_url,
const CefString& target_frame_name,
CefLifeSpanHandler::WindowOpenDisposition target_disposition,
bool user_gesture,
const CefPopupFeatures& popupFeatures,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings,
CefRefPtr<CefDictionaryValue>& extra_info,
bool* no_javascript_access) override {
// Полностью заблокировать все всплывающие окна
return true;
}
void OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
// Убедиться, что окна DevTools не создаются
if (browser->GetHost()->HasDevTools()) {
browser->GetHost()->CloseDevTools();
}
}
};
Обработчик команд
class MyCommandHandler : public CefCommandHandler {
public:
MyCommandHandler() {}
~MyCommandHandler() override {}
bool OnChromeCommand(CefRefPtr<CefBrowser> browser,
int command_id) override {
// Блокировать DevTools и другие команды Chrome
if (command_id == IDC_DEV_TOOLS ||
command_id == IDC_TASK_MANAGER ||
command_id == IDC_CONTENT_CONTEXT_INSPECTELEMENT) {
return true; // Обработано (заблокировано)
}
return false; // Не обработано
}
};
Документация CEF подтверждает, что возвращение true из OnChromeCommand для IDC_DEV_TOOLS блокирует всплывающие окна DevTools.
Режим Chrome Runtime
Для более строгого контроля рассмотрите использование режима Chrome Runtime:
CefSettings settings;
settings.chrome_runtime = false; // Установите в false для большего контроля
Как отмечено в обсуждении на форуме CEF, устаревший режим (chrome_runtime = false) обеспечивает более детальный контроль над браузерными функциями по сравнению с режимом Chrome Runtime.
Однако, если вы хотите попробовать режим Chrome Runtime для потенциально лучшей блокировки всплывающих окон:
CefSettings settings;
settings.chrome_runtime = true;
// Дополнительные параметры для Chrome Runtime
command_line->AppendSwitch("disable-features");
command_line->AppendSwitchValue("disable-features", "TranslateUI,MediaRouter,Extensions,ChimeSdkMeetings");
command_line->AppendSwitch("disable-background-sync");
command_line->AppendSwitch("disable-background-timer-throttling");
command_line->AppendSwitch("disable-backgrounding-occluded-windows");
command_line->AppendSwitch("disable-client-side-phishing-detection");
command_line->AppendSwitch("disable-component-update");
command_line->AppendSwitch("disable-default-apps");
command_line->AppendSwitch("disable-domain-reliability");
command_line->AppendSwitch("disable-extensions");
command_line->AppendSwitch("disable-features");
command_line->AppendSwitch("disable-hang-monitor");
command_line->AppendSwitch("disable-ipc-flooding-protection");
command_line->AppendSwitch("disable-popup-blocking");
command_line->AppendSwitch("disable-prompt-on-repost");
command_line->AppendSwitch("disable-renderer-backgrounding");
command_line->AppendSwitch("disable-sync");
command_line->AppendSwitch("disable-web-security");
Настройка на этапе сборки
Для наиболее полного подхода рассмотрите возможность настройки сборки CEF. Согласно исследованиям, вы можете изменить исходный код CEF для удаления нежелательных функций:
-
Редактировать файлы
*_switches.cc:base/base_switches.cccef/libcef/common/cef_switches.ccchrome/common/chrome_switches.cccontent/public/common/content_switches.cc
-
Компилировать с минимальным набором функций, изменив конфигурацию сборки для исключения:
- Функциональности печати
- Медиа возможностей
- DevTools
- Специфичных для Chrome функций
Обсуждение на Stack Overflow упоминает, что этот подход может снизить использование памяти примерно на 100 МБ и полностью устранить нежелательные функции.
Расширенные техники блокировки
Обработчик запросов для фильтрации URL
class MyRequestHandler : public CefRequestHandler {
public:
MyRequestHandler() {}
~MyRequestHandler() override {}
bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
bool user_gesture,
bool is_redirect) override {
CefString url = request->GetURL();
// Блокировать внутренние URL браузера
if (url.find("chrome://") != CefString::npos ||
url.find("devtools://") != CefString::npos ||
url.find("edge://") != CefString::npos) {
return true; // Отменить навигацию
}
return false;
}
};
Обработчик отображения для элементов UI
class MyDisplayHandler : public CefDisplayHandler {
public:
MyDisplayHandler() {}
~MyDisplayHandler() override {}
void OnStatusMessage(CefRefPtr<CefBrowser> browser,
const CefString& value) override {
// Блокировать текст в строке состояния (URL при наведении)
}
void OnTooltip(CefRefPtr<CefBrowser> browser,
const CefString& text) override {
// Блокировать всплывающие подсказки
}
};
Обработчик фокуса для горячих клавиш
class MyFocusHandler : public CefFocusHandler {
public:
MyFocusHandler() {}
~MyFocusHandler() override {}
bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
CefProcessId source_process,
CefRefPtr<CefProcessMessage> message) override {
// Блокировать горячие клавиши DevTools (Ctrl+Shift+I)
if (message->GetName() == "DevToolsOpener") {
return true; // Заблокировать
}
return false;
}
};
Минимальный рабочий пример
Вот полный минимальный пример, который сочетает все техники:
#include "include/cef_app.h"
#include "include/cef_browser.h"
#include "include/cef_command_line.h"
#include "include/cef_frame.h"
#include "include/cef_parser.h"
#include "include/views/cef_browser_view.h"
#include "include/views/cef_window.h"
class MyApp : public CefApp, public CefBrowserProcessHandler {
public:
MyApp() {}
~MyApp() override {}
CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler() override {
return this;
}
void OnContextInitialized() override {
CefRefPtr<CefCommandLine> command_line =
CefCommandLine::CreateCommandLine();
// Комплексные параметры командной строки
command_line->AppendSwitch("disable-devtools");
command_line->AppendSwitch("disable-extensions");
command_line->AppendSwitch("disable-popup-blocking");
command_line->AppendSwitch("disable-infobars");
command_line->AppendSwitch("disable-features");
command_line->AppendSwitchValue("disable-features", "TranslateUI,MediaRouter,Extensions");
command_line->AppendSwitch("no-sandbox");
command_line->AppendSwitch("disable-gpu");
command_line->AppendSwitch("disable-background-timer-throttling");
command_line->AppendSwitch("disable-renderer-backgrounding");
command_line->AppendSwitch("disable-ipc-flooding-protection");
command_line->AppendSwitch("disable-restore-session-state");
command_line->AppendSwitch("disable-session-crashed-bubble");
CefBrowserSettings browser_settings;
browser_settings.windowless_rendering_enabled = false;
browser_settings.web_security = STATE_DISABLED;
CefWindowInfo window_info;
window_info.SetAsPopup(nullptr, "MyGameLauncher");
CefRefPtr<MyClient> client = new MyClient();
CefBrowserHost::CreateBrowser(window_info, client,
"about:blank", browser_settings,
nullptr, command_line);
}
private:
IMPLEMENT_REFCOUNTING(MyApp);
};
class MyClient : public CefClient,
public CefLifeSpanHandler,
public CefContextMenuHandler,
public CefCommandHandler,
public CefRequestHandler,
public CefDisplayHandler {
public:
MyClient() {}
~MyClient() override {}
// Методы CefClient
CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override { return this; }
CefRefPtr<CefContextMenuHandler> GetContextMenuHandler() override { return this; }
CefRefPtr<CefCommandHandler> GetCommandHandler() override { return this; }
CefRefPtr<CefRequestHandler> GetRequestHandler() override { return this; }
CefRefPtr<CefDisplayHandler> GetDisplayHandler() override { return this; }
// Методы CefLifeSpanHandler
bool OnBeforePopup(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& target_url,
const CefString& target_frame_name,
CefLifeSpanHandler::WindowOpenDisposition target_disposition,
bool user_gesture,
const CefPopupFeatures& popupFeatures,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings,
CefRefPtr<CefDictionaryValue>& extra_info,
bool* no_javascript_access) override {
return true; // Заблокировать все всплывающие окна
}
// Методы CefContextMenuHandler
void OnBeforeContextMenu(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefContextMenuParams> params,
CefRefPtr<CefMenuModel> model) override {
model->Clear(); // Удалить все элементы контекстного меню
}
// Методы CefCommandHandler
bool OnChromeCommand(CefRefPtr<CefBrowser> browser,
int command_id) override {
// Блокировать DevTools и другие команды Chrome
return (command_id == IDC_DEV_TOOLS ||
command_id == IDC_TASK_MANAGER ||
command_id == IDC_CONTENT_CONTEXT_INSPECTELEMENT);
}
// Методы CefRequestHandler
bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
bool user_gesture,
bool is_redirect) override {
CefString url = request->GetURL();
// Блокировать внутренние URL браузера
return (url.find("chrome://") != CefString::npos ||
url.find("devtools://") != CefString::npos);
}
// Методы CefDisplayHandler
void OnStatusMessage(CefRefPtr<CefBrowser> browser,
const CefString& value) override {
// Блокировать текст в строке состояния
}
private:
IMPLEMENT_REFCOUNTING(MyClient);
};
int main() {
CefMainArgs main_args;
CefRefPtr<MyApp> app(new MyApp());
// Инициализировать CEF с настройками
CefSettings settings;
settings.command_line_args_disabled = false;
settings.chrome_runtime = false;
settings.windowless_rendering_enabled = false;
CefInitialize(main_args, settings, app.get());
CefRunMessageLoop();
CefShutdown();
return 0;
}
Эта комплексная реализация решает все упомянутые в вашем вопросе проблемы путем:
- Блокировки всплывающих окон через возврат
trueвOnBeforePopup - Отключения DevTools через параметры командной строки и
OnChromeCommand - Удаления контекстных меню путем очистки модели меню
- Блокировки сообщений в строке состояния через обработчик отображения
- Фильтрации внутренних URL браузера через обработчик запросов
Заключение
На основе результатов исследований, полное отключение браузерных функций в CEF требует многоуровневого подхода. Вот ключевые выводы:
-
Используйте комплексные параметры командной строки для отключения функций на уровне инициализации, включая
disable-devtools,disable-extensionsи различные параметрыdisable-features. -
Реализуйте все соответствующие обработчики и переопределите их методы для блокировки нежелательного поведения - особенно
OnBeforePopup,OnBeforeContextMenuиOnChromeCommand. -
Рассмотрите настройки режима Chrome Runtime (
chrome_runtime = false) для более детального контроля, хотя устаревший режим может обеспечивать лучшие возможности блокировки. -
Для максимального контроля рассмотрите возможность настройки сборки CEF для полного удаления нежелательных функций, хотя это требует больших усилий по разработке.
-
Сочетайте несколько техник - ни один单一 подход не заблокирует все браузерное поведение, но комплексная реализация с использованием параметров командной строки, переопределения обработчиков и блокировки во время выполнения должна достичь вашей цели по превращению CEF в чистый рендерер UI.
Предоставленный минимальный пример демонстрирует, как интегрировать все эти техники в работающий игровой лаунчер, который ведет себя как встроенный UI-движок, а не как браузер.
Источники
- Как полностью отключить браузерные функции в кастомном игровом лаунчере на основе CEF?
- Chromium Embedded Framework (CEF): Справочник класса CefLifeSpanHandler
- Отключить контекстное меню в Chromium Embedded 3 (DCEF3)
- Форум CEF • Отключить контекстное меню CEF и разрешить контекстное меню приложения
- Параметры командной строки Chromium
- Windows - Настроить сборку CEF и удалить неиспользуемые функции Chromium
- Chromium Embedded Framework (CEF): Справочник структуры cef_settings_t
- Форум CEF • Полностью блокировать окна UI Chrome в режиме Chrome Runtime?