Skip to content

Commit 05ae2ac

Browse files
committed
1.6: Addendum to 2e56bd0 & ec248d4: Further improve CEF implementation, and fix any bugs encountered along the way.
-- NOTE: Different code in SharedUtil.Misc.hpp due to 1.6 backport (C++ 14 constraint) Fixes CEF freeze (between reconnects) introduced by ec248d4 as well, e.g: ERROR: [browser_info_manager.cc] Timeout of new browser info response for frame [id] (has_rfh=1) Regarding the directly above, about the added safety checks; Especially needed now that the Initialise() return logic changed. Previously, on initialization fail, it would leave CEF in a partial state. The new code now properly returns false and cleans up m_pWebCore. Before (buggy code): When Initialise() failed, the code deleted m_pWebCore with SAFE_DELETE Next call to GetWebCore() created a new CWebCore and call CefInitialize() again Problem: CEF only allows calling CefInitialize() ONCE per process - second call causes freeze After (fixed code): Initialise() stores the result in m_bInitialised flag m_pWebCore is NEVER deleted, even if initialization fails Added IsInitialised() method that returns the m_bInitialised flag What this means for callers (Hence all the new checks being added now): - GetWebCore() can now return a non-null pointer that is not usable. Before: If you got a pointer back from GetWebCore(), it was always safe to use After: You need to check if the pointer is nullptr because we now return nullptr when initialization failed Example: IsWebCoreLoaded() now checks both that the pointer exists AND that CEF initialized successfully Every caller of GetWebCore() needs to handle nullptr return value Every method in CClientWebBrowser needs to check m_pWebView ins't null before using it
1 parent e866d70 commit 05ae2ac

26 files changed

+888
-155
lines changed

Client/ceflauncher/CEFLauncher.manifest

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,5 +53,10 @@
5353
</dependency>
5454

5555
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
56+
<security>
57+
<requestedPrivileges>
58+
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
59+
</requestedPrivileges>
60+
</security>
5661
</trustInfo>
5762
</assembly>

Client/ceflauncher_DLL/Main.cpp

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "CCefApp.h"
2121
#include <string>
2222
#include <cef3/cef/include/cef_sandbox_win.h>
23+
#include <SharedUtil.h>
2324

2425
// #define CEF_ENABLE_SANDBOX
2526
#ifdef CEF_ENABLE_SANDBOX
@@ -30,15 +31,18 @@ DWORD WINAPI CheckParentProcessAliveness(LPVOID);
3031

3132
int _declspec(dllexport) InitCEF()
3233
{
33-
// Get absolute CEFLauncher.exe path
34-
TCHAR buffer[MAX_PATH];
35-
GetModuleFileName(NULL, buffer, MAX_PATH);
36-
std::wstring currentFileName(buffer);
37-
38-
// Extract MTA path and set DLL directory (absolute path is required here)
39-
size_t pos = currentFileName.find_last_of(L'\\');
40-
std::wstring mtaPath = currentFileName.substr(0, pos - 3); // Strip "CEF"
41-
SetDllDirectory(mtaPath.c_str());
34+
// Get MTA base directory and set DLL directory to MTA folder
35+
const SString strBaseDir = SharedUtil::GetMTAProcessBaseDir();
36+
37+
if (strBaseDir.empty())
38+
{
39+
// Unable to determine base directory - CEF cannot initialize
40+
return -1;
41+
}
42+
43+
const SString strMTADir = SharedUtil::PathJoin(strBaseDir, "MTA");
44+
45+
SetDllDirectoryW(SharedUtil::FromUTF8(strMTADir));
4246

4347
// Load libcef.dll from the DLL directory
4448
assert(SUCCEEDED(__HrLoadAllImportsForDll("libcef.dll")));
@@ -70,9 +74,10 @@ static DWORD WINAPI CheckParentProcessAliveness(LPVOID)
7074
{
7175
NTSTATUS(NTAPI * queryInformation)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG) = nullptr;
7276

73-
if (HMODULE const ntdll = GetModuleHandleW(L"ntdll.dll"); ntdll != nullptr)
77+
if (auto ntdll = GetModuleHandleW(L"ntdll.dll"); ntdll != nullptr)
7478
{
75-
queryInformation = reinterpret_cast<decltype(queryInformation)>(GetProcAddress(ntdll, "NtQueryInformationProcess"));
79+
auto procAddr = GetProcAddress(ntdll, "NtQueryInformationProcess");
80+
queryInformation = reinterpret_cast<decltype(queryInformation)>(reinterpret_cast<void*>(procAddr));
7681
}
7782

7883
if (queryInformation == nullptr)

Client/ceflauncher_DLL/premake5.lua

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ project "CEFLauncher DLL"
44
targetname "CEFLauncher_DLL"
55
targetdir(buildpath("mta/cef"))
66

7-
includedirs { "../../vendor/cef3/cef" }
7+
includedirs { "../../vendor/cef3/cef", "../../Shared/sdk" }
88
libdirs { "../../vendor/cef3/cef/Release" }
99

1010
defines { "UNICODE", "PSAPI_VERSION=1" }
@@ -19,10 +19,11 @@ project "CEFLauncher DLL"
1919
files {
2020
"premake5.lua",
2121
"*.h",
22-
"*.cpp"
22+
"*.cpp",
23+
"../../Shared/sdk/SharedUtil.cpp"
2324
}
2425

25-
links { "delayimp", "CEF", "libcef.lib", "Psapi.lib", "version.lib", "Winmm.lib", "Ws2_32.lib", "DbgHelp.lib" }
26+
links { "delayimp", "CEF", "libcef.lib", "Psapi.lib", "version.lib", "Winmm.lib", "Ws2_32.lib", "DbgHelp.lib" }
2627
linkoptions { "/DELAYLOAD:libcef.dll" }
2728

2829
filter "architecture:not x86"

Client/cefweb/CWebApp.cpp

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,34 @@ void CWebApp::OnBeforeCommandLineProcessing(const CefString& process_type, CefRe
2929
if (!command_line)
3030
return;
3131

32+
// Add GTA path and MTA base path switches before g_pCore check
33+
// This callback runs in both browser process and subprocess
34+
// In subprocess, g_pCore is NULL, so switches must be added before that check
35+
// Read GTA path from registry
36+
const SString strGTAPath = GetCommonRegistryValue("", "GTA:SA Path");
37+
if (!strGTAPath.empty())
38+
{
39+
// Pass GTA directory path to CEFLauncher subprocess via command-line switch
40+
// CEF's AppendSwitchWithValue handles quoting automatically
41+
command_line->AppendSwitchWithValue("mta-gta-path", strGTAPath);
42+
// AddReportLog only available in browser process where g_pCore exists
43+
}
44+
45+
// Pass MTA base directory path to subprocess
46+
// MTA DLLs are in Bin/MTA but parent process may be elsewhere
47+
const SString strMTAPath = GetMTAProcessBaseDir();
48+
if (!strMTAPath.empty())
49+
{
50+
command_line->AppendSwitchWithValue("mta-base-path", strMTAPath);
51+
}
52+
53+
// Disable AutoDeElevate to allow CEF to run with elevated privileges
54+
// Must be added before g_pCore check to apply to both browser process and subprocess
55+
// https://github.com/chromiumembedded/cef/issues/3960
56+
// https://chromium-review.googlesource.com/c/chromium/src/+/6515318
57+
command_line->AppendSwitch("do-not-de-elevate");
58+
59+
// Browser-process-only settings
3260
if (!g_pCore) [[unlikely]]
3361
return;
3462

@@ -39,11 +67,6 @@ void CWebApp::OnBeforeCommandLineProcessing(const CefString& process_type, CefRe
3967
if (!pWebCore->GetGPUEnabled())
4068
command_line->AppendSwitch("disable-gpu");
4169

42-
// Disable the AutoDeElevate feature to make launching CEF with Admin privileges work.
43-
// https://github.com/chromiumembedded/cef/issues/3960
44-
// https://chromium-review.googlesource.com/c/chromium/src/+/6515318
45-
command_line->AppendSwitch("do-not-de-elevate");
46-
4770
command_line->AppendSwitch("disable-gpu-compositing"); // always disable this, causes issues with official builds
4871

4972
// command_line->AppendSwitch("disable-d3d11");
@@ -108,8 +131,8 @@ CefRefPtr<CefResourceHandler> CWebApp::Create(CefRefPtr<CefBrowser> browser, Cef
108131
}
109132
else
110133
{
111-
SString resourceName = path.substr(0, slashPos);
112-
SString resourcePath = path.substr(slashPos + 1);
134+
const SString resourceName = path.substr(0, slashPos);
135+
const SString resourcePath = path.substr(slashPos + 1);
113136

114137
if (resourcePath.empty())
115138
{
@@ -137,7 +160,7 @@ CefRefPtr<CefResourceHandler> CWebApp::Create(CefRefPtr<CefBrowser> browser, Cef
137160

138161
if (urlParts.query.str)
139162
{
140-
SString strGet = UTF16ToMbUTF8(urlParts.query.str);
163+
const SString strGet = UTF16ToMbUTF8(urlParts.query.str);
141164
std::vector<SString> vecTmp;
142165
vecTmp.reserve(8); // Reserve space for common query parameter count
143166
strGet.Split("&", vecTmp);
@@ -153,13 +176,13 @@ CefRefPtr<CefResourceHandler> CWebApp::Create(CefRefPtr<CefBrowser> browser, Cef
153176
}
154177

155178
CefPostData::ElementVector vecPostElements;
156-
if (auto postData = request->GetPostData(); postData)
179+
if (const auto postData = request->GetPostData(); postData)
157180
{
158181
postData->GetElements(vecPostElements);
159182

160183
SString key;
161184
SString value;
162-
for (auto&& post : vecPostElements)
185+
for (const auto& post : vecPostElements)
163186
{
164187
// Limit to 5MiB and allow byte data only
165188
constexpr size_t MAX_POST_SIZE = 5 * 1024 * 1024;
@@ -168,12 +191,12 @@ CefRefPtr<CefResourceHandler> CWebApp::Create(CefRefPtr<CefBrowser> browser, Cef
168191
continue;
169192

170193
// Make string from buffer
171-
auto buffer = std::make_unique<char[]>(bytesCount);
194+
const auto buffer = std::make_unique<char[]>(bytesCount);
172195
// Verify GetBytes succeeded before using buffer
173-
size_t bytesRead = post->GetBytes(bytesCount, buffer.get());
196+
const size_t bytesRead = post->GetBytes(bytesCount, buffer.get());
174197
if (bytesRead != bytesCount)
175198
continue;
176-
SStringX postParam(buffer.get(), bytesCount);
199+
const SStringX postParam(buffer.get(), bytesCount);
177200

178201
// Parse POST data into vector
179202
std::vector<SString> vecTmp;
@@ -197,7 +220,7 @@ CefRefPtr<CefResourceHandler> CWebApp::Create(CefRefPtr<CefBrowser> browser, Cef
197220
{
198221
// Calculate MTA resource path
199222
static constexpr auto LOCAL = "local";
200-
path = (resourceName != LOCAL) ? ":" + resourceName + "/" + resourcePath : resourcePath;
223+
path = (resourceName != LOCAL) ? SString(":" + resourceName + "/" + resourcePath) : resourcePath;
201224

202225
// Calculate absolute path
203226
if (!pWebView->GetFullPathFromLocal(path))

0 commit comments

Comments
 (0)