Skip to content

Commit d6f85aa

Browse files
committed
Enable support for CEF 6613+ and Chrome Runtime
Add a dummy Browser Client to introduce limitations into the Chrome UI windows that can be opened in uncontrolled edge cases. Chrome UI windows are unmanaged by default. By returning something other than null in GetDefaultClient() we can lock it down in various ways. OnBeforePopup, OnOpenURLFromTab can probably be removed as they don't get called. There's no direct way to stop the Chrome UI window from being opened, so instead close it immediately. Disable Various Chrome Settings in custom docks & browser sources via SetPreferences. For more, check `chrome/common/pref_names.h`. Chrome's default error display is now used by CEF, so on top of the existing override in browser docks, a similar override has been added to browser sources which just redirects to about:blank. Also blocks - Chrome Extensions, as they are largely untested and unpredictable - MediaRouter, which provides Cast.. functionality - CalculateNativeWinOcclusion, which lowers FPS for hidden pages - LiveCaption, which provides automatic captions - DocumentPictureInPictureAPI, which provides PiP widgets (YouTube) A data migration function is included. It moves some directories into a new 'Default' profile subdirectory, and performs the necessary renaming of certain files to ensure the new Profile loads. Additionally, the cookie directories for each service integration must be moved into the root config directory, as subdirectories in their current form (obs_profile_cookies/<cookie_id>) are not supported. This is intentional, and according to Marshall this was never a supported setup. cache_path *must* be a direct child of the root_cache_path. Invalid cache_path_ is silently treated as Incognito Mode and cookies are not stored.
1 parent 19b1c96 commit d6f85aa

14 files changed

Lines changed: 382 additions & 7 deletions

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ target_sources(
2525
browser-app.hpp
2626
browser-client.cpp
2727
browser-client.hpp
28+
browser-dummy-client.cpp
29+
browser-dummy-client.hpp
2830
browser-scheme.cpp
2931
browser-scheme.hpp
3032
browser-version.h

browser-app.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,64 @@ CefRefPtr<CefBrowserProcessHandler> BrowserApp::GetBrowserProcessHandler()
4848
return this;
4949
}
5050

51+
CefRefPtr<CefClient> BrowserApp::GetDefaultClient()
52+
{
53+
return GetDummy();
54+
}
55+
5156
void BrowserApp::OnRegisterCustomSchemes(CefRawPtr<CefSchemeRegistrar> registrar)
5257
{
5358
registrar->AddCustomScheme("http", CEF_SCHEME_OPTION_STANDARD | CEF_SCHEME_OPTION_CORS_ENABLED);
5459
}
5560

61+
void BrowserApp::OnContextInitialized()
62+
{
63+
/**
64+
* Without a default client, CefBrowser is unmanaged, allowing full-blown Chromium windows outside of our control
65+
* We don't actually want those, so define a dummy client which will automatically close any such windows
66+
*/
67+
dummy = new BrowserDummyClient();
68+
69+
CefRefPtr<CefRequestContext> requestContext = CefRequestContext::GetGlobalContext();
70+
CefString errorMessage;
71+
CefRefPtr<CefValue> optionValue = CefValue::Create();
72+
73+
constexpr std::array<std::string_view, 20> kBrowserFeaturesToDisable{
74+
"autofill.credit_card_enabled",
75+
"autofill.enabled",
76+
"autofill.iban_enabled",
77+
"autofill.payment_card_benefits",
78+
"autofill.payment_cvc_storage",
79+
"autofill.profile_enabled",
80+
"autologin.enabled",
81+
"browser_labs_enabled",
82+
"credentials_enable_autosignin",
83+
"credentials_enable_service",
84+
"payments.can_make_payment_enabled",
85+
"printing.enabled",
86+
"search.suggest_enabled",
87+
"shopping_list_enabled",
88+
"side_panel.google_search_side_panel_enabled",
89+
"side_search.enabled",
90+
"signin.allowed",
91+
"signin.allowed_on_next_startup",
92+
"translate",
93+
"url_keyed_anonymized_data_collection.enabled"};
94+
95+
constexpr std::array<std::string_view, 2> kBrowserFeaturesToEnable{"extensions.block_external_extensions",
96+
"extensions.disabled"};
97+
98+
optionValue->SetBool(false);
99+
for (std::string_view feature : kBrowserFeaturesToDisable) {
100+
requestContext->SetPreference(feature.data(), optionValue.get(), errorMessage);
101+
}
102+
103+
optionValue->SetBool(true);
104+
for (std::string_view feature : kBrowserFeaturesToEnable) {
105+
requestContext->SetPreference(feature.data(), optionValue.get(), errorMessage);
106+
}
107+
}
108+
56109
void BrowserApp::OnBeforeChildProcessLaunch(CefRefPtr<CefCommandLine> command_line)
57110
{
58111
#ifdef _WIN32
@@ -82,16 +135,32 @@ void BrowserApp::OnBeforeCommandLineProcessing(const CefString &, CefRefPtr<CefC
82135
disableFeatures += ",EnableWindowsGamingInputDataFetcher";
83136
#endif
84137
disableFeatures += ",WebBluetooth";
138+
disableFeatures += ",MediaRouter";
139+
disableFeatures += ",CalculateNativeWinOcclusion";
140+
disableFeatures += ",LiveCaption";
85141
command_line->AppendSwitchWithValue("disable-features", disableFeatures);
86142
} else {
87143
command_line->AppendSwitchWithValue("disable-features", "WebBluetooth,"
88144
#ifdef _WIN32
89145
"EnableWindowsGamingInputDataFetcher,"
90146
#endif
147+
"MediaRouter,"
148+
"CalculateNativeWinOcclusion,"
149+
"LiveCaption,"
91150
"HardwareMediaKeyHandling");
92151
}
93152

153+
if (command_line->HasSwitch("disable-blink-features")) {
154+
std::string disableBlinkFeatures = command_line->GetSwitchValue("disable-blink-features");
155+
disableBlinkFeatures += ",DocumentPictureInPictureAPI";
156+
command_line->AppendSwitchWithValue("disable-blink-features", disableBlinkFeatures);
157+
} else {
158+
command_line->AppendSwitchWithValue("disable-blink-features", "DocumentPictureInPictureAPI");
159+
}
160+
94161
command_line->AppendSwitchWithValue("autoplay-policy", "no-user-gesture-required");
162+
command_line->AppendSwitch("disable-extensions");
163+
command_line->AppendSwitch("hide-crash-restore-bubble");
95164
#ifdef __APPLE__
96165
command_line->AppendSwitch("use-mock-keychain");
97166
#elif !defined(_WIN32)

browser-app.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <unordered_map>
2323
#include <functional>
2424
#include "cef-headers.hpp"
25+
#include "browser-dummy-client.hpp"
2526

2627
typedef std::function<void(CefRefPtr<CefBrowser>)> BrowserFunc;
2728

@@ -85,6 +86,8 @@ class BrowserApp : public CefApp, public CefRenderProcessHandler, public CefBrow
8586

8687
virtual CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() override;
8788
virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler() override;
89+
virtual CefRefPtr<CefClient> GetDefaultClient() override;
90+
virtual void OnContextInitialized() override;
8891
virtual void OnBeforeChildProcessLaunch(CefRefPtr<CefCommandLine> command_line) override;
8992
virtual void OnRegisterCustomSchemes(CefRawPtr<CefSchemeRegistrar> registrar) override;
9093
virtual void OnBeforeCommandLineProcessing(const CefString &process_type,
@@ -106,5 +109,9 @@ class BrowserApp : public CefApp, public CefRenderProcessHandler, public CefBrow
106109
QTimer frameTimer;
107110
#endif
108111

112+
CefRefPtr<BrowserDummyClient> dummy = nullptr;
113+
114+
BrowserDummyClient *GetDummy() const { return dummy.get(); };
115+
109116
IMPLEMENT_REFCOUNTING(BrowserApp);
110117
};

browser-client.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,18 @@ void BrowserClient::OnLoadEnd(CefRefPtr<CefBrowser>, CefRefPtr<CefFrame> frame,
626626
}
627627
}
628628

629+
void BrowserClient::OnLoadError(CefRefPtr<CefBrowser>, CefRefPtr<CefFrame> frame, CefLoadHandler::ErrorCode,
630+
const CefString &, const CefString &)
631+
{
632+
#if CHROME_VERSION_BUILD > 6533
633+
// CEF doesn't currently provide a way to properly disable/override the default Chrome error page
634+
// FIXME https://github.com/chromiumembedded/cef/issues/3852
635+
frame->LoadURL("about:blank");
636+
#else
637+
UNUSED_PARAMETER(frame);
638+
#endif
639+
}
640+
629641
bool BrowserClient::OnConsoleMessage(CefRefPtr<CefBrowser>, cef_log_severity_t level, const CefString &message,
630642
const CefString &source, int line)
631643
{

browser-client.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,5 +146,9 @@ class BrowserClient : public CefClient,
146146
/* CefLoadHandler */
147147
virtual void OnLoadEnd(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, int httpStatusCode) override;
148148

149+
virtual void OnLoadError(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,
150+
CefLoadHandler::ErrorCode errorCode, const CefString &errorText,
151+
const CefString &failedUrl) override;
152+
149153
IMPLEMENT_REFCOUNTING(BrowserClient);
150154
};

browser-dummy-client.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
2+
#include "browser-dummy-client.hpp"
3+
4+
CefRefPtr<CefCommandHandler> BrowserDummyClient::GetCommandHandler()
5+
{
6+
return this;
7+
}
8+
9+
CefRefPtr<CefRequestHandler> BrowserDummyClient::GetRequestHandler()
10+
{
11+
return this;
12+
}
13+
14+
CefRefPtr<CefLifeSpanHandler> BrowserDummyClient::GetLifeSpanHandler()
15+
{
16+
return this;
17+
}
18+
19+
bool BrowserDummyClient::OnChromeCommand(CefRefPtr<CefBrowser>, int, cef_window_open_disposition_t)
20+
{
21+
return true;
22+
}
23+
24+
bool BrowserDummyClient::IsChromeAppMenuItemVisible(CefRefPtr<CefBrowser>, int)
25+
{
26+
return false;
27+
}
28+
29+
bool BrowserDummyClient::IsChromeToolbarButtonVisible(cef_chrome_toolbar_button_type_t)
30+
{
31+
return false;
32+
}
33+
34+
bool BrowserDummyClient::IsChromePageActionIconVisible(cef_chrome_page_action_icon_type_t)
35+
{
36+
return false;
37+
}
38+
39+
bool BrowserDummyClient::IsChromeAppMenuItemEnabled(CefRefPtr<CefBrowser>, int)
40+
{
41+
return false;
42+
}
43+
44+
bool BrowserDummyClient::OnBeforePopup(CefRefPtr<CefBrowser>, CefRefPtr<CefFrame>,
45+
#if CHROME_VERSION_BUILD >= 6834
46+
int,
47+
#endif
48+
const CefString &, const CefString &, cef_window_open_disposition_t, bool,
49+
const CefPopupFeatures &, CefWindowInfo &, CefRefPtr<CefClient> &,
50+
CefBrowserSettings &, CefRefPtr<CefDictionaryValue> &, bool *)
51+
{
52+
return true;
53+
}
54+
55+
void BrowserDummyClient::OnAfterCreated(CefRefPtr<CefBrowser> browser)
56+
{
57+
if (browser && browser->GetHost()) {
58+
browser->GetHost()->CloseBrowser(false);
59+
}
60+
}
61+
62+
bool BrowserDummyClient::OnOpenURLFromTab(CefRefPtr<CefBrowser>, CefRefPtr<CefFrame>, const CefString &,
63+
CefRequestHandler::WindowOpenDisposition, bool)
64+
{
65+
return true;
66+
}
67+
68+
bool BrowserDummyClient::OnBeforeBrowse(CefRefPtr<CefBrowser>, CefRefPtr<CefFrame>, CefRefPtr<CefRequest>, bool, bool)
69+
{
70+
return true;
71+
}

browser-dummy-client.hpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#pragma once
2+
3+
#include "cef-headers.hpp"
4+
5+
class BrowserDummyClient : public CefClient,
6+
public CefCommandHandler,
7+
public CefRequestHandler,
8+
public CefLifeSpanHandler {
9+
public:
10+
virtual CefRefPtr<CefCommandHandler> GetCommandHandler() override;
11+
virtual CefRefPtr<CefRequestHandler> GetRequestHandler() override;
12+
virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override;
13+
14+
/* CefCommandHandler */
15+
virtual bool OnChromeCommand(CefRefPtr<CefBrowser> browser, int command_id,
16+
cef_window_open_disposition_t disposition) override;
17+
virtual bool IsChromeAppMenuItemVisible(CefRefPtr<CefBrowser> browser, int command_id) override;
18+
virtual bool IsChromeToolbarButtonVisible(cef_chrome_toolbar_button_type_t button_type) override;
19+
20+
virtual bool IsChromePageActionIconVisible(cef_chrome_page_action_icon_type_t icon_type) override;
21+
22+
virtual bool IsChromeAppMenuItemEnabled(CefRefPtr<CefBrowser> browser, int command_id) override;
23+
24+
/* CefLifeSpanHandler */
25+
virtual bool OnBeforePopup(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,
26+
#if CHROME_VERSION_BUILD >= 6834
27+
int,
28+
#endif
29+
const CefString &target_url, const CefString &target_frame_name,
30+
cef_window_open_disposition_t target_disposition, bool user_gesture,
31+
const CefPopupFeatures &popupFeatures, CefWindowInfo &windowInfo,
32+
CefRefPtr<CefClient> &client, CefBrowserSettings &settings,
33+
CefRefPtr<CefDictionaryValue> &extra_info, bool *no_javascript_access) override;
34+
35+
virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) override;
36+
37+
/* CefRequestHandler */
38+
virtual bool OnOpenURLFromTab(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,
39+
const CefString &target_url,
40+
CefRequestHandler::WindowOpenDisposition target_disposition,
41+
bool user_gesture) override;
42+
43+
virtual bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,
44+
CefRefPtr<CefRequest> request, bool user_gesture, bool is_redirect) override;
45+
46+
IMPLEMENT_REFCOUNTING(BrowserDummyClient);
47+
};

cmake/os-linux.cmake

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ add_executable(OBS::browser-helper ALIAS browser-helper)
1414

1515
target_sources(
1616
browser-helper PRIVATE # cmake-format: sortable
17-
browser-app.cpp browser-app.hpp cef-headers.hpp obs-browser-page/obs-browser-page-main.cpp)
17+
browser-app.cpp browser-app.hpp browser-dummy-client.hpp browser-dummy-client.cpp
18+
cef-headers.hpp obs-browser-page/obs-browser-page-main.cpp)
1819

1920
target_include_directories(browser-helper PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/deps"
2021
"${CMAKE_CURRENT_SOURCE_DIR}/obs-browser-page")

cmake/os-macos.cmake

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ foreach(helper IN LISTS helper_suffixes)
3131

3232
target_sources(
3333
${target_name} PRIVATE # cmake-format: sortable
34-
browser-app.cpp browser-app.hpp cef-headers.hpp obs-browser-page/obs-browser-page-main.cpp)
34+
browser-app.cpp browser-app.hpp browser-dummy-client.hpp browser-dummy-client.cpp
35+
cef-headers.hpp obs-browser-page/obs-browser-page-main.cpp)
3536

3637
target_compile_definitions(${target_name} PRIVATE ENABLE_BROWSER_SHARED_TEXTURE)
3738

cmake/os-windows.cmake

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ add_executable(OBS::browser-helper ALIAS obs-browser-helper)
1010
target_sources(
1111
obs-browser-helper
1212
PRIVATE # cmake-format: sortable
13-
browser-app.cpp browser-app.hpp cef-headers.hpp obs-browser-page.manifest
14-
obs-browser-page/obs-browser-page-main.cpp)
13+
browser-app.cpp browser-app.hpp browser-dummy-client.hpp browser-dummy-client.cpp
14+
cef-headers.hpp obs-browser-page.manifest obs-browser-page/obs-browser-page-main.cpp)
1515

1616
target_include_directories(obs-browser-helper PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/deps"
1717
"${CMAKE_CURRENT_SOURCE_DIR}/obs-browser-page")

0 commit comments

Comments
 (0)