mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
win: Add bootstrap[c].exe for sandbox integration (see #3824)
Replace cef_sandbox.lib usage with bootstrap executables. See the SandboxSetup Wiki page for details.
This commit is contained in:
215
BUILD.gn
215
BUILD.gn
@ -319,6 +319,16 @@ group("cef") {
|
||||
":libcef_static_unittests",
|
||||
]
|
||||
|
||||
if (is_win) {
|
||||
deps += [
|
||||
":bootstrap",
|
||||
":bootstrapc",
|
||||
":cefclient_dll",
|
||||
":cefsimple_dll",
|
||||
":ceftests_dll",
|
||||
]
|
||||
}
|
||||
|
||||
if (!is_linux || ozone_platform_x11) {
|
||||
deps += [ ":cefclient" ]
|
||||
}
|
||||
@ -992,6 +1002,9 @@ source_set("libcef_static") {
|
||||
"libcef/browser/native/browser_platform_delegate_native_win.h",
|
||||
"libcef/browser/osr/browser_platform_delegate_osr_win.cc",
|
||||
"libcef/browser/osr/browser_platform_delegate_osr_win.h",
|
||||
"libcef/browser/preferred_stack_size_win.inc",
|
||||
"libcef_dll/bootstrap/bootstrap_util_win.cc",
|
||||
"libcef_dll/bootstrap/bootstrap_util_win.h",
|
||||
]
|
||||
|
||||
deps += [
|
||||
@ -1228,6 +1241,73 @@ if (is_mac) {
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# bootstrap target.
|
||||
#
|
||||
|
||||
if (is_win) {
|
||||
bootstrap_sources = includes_common +
|
||||
includes_win + [
|
||||
"libcef_dll/bootstrap/bootstrap_util_win.cc",
|
||||
"libcef_dll/bootstrap/bootstrap_util_win.h",
|
||||
"libcef_dll/bootstrap/bootstrap_win.cc",
|
||||
"libcef_dll/bootstrap/win/bootstrap.rc",
|
||||
"libcef_dll/bootstrap/win/resource.h",
|
||||
"libcef/browser/preferred_stack_size_win.inc",
|
||||
]
|
||||
|
||||
bootstrap_deps = [
|
||||
":cef_sandbox",
|
||||
":make_version_header",
|
||||
"//base",
|
||||
"//build/win:default_exe_manifest",
|
||||
]
|
||||
|
||||
# Windows application that initializes the sandbox and then passes
|
||||
# execution to a client-provided DLL.
|
||||
executable("bootstrap") {
|
||||
# Necessary because the libcef target is testonly.
|
||||
testonly = true
|
||||
|
||||
sources = bootstrap_sources
|
||||
deps = bootstrap_deps
|
||||
|
||||
configs += [ ":libcef_includes_config" ]
|
||||
|
||||
# Set /SUBSYSTEM:WINDOWS.
|
||||
configs -= [ "//build/config/win:console" ]
|
||||
configs += [ "//build/config/win:windowed" ]
|
||||
|
||||
# Delay-load as many DLLs as possible for sandbox and startup perf
|
||||
# improvements.
|
||||
configs += [ "//build/config/win:delayloads" ]
|
||||
|
||||
defines = [
|
||||
"CEF_BUILD_BOOTSTRAP",
|
||||
]
|
||||
}
|
||||
|
||||
# Like "bootstrap", but as a console application.
|
||||
executable("bootstrapc") {
|
||||
# Necessary because the libcef target is testonly.
|
||||
testonly = true
|
||||
|
||||
sources = bootstrap_sources
|
||||
deps = bootstrap_deps
|
||||
|
||||
configs += [ ":libcef_includes_config" ]
|
||||
|
||||
# Delay-load as many DLLs as possible for sandbox and startup perf
|
||||
# improvements.
|
||||
configs += [ "//build/config/win:delayloads" ]
|
||||
|
||||
defines = [
|
||||
"CEF_BUILD_BOOTSTRAP",
|
||||
"CEF_BUILD_BOOTSTRAP_CONSOLE",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Resource grit/pack targets.
|
||||
#
|
||||
@ -2224,6 +2304,66 @@ if (is_mac) {
|
||||
}
|
||||
}
|
||||
|
||||
if (is_win) {
|
||||
# Like the "cefclient" executable target, but building a DLL to be loaded by
|
||||
# bootstrap.exe.
|
||||
shared_library("cefclient_dll") {
|
||||
# Necessary because the libcef target is testonly.
|
||||
testonly = true
|
||||
|
||||
output_name = "cefclient"
|
||||
|
||||
sources = includes_common +
|
||||
includes_win +
|
||||
gypi_paths2.includes_wrapper +
|
||||
gypi_paths2.shared_sources_browser +
|
||||
gypi_paths2.shared_sources_common +
|
||||
gypi_paths2.shared_sources_renderer +
|
||||
gypi_paths2.shared_sources_win +
|
||||
gypi_paths2.cefclient_sources_browser +
|
||||
gypi_paths2.cefclient_sources_common +
|
||||
gypi_paths2.cefclient_sources_renderer +
|
||||
gypi_paths2.cefclient_sources_win +
|
||||
gypi_paths2.cefclient_sources_resources_win_rc
|
||||
|
||||
deps = [
|
||||
":bootstrap",
|
||||
":libcef",
|
||||
":libcef_dll_wrapper",
|
||||
]
|
||||
|
||||
defines = [
|
||||
"CEF_USE_ATL",
|
||||
"CEF_USE_BOOTSTRAP",
|
||||
]
|
||||
|
||||
# Delay-load as many DLLs as possible for sandbox and startup perf
|
||||
# improvements.
|
||||
configs += [ "//build/config/win:delayloads" ]
|
||||
|
||||
libs = [
|
||||
"comctl32.lib",
|
||||
"d3d11.lib",
|
||||
"imm32.lib",
|
||||
"oleacc.lib",
|
||||
"rpcrt4.lib",
|
||||
"shlwapi.lib",
|
||||
]
|
||||
|
||||
if (target_cpu != "arm64") {
|
||||
libs += [
|
||||
"glu32.lib",
|
||||
"opengl32.lib",
|
||||
]
|
||||
ldflags = [
|
||||
"/DELAYLOAD:glu32.dll",
|
||||
"/DELAYLOAD:oleaut32.dll",
|
||||
"/DELAYLOAD:opengl32.dll",
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# cefsimple targets.
|
||||
@ -2288,6 +2428,44 @@ if (is_mac) {
|
||||
}
|
||||
}
|
||||
|
||||
if (is_win) {
|
||||
# Like the "cefsimple" executable target, but building a DLL to be loaded by
|
||||
# bootstrap.exe.
|
||||
shared_library("cefsimple_dll") {
|
||||
# Necessary because the libcef target is testonly.
|
||||
testonly = true
|
||||
|
||||
output_name = "cefsimple"
|
||||
|
||||
sources = includes_common +
|
||||
includes_win +
|
||||
gypi_paths2.includes_wrapper +
|
||||
gypi_paths2.cefsimple_sources_common +
|
||||
gypi_paths2.cefsimple_sources_win +
|
||||
gypi_paths2.cefsimple_sources_resources_win_rc
|
||||
|
||||
deps = [
|
||||
":bootstrap",
|
||||
":libcef",
|
||||
":libcef_dll_wrapper",
|
||||
]
|
||||
|
||||
defines = [
|
||||
"CEF_USE_BOOTSTRAP",
|
||||
]
|
||||
|
||||
# Delay-load as many DLLs as possible for sandbox and startup perf
|
||||
# improvements.
|
||||
configs += [ "//build/config/win:delayloads" ]
|
||||
|
||||
libs = [
|
||||
"comctl32.lib",
|
||||
"shlwapi.lib",
|
||||
"rpcrt4.lib",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# ceftests targets.
|
||||
@ -2361,4 +2539,41 @@ if (is_mac) {
|
||||
configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ]
|
||||
}
|
||||
}
|
||||
|
||||
if (is_win) {
|
||||
# Like the "ceftests" executable target, but building a DLL to be loaded by
|
||||
# bootstrapc.exe.
|
||||
shared_library("ceftests_dll") {
|
||||
testonly = true
|
||||
|
||||
output_name = "ceftests"
|
||||
|
||||
sources = includes_common +
|
||||
gypi_paths2.includes_wrapper +
|
||||
gypi_paths2.shared_sources_browser +
|
||||
gypi_paths2.shared_sources_common +
|
||||
gypi_paths2.shared_sources_renderer +
|
||||
gypi_paths2.shared_sources_win +
|
||||
gypi_paths2.ceftests_sources_common +
|
||||
gypi_paths2.ceftests_sources_win +
|
||||
gypi_paths2.ceftests_sources_resources_win_rc
|
||||
|
||||
deps = [
|
||||
":bootstrapc",
|
||||
":libcef",
|
||||
":libcef_dll_wrapper",
|
||||
":gtest_teamcity",
|
||||
"//testing/gtest",
|
||||
]
|
||||
|
||||
defines = [
|
||||
"CEF_USE_BOOTSTRAP",
|
||||
"CEF_TESTS_IN_SRC_DIRECTORY",
|
||||
]
|
||||
|
||||
# Delay-load as many DLLs as possible for sandbox and startup perf
|
||||
# improvements.
|
||||
configs += [ "//build/config/win:delayloads" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,10 @@
|
||||
|
||||
#if defined(OS_WIN)
|
||||
|
||||
#if !defined(GENERATING_CEF_API_HASH)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -49,13 +53,34 @@ extern "C" {
|
||||
/// http://www.chromium.org/developers/design-documents/sandbox for complete
|
||||
/// details.
|
||||
///
|
||||
/// To enable the sandbox on Windows the following requirements must be met:
|
||||
/// 1. Use the same executable for the browser process and all sub-processes.
|
||||
/// 2. Link the executable with the cef_sandbox static library.
|
||||
/// 3. Call the cef_sandbox_info_create() function from within the executable
|
||||
/// (not from a separate DLL) and pass the resulting pointer into both the
|
||||
/// CefExecuteProcess() and CefInitialize() functions via the
|
||||
/// |windows_sandbox_info| parameter.
|
||||
/// To enable the sandbox on Windows the same executable must be used for all
|
||||
/// processes (browser process and sub-processes). This executable must link the
|
||||
/// cef_sandbox static library and initialize the sandbox by calling
|
||||
/// cef_sandbox_info_create. The resulting |sandbox_info| value must then be
|
||||
/// passed to CefExecuteProcess and CefInitialize.
|
||||
///
|
||||
/// Beginning with M138 the cef_sandbox static library can only be linked with
|
||||
/// applications built as part of the CEF/Chromium build. This is due to
|
||||
/// unavoidable dependencies on Chromium's bundled Clang/LLVM/libc++ toolchain.
|
||||
/// Client applications therefore have 3 options for sandbox integration:
|
||||
///
|
||||
/// 1. Build the client application (or a custom bootstrap executable) as part
|
||||
/// of the CEF/Chromium build using Chromium's bundled Clang/LLVM/libc++
|
||||
/// toolchain. For details of this option see
|
||||
/// https://bitbucket.org/chromiumembedded/cef/wiki/SandboxSetup.md
|
||||
/// 2. Build the client application as a DLL using any toolchain and run using
|
||||
/// the provided bootstrap.exe or bootstrapc.exe. The DLL implements
|
||||
/// RunWinMain or RunConsoleMain respectively and gets passed the
|
||||
/// |sandbox_info| parameter which it then forwards to CefExecuteProcess
|
||||
/// and CefInitialize. The provided bootstrap executables can optionally be
|
||||
/// renamed or modified [1] to meet client branding needs.
|
||||
/// 3. Build the client application as an executable using any toolchain with
|
||||
/// the sandbox disabled. Pass nullptr as the |sandbox_info| parameter to
|
||||
/// CefExecuteProcess and CefInitialize.
|
||||
///
|
||||
/// [1] Embedded executable resources such as icons and file properties can be
|
||||
/// modified using Visual Studio or Resource Hacker tools. Be sure to code
|
||||
/// sign all binaries after modification and before distribution to users.
|
||||
///
|
||||
|
||||
///
|
||||
@ -88,6 +113,37 @@ class CefScopedSandboxInfo {
|
||||
};
|
||||
#endif // __cplusplus
|
||||
|
||||
#if defined(CEF_BUILD_BOOTSTRAP)
|
||||
#define CEF_BOOTSTRAP_EXPORT __declspec(dllimport)
|
||||
#else
|
||||
#define CEF_BOOTSTRAP_EXPORT __declspec(dllexport)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
///
|
||||
/// Entry point to be implemented by client DLLs using bootstrap.exe for
|
||||
/// windows (/SUBSYSTEM:WINDOWS) applications.
|
||||
///
|
||||
CEF_BOOTSTRAP_EXPORT int RunWinMain(HINSTANCE hInstance,
|
||||
LPTSTR lpCmdLine,
|
||||
int nCmdShow,
|
||||
void* sandbox_info);
|
||||
|
||||
///
|
||||
/// Entry point to be implemented by client DLLs using bootstrapc.exe for
|
||||
/// console (/SUBSYSTEM:CONSOLE) applications.
|
||||
///
|
||||
CEF_BOOTSTRAP_EXPORT int RunConsoleMain(int argc,
|
||||
char* argv[],
|
||||
void* sandbox_info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // defined(OS_WIN)
|
||||
|
||||
#endif // CEF_INCLUDE_CEF_SANDBOX_WIN_H_
|
||||
|
@ -41,6 +41,8 @@
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "include/internal/cef_export.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -50,6 +50,10 @@
|
||||
#include "cef/libcef/browser/chrome/chrome_web_contents_view_delegate_cef.h"
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
#include "cef/libcef_dll/bootstrap/bootstrap_util_win.h"
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
class CefSelectClientCertificateCallbackImpl
|
||||
@ -214,6 +218,17 @@ void ChromeContentBrowserClientCef::AppendExtraCommandLineSwitches(
|
||||
command_line->CopySwitchesFrom(*browser_cmd, kSwitchNames);
|
||||
}
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
{
|
||||
const auto& module_value = bootstrap_util::GetValidatedModuleValue(
|
||||
*browser_cmd, bootstrap_util::GetExePath());
|
||||
if (!module_value.empty()) {
|
||||
command_line->AppendSwitchNative(bootstrap_util::switches::kModule,
|
||||
module_value);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
const std::string& process_type =
|
||||
command_line->GetSwitchValueASCII(switches::kProcessType);
|
||||
|
||||
|
@ -22,9 +22,9 @@
|
||||
#include "ui/base/ui_base_switches.h"
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
#include "base/debug/alias.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "cef/include/internal/cef_win.h"
|
||||
#include "cef/libcef/browser/preferred_stack_size_win.inc"
|
||||
#include "chrome/chrome_elf/chrome_elf_main.h"
|
||||
#include "chrome/install_static/initialize_from_primary_module.h"
|
||||
#endif
|
||||
@ -185,110 +185,6 @@ base::FilePath NormalizeCachePathAndSet(cef_string_t& path_str,
|
||||
return path;
|
||||
}
|
||||
|
||||
// Based on chrome/app/chrome_exe_main_win.cc.
|
||||
// In 32-bit builds, the main thread starts with the default (small) stack size.
|
||||
// The ARCH_CPU_32_BITS blocks here and below are in support of moving the main
|
||||
// thread to a fiber with a larger stack size.
|
||||
#if BUILDFLAG(IS_WIN) && defined(ARCH_CPU_32_BITS)
|
||||
// The information needed to transfer control to the large-stack fiber and later
|
||||
// pass the main routine's exit code back to the small-stack fiber prior to
|
||||
// termination.
|
||||
struct FiberState {
|
||||
FiberState(wWinMainPtr wWinMain,
|
||||
HINSTANCE hInstance,
|
||||
LPWSTR lpCmdLine,
|
||||
int nCmdShow) {
|
||||
this->wWinMain = wWinMain;
|
||||
this->hInstance = hInstance;
|
||||
this->lpCmdLine = lpCmdLine;
|
||||
this->nCmdShow = nCmdShow;
|
||||
}
|
||||
|
||||
FiberState(mainPtr main, int argc, char** argv) {
|
||||
this->main = main;
|
||||
this->argc = argc;
|
||||
this->argv = argv;
|
||||
}
|
||||
|
||||
wWinMainPtr wWinMain = nullptr;
|
||||
HINSTANCE hInstance;
|
||||
LPWSTR lpCmdLine;
|
||||
int nCmdShow;
|
||||
|
||||
mainPtr main = nullptr;
|
||||
int argc;
|
||||
char** argv;
|
||||
|
||||
LPVOID original_fiber;
|
||||
int fiber_result;
|
||||
};
|
||||
|
||||
// A PFIBER_START_ROUTINE function run on a large-stack fiber that calls the
|
||||
// main routine, stores its return value, and returns control to the small-stack
|
||||
// fiber. |params| must be a pointer to a FiberState struct.
|
||||
void WINAPI FiberBinder(void* params) {
|
||||
auto* fiber_state = static_cast<FiberState*>(params);
|
||||
// Call the main routine from the fiber. Reusing the entry point minimizes
|
||||
// confusion when examining call stacks in crash reports - seeing wWinMain on
|
||||
// the stack is a handy hint that this is the main thread of the process.
|
||||
if (fiber_state->main) {
|
||||
fiber_state->fiber_result =
|
||||
fiber_state->main(fiber_state->argc, fiber_state->argv);
|
||||
} else {
|
||||
fiber_state->fiber_result =
|
||||
fiber_state->wWinMain(fiber_state->hInstance, nullptr,
|
||||
fiber_state->lpCmdLine, fiber_state->nCmdShow);
|
||||
}
|
||||
|
||||
// Switch back to the main thread to exit.
|
||||
::SwitchToFiber(fiber_state->original_fiber);
|
||||
}
|
||||
|
||||
int RunMainWithPreferredStackSize(FiberState& fiber_state) {
|
||||
enum class FiberStatus { kConvertFailed, kCreateFiberFailed, kSuccess };
|
||||
FiberStatus fiber_status = FiberStatus::kSuccess;
|
||||
// GetLastError result if fiber conversion failed.
|
||||
DWORD fiber_error = ERROR_SUCCESS;
|
||||
if (!::IsThreadAFiber()) {
|
||||
// Make the main thread's stack size 4 MiB so that it has roughly the same
|
||||
// effective size as the 64-bit build's 8 MiB stack.
|
||||
constexpr size_t kStackSize = 4 * 1024 * 1024; // 4 MiB
|
||||
// Leak the fiber on exit.
|
||||
LPVOID original_fiber =
|
||||
::ConvertThreadToFiberEx(nullptr, FIBER_FLAG_FLOAT_SWITCH);
|
||||
if (original_fiber) {
|
||||
fiber_state.original_fiber = original_fiber;
|
||||
// Create a fiber with a bigger stack and switch to it. Leak the fiber on
|
||||
// exit.
|
||||
LPVOID big_stack_fiber = ::CreateFiberEx(
|
||||
0, kStackSize, FIBER_FLAG_FLOAT_SWITCH, FiberBinder, &fiber_state);
|
||||
if (big_stack_fiber) {
|
||||
::SwitchToFiber(big_stack_fiber);
|
||||
// The fibers must be cleaned up to avoid obscure TLS-related shutdown
|
||||
// crashes.
|
||||
::DeleteFiber(big_stack_fiber);
|
||||
::ConvertFiberToThread();
|
||||
// Control returns here after CEF has finished running on FiberMain.
|
||||
return fiber_state.fiber_result;
|
||||
}
|
||||
fiber_status = FiberStatus::kCreateFiberFailed;
|
||||
} else {
|
||||
fiber_status = FiberStatus::kConvertFailed;
|
||||
}
|
||||
// If we reach here then creating and switching to a fiber has failed. This
|
||||
// probably means we are low on memory and will soon crash. Try to report
|
||||
// this error once crash reporting is initialized.
|
||||
fiber_error = ::GetLastError();
|
||||
base::debug::Alias(&fiber_error);
|
||||
}
|
||||
|
||||
// If we are already a fiber then continue normal execution.
|
||||
// Intentionally crash if converting to a fiber failed.
|
||||
CHECK_EQ(fiber_status, FiberStatus::kSuccess);
|
||||
return -1;
|
||||
}
|
||||
#endif // BUILDFLAG(IS_WIN) && defined(ARCH_CPU_32_BITS)
|
||||
|
||||
} // namespace
|
||||
|
||||
NO_STACK_PROTECTOR
|
||||
@ -418,23 +314,6 @@ void CefQuitMessageLoop() {
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
|
||||
#if defined(ARCH_CPU_32_BITS)
|
||||
int CefRunWinMainWithPreferredStackSize(wWinMainPtr wWinMain,
|
||||
HINSTANCE hInstance,
|
||||
LPWSTR lpCmdLine,
|
||||
int nCmdShow) {
|
||||
CHECK(wWinMain && hInstance);
|
||||
FiberState fiber_state(wWinMain, hInstance, lpCmdLine, nCmdShow);
|
||||
return RunMainWithPreferredStackSize(fiber_state);
|
||||
}
|
||||
|
||||
int CefRunMainWithPreferredStackSize(mainPtr main, int argc, char* argv[]) {
|
||||
CHECK(main);
|
||||
FiberState fiber_state(main, argc, argv);
|
||||
return RunMainWithPreferredStackSize(fiber_state);
|
||||
}
|
||||
#endif // defined(ARCH_CPU_32_BITS)
|
||||
|
||||
void CefSetOSModalLoop(bool osModalLoop) {
|
||||
// Verify that the context is in a valid state.
|
||||
if (!CONTEXT_STATE_VALID()) {
|
||||
|
129
libcef/browser/preferred_stack_size_win.inc
Normal file
129
libcef/browser/preferred_stack_size_win.inc
Normal file
@ -0,0 +1,129 @@
|
||||
#include "build/build_config.h"
|
||||
|
||||
// Based on chrome/app/chrome_exe_main_win.cc.
|
||||
// In 32-bit builds, the main thread starts with the default (small) stack size.
|
||||
// The ARCH_CPU_32_BITS blocks here and below are in support of moving the main
|
||||
// thread to a fiber with a larger stack size.
|
||||
#if BUILDFLAG(IS_WIN) && defined(ARCH_CPU_32_BITS)
|
||||
|
||||
#include "base/debug/alias.h"
|
||||
#include "include/internal/cef_app_win.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// The information needed to transfer control to the large-stack fiber and later
|
||||
// pass the main routine's exit code back to the small-stack fiber prior to
|
||||
// termination.
|
||||
struct FiberState {
|
||||
FiberState(wWinMainPtr wWinMain,
|
||||
HINSTANCE hInstance,
|
||||
LPWSTR lpCmdLine,
|
||||
int nCmdShow) {
|
||||
this->wWinMain = wWinMain;
|
||||
this->hInstance = hInstance;
|
||||
this->lpCmdLine = lpCmdLine;
|
||||
this->nCmdShow = nCmdShow;
|
||||
}
|
||||
|
||||
FiberState(mainPtr main, int argc, char** argv) {
|
||||
this->main = main;
|
||||
this->argc = argc;
|
||||
this->argv = argv;
|
||||
}
|
||||
|
||||
wWinMainPtr wWinMain = nullptr;
|
||||
HINSTANCE hInstance;
|
||||
LPWSTR lpCmdLine;
|
||||
int nCmdShow;
|
||||
|
||||
mainPtr main = nullptr;
|
||||
int argc;
|
||||
char** argv;
|
||||
|
||||
LPVOID original_fiber;
|
||||
int fiber_result;
|
||||
};
|
||||
|
||||
// A PFIBER_START_ROUTINE function run on a large-stack fiber that calls the
|
||||
// main routine, stores its return value, and returns control to the small-stack
|
||||
// fiber. |params| must be a pointer to a FiberState struct.
|
||||
void WINAPI FiberBinder(void* params) {
|
||||
auto* fiber_state = static_cast<FiberState*>(params);
|
||||
// Call the main routine from the fiber. Reusing the entry point minimizes
|
||||
// confusion when examining call stacks in crash reports - seeing wWinMain on
|
||||
// the stack is a handy hint that this is the main thread of the process.
|
||||
if (fiber_state->main) {
|
||||
fiber_state->fiber_result =
|
||||
fiber_state->main(fiber_state->argc, fiber_state->argv);
|
||||
} else {
|
||||
fiber_state->fiber_result =
|
||||
fiber_state->wWinMain(fiber_state->hInstance, nullptr,
|
||||
fiber_state->lpCmdLine, fiber_state->nCmdShow);
|
||||
}
|
||||
|
||||
// Switch back to the main thread to exit.
|
||||
::SwitchToFiber(fiber_state->original_fiber);
|
||||
}
|
||||
|
||||
int RunMainWithPreferredStackSize(FiberState& fiber_state) {
|
||||
enum class FiberStatus { kConvertFailed, kCreateFiberFailed, kSuccess };
|
||||
FiberStatus fiber_status = FiberStatus::kSuccess;
|
||||
// GetLastError result if fiber conversion failed.
|
||||
DWORD fiber_error = ERROR_SUCCESS;
|
||||
if (!::IsThreadAFiber()) {
|
||||
// Make the main thread's stack size 4 MiB so that it has roughly the same
|
||||
// effective size as the 64-bit build's 8 MiB stack.
|
||||
constexpr size_t kStackSize = 4 * 1024 * 1024; // 4 MiB
|
||||
// Leak the fiber on exit.
|
||||
LPVOID original_fiber =
|
||||
::ConvertThreadToFiberEx(nullptr, FIBER_FLAG_FLOAT_SWITCH);
|
||||
if (original_fiber) {
|
||||
fiber_state.original_fiber = original_fiber;
|
||||
// Create a fiber with a bigger stack and switch to it. Leak the fiber on
|
||||
// exit.
|
||||
LPVOID big_stack_fiber = ::CreateFiberEx(
|
||||
0, kStackSize, FIBER_FLAG_FLOAT_SWITCH, FiberBinder, &fiber_state);
|
||||
if (big_stack_fiber) {
|
||||
::SwitchToFiber(big_stack_fiber);
|
||||
// The fibers must be cleaned up to avoid obscure TLS-related shutdown
|
||||
// crashes.
|
||||
::DeleteFiber(big_stack_fiber);
|
||||
::ConvertFiberToThread();
|
||||
// Control returns here after CEF has finished running on FiberMain.
|
||||
return fiber_state.fiber_result;
|
||||
}
|
||||
fiber_status = FiberStatus::kCreateFiberFailed;
|
||||
} else {
|
||||
fiber_status = FiberStatus::kConvertFailed;
|
||||
}
|
||||
// If we reach here then creating and switching to a fiber has failed. This
|
||||
// probably means we are low on memory and will soon crash. Try to report
|
||||
// this error once crash reporting is initialized.
|
||||
fiber_error = ::GetLastError();
|
||||
base::debug::Alias(&fiber_error);
|
||||
}
|
||||
|
||||
// If we are already a fiber then continue normal execution.
|
||||
// Intentionally crash if converting to a fiber failed.
|
||||
CHECK_EQ(fiber_status, FiberStatus::kSuccess);
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int CefRunWinMainWithPreferredStackSize(wWinMainPtr wWinMain,
|
||||
HINSTANCE hInstance,
|
||||
LPWSTR lpCmdLine,
|
||||
int nCmdShow) {
|
||||
CHECK(wWinMain && hInstance);
|
||||
FiberState fiber_state(wWinMain, hInstance, lpCmdLine, nCmdShow);
|
||||
return RunMainWithPreferredStackSize(fiber_state);
|
||||
}
|
||||
|
||||
int CefRunMainWithPreferredStackSize(mainPtr main, int argc, char* argv[]) {
|
||||
CHECK(main);
|
||||
FiberState fiber_state(main, argc, argv);
|
||||
return RunMainWithPreferredStackSize(fiber_state);
|
||||
}
|
||||
|
||||
#endif // BUILDFLAG(IS_WIN) && defined(ARCH_CPU_32_BITS)
|
82
libcef_dll/bootstrap/bootstrap_util_win.cc
Normal file
82
libcef_dll/bootstrap/bootstrap_util_win.cc
Normal file
@ -0,0 +1,82 @@
|
||||
// Copyright (c) 2025 The Chromium Embedded Framework Authors. All rights
|
||||
// reserved. Use of this source code is governed by a BSD-style license that
|
||||
// can be found in the LICENSE file.
|
||||
|
||||
#include "cef/libcef_dll/bootstrap/bootstrap_util_win.h"
|
||||
|
||||
#include "base/check_op.h"
|
||||
#include "base/command_line.h"
|
||||
|
||||
namespace bootstrap_util {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr wchar_t kWindowsSelfName[] = TEXT("bootstrap");
|
||||
constexpr wchar_t kConsoleSelfName[] = TEXT("bootstrapc");
|
||||
|
||||
// Returns the file name only without extension, if any.
|
||||
inline std::wstring NamePart(const base::FilePath& path) {
|
||||
return path.BaseName().RemoveExtension().value();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool IsDefaultExeName(const std::wstring& name) {
|
||||
return base::FilePath::CompareEqualIgnoreCase(name, kWindowsSelfName) ||
|
||||
base::FilePath::CompareEqualIgnoreCase(name, kConsoleSelfName);
|
||||
}
|
||||
|
||||
std::wstring GetModuleValue(const base::CommandLine& command_line) {
|
||||
if (command_line.HasSwitch(switches::kModule)) {
|
||||
const auto& value = command_line.GetSwitchValuePath(switches::kModule);
|
||||
if (!value.empty()) {
|
||||
return NamePart(value);
|
||||
}
|
||||
}
|
||||
|
||||
return std::wstring();
|
||||
}
|
||||
|
||||
base::FilePath GetExePath() {
|
||||
HMODULE hModule = ::GetModuleHandle(nullptr);
|
||||
CHECK(hModule);
|
||||
return GetModulePath(hModule);
|
||||
}
|
||||
|
||||
base::FilePath GetModulePath(HMODULE module) {
|
||||
wchar_t buffer[MAX_PATH];
|
||||
DWORD length = ::GetModuleFileName(module, buffer, MAX_PATH);
|
||||
CHECK_NE(length, 0U);
|
||||
CHECK_LT(length, static_cast<DWORD>(MAX_PATH));
|
||||
|
||||
return base::FilePath(buffer);
|
||||
}
|
||||
|
||||
std::wstring GetValidatedModuleValue(const base::CommandLine& command_line,
|
||||
const base::FilePath& exe_path) {
|
||||
// Allow module value configuration if the bootstrap executable has the
|
||||
// default name.
|
||||
const auto& value = GetModuleValue(command_line);
|
||||
if (!value.empty() && IsDefaultExeName(NamePart(exe_path))) {
|
||||
return value;
|
||||
}
|
||||
return std::wstring();
|
||||
}
|
||||
|
||||
std::wstring GetDefaultModuleValue(const base::FilePath& exe_path) {
|
||||
return NamePart(exe_path);
|
||||
}
|
||||
|
||||
bool IsModulePathAllowed(HMODULE module, const base::FilePath& exe_path) {
|
||||
// Allow any module path if the bootstrap executable has the default name.
|
||||
if (IsDefaultExeName(NamePart(exe_path))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto& module_path = GetModulePath(module);
|
||||
|
||||
// Module must be at the same path as the executable.
|
||||
return module_path.DirName() == exe_path.DirName();
|
||||
}
|
||||
|
||||
} // namespace bootstrap_util
|
51
libcef_dll/bootstrap/bootstrap_util_win.h
Normal file
51
libcef_dll/bootstrap/bootstrap_util_win.h
Normal file
@ -0,0 +1,51 @@
|
||||
// Copyright (c) 2025 The Chromium Embedded Framework Authors. All rights
|
||||
// reserved. Use of this source code is governed by a BSD-style license that
|
||||
// can be found in the LICENSE file.
|
||||
|
||||
#ifndef CEF_LIBCEF_DLL_BOOTSTRAP_BOOTSTRAP_UTIL_WIN_H_
|
||||
#define CEF_LIBCEF_DLL_BOOTSTRAP_BOOTSTRAP_UTIL_WIN_H_
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/files/file_path.h"
|
||||
|
||||
namespace base {
|
||||
class CommandLine;
|
||||
}
|
||||
|
||||
namespace bootstrap_util {
|
||||
|
||||
namespace switches {
|
||||
inline constexpr char kModule[] = "module";
|
||||
}
|
||||
|
||||
// Returns true if |name| is one of the default bootstrap executable names.
|
||||
bool IsDefaultExeName(const std::wstring& name);
|
||||
|
||||
// Returns the command-line configured module value without validation.
|
||||
std::wstring GetModuleValue(const base::CommandLine& command_line);
|
||||
|
||||
// The following functions can only be called in unsandboxed processes.
|
||||
|
||||
// Returns the fully qualified file path for the executable module.
|
||||
base::FilePath GetExePath();
|
||||
|
||||
// Returns the fully qualified file path for |module|.
|
||||
base::FilePath GetModulePath(HMODULE module);
|
||||
|
||||
// Returns the command-line configured module value if it passes validation.
|
||||
std::wstring GetValidatedModuleValue(const base::CommandLine& command_line,
|
||||
const base::FilePath& exe_path);
|
||||
|
||||
// Returns the default module name (executable name without extension).
|
||||
std::wstring GetDefaultModuleValue(const base::FilePath& exe_path);
|
||||
|
||||
// Returns true if loading |module| is allowed.
|
||||
bool IsModulePathAllowed(HMODULE module, const base::FilePath& exe_path);
|
||||
|
||||
} // namespace bootstrap_util
|
||||
|
||||
#endif // CEF_LIBCEF_DLL_BOOTSTRAP_BOOTSTRAP_UTIL_WIN_H_
|
179
libcef_dll/bootstrap/bootstrap_win.cc
Normal file
179
libcef_dll/bootstrap/bootstrap_win.cc
Normal file
@ -0,0 +1,179 @@
|
||||
// Copyright (c) 2025 The Chromium Embedded Framework Authors. All rights
|
||||
// reserved. Use of this source code is governed by a BSD-style license that
|
||||
// can be found in the LICENSE file.
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "base/command_line.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/process/process_info.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "cef/include/cef_sandbox_win.h"
|
||||
#include "cef/libcef/browser/preferred_stack_size_win.inc"
|
||||
#include "cef/libcef_dll/bootstrap/bootstrap_util_win.h"
|
||||
#include "cef/libcef_dll/bootstrap/win/resource.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// Load a string from the string table in bootstrap.rc.
|
||||
std::wstring LoadString(int string_id) {
|
||||
const int kMaxSize = 100;
|
||||
TCHAR buff[kMaxSize] = {0};
|
||||
::LoadString(::GetModuleHandle(nullptr), string_id, buff, kMaxSize);
|
||||
return buff;
|
||||
}
|
||||
|
||||
// Replace $1-$2-$3..$9 in the format string with values from |subst|.
|
||||
// Additionally, any number of consecutive '$' characters is replaced by that
|
||||
// number less one. Eg $$->$, $$$->$$, etc. Supports up to 9 replacements.
|
||||
std::wstring FormatErrorString(int string_id,
|
||||
base::span<const std::u16string> subst) {
|
||||
return base::UTF16ToWide(base::ReplaceStringPlaceholders(
|
||||
base::WideToUTF16(LoadString(string_id)), subst, nullptr));
|
||||
}
|
||||
|
||||
void ShowError(const std::wstring& error) {
|
||||
const auto subst = std::to_array<std::u16string>(
|
||||
{base::WideToUTF16(bootstrap_util::GetExePath().BaseName().value())});
|
||||
const auto& title = FormatErrorString(IDS_ERROR_TITLE, subst);
|
||||
const auto& extra_info = LoadString(IDS_ERROR_EXTRA_INFO);
|
||||
|
||||
#if defined(CEF_BUILD_BOOTSTRAP_CONSOLE)
|
||||
std::wcerr << title.c_str() << ": " << error << extra_info;
|
||||
#else
|
||||
const std::wstring& msg = error + extra_info;
|
||||
::MessageBox(nullptr, msg.c_str(), title.c_str(), MB_ICONERROR | MB_OK);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#if defined(CEF_BUILD_BOOTSTRAP_CONSOLE)
|
||||
int main(int argc, char* argv[]) {
|
||||
#else // !defined(CEF_BUILD_BOOTSTRAP_CONSOLE)
|
||||
// Entry point function for all processes.
|
||||
int APIENTRY wWinMain(HINSTANCE hInstance,
|
||||
HINSTANCE hPrevInstance,
|
||||
LPTSTR lpCmdLine,
|
||||
int nCmdShow) {
|
||||
UNREFERENCED_PARAMETER(hPrevInstance);
|
||||
UNREFERENCED_PARAMETER(lpCmdLine);
|
||||
#endif // !defined(CEF_BUILD_BOOTSTRAP_CONSOLE)
|
||||
|
||||
#if defined(ARCH_CPU_32_BITS)
|
||||
// Run the main thread on 32-bit Windows using a fiber with the preferred 4MiB
|
||||
// stack size. This function must be called at the top of the executable entry
|
||||
// point function (`main()` or `wWinMain()`). It is used in combination with
|
||||
// the initial stack size of 0.5MiB configured via the `/STACK:0x80000` linker
|
||||
// flag on executable targets. This saves significant memory on threads (like
|
||||
// those in the Windows thread pool, and others) whose stack size can only be
|
||||
// controlled via the linker flag.
|
||||
#if defined(CEF_BUILD_BOOTSTRAP_CONSOLE)
|
||||
int exit_code = CefRunMainWithPreferredStackSize(main, argc, argv);
|
||||
#else
|
||||
int exit_code = CefRunWinMainWithPreferredStackSize(wWinMain, hInstance,
|
||||
lpCmdLine, nCmdShow);
|
||||
#endif
|
||||
if (exit_code >= 0) {
|
||||
// The fiber has completed so return here.
|
||||
return exit_code;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Parse command-line arguments.
|
||||
const base::CommandLine command_line =
|
||||
base::CommandLine::FromString(::GetCommandLineW());
|
||||
|
||||
// True if this is a sandboxed sub-process. Uses similar logic to
|
||||
// Sandbox::IsProcessSandboxed.
|
||||
const bool is_sandboxed =
|
||||
command_line.HasSwitch("type") &&
|
||||
base::GetCurrentProcessIntegrityLevel() < base::MEDIUM_INTEGRITY;
|
||||
|
||||
std::wstring dll_name;
|
||||
base::FilePath exe_path;
|
||||
|
||||
if (is_sandboxed) {
|
||||
// Running as a sandboxed sub-process. May already be locked down, so we
|
||||
// can't call WinAPI functions. The command-line will already have been
|
||||
// validated in ChromeContentBrowserClientCef::
|
||||
// AppendExtraCommandLineSwitches. Retrieve the module value without
|
||||
// additional validation.
|
||||
dll_name = bootstrap_util::GetModuleValue(command_line);
|
||||
if (dll_name.empty()) {
|
||||
// Default to the command-line program name without extension.
|
||||
dll_name = command_line.GetProgram().BaseName().RemoveExtension().value();
|
||||
}
|
||||
} else {
|
||||
// Running as the main process or unsandboxed sub-process.
|
||||
exe_path = bootstrap_util::GetExePath();
|
||||
|
||||
// Retrieve the module name with validation.
|
||||
dll_name = bootstrap_util::GetValidatedModuleValue(command_line, exe_path);
|
||||
if (dll_name.empty()) {
|
||||
// Default to the executable module file name without extension. This is
|
||||
// safer than relying on the command-line program name.
|
||||
dll_name = bootstrap_util::GetDefaultModuleValue(exe_path);
|
||||
}
|
||||
|
||||
if (bootstrap_util::IsDefaultExeName(dll_name)) {
|
||||
ShowError(LoadString(IDS_ERROR_NO_MODULE_NAME));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Manage the life span of the sandbox information object. This is necessary
|
||||
// for sandbox support on Windows. See cef_sandbox_win.h for complete details.
|
||||
CefScopedSandboxInfo scoped_sandbox;
|
||||
void* sandbox_info = scoped_sandbox.sandbox_info();
|
||||
|
||||
#if defined(CEF_BUILD_BOOTSTRAP_CONSOLE)
|
||||
constexpr char kProcName[] = "RunConsoleMain";
|
||||
using kProcType = decltype(&RunConsoleMain);
|
||||
#else
|
||||
constexpr char kProcName[] = "RunWinMain";
|
||||
using kProcType = decltype(&RunWinMain);
|
||||
#endif
|
||||
|
||||
std::wstring error;
|
||||
|
||||
if (HMODULE hModule = ::LoadLibrary(dll_name.c_str())) {
|
||||
if (is_sandboxed ||
|
||||
bootstrap_util::IsModulePathAllowed(hModule, exe_path)) {
|
||||
if (auto* pFunc = (kProcType)::GetProcAddress(hModule, kProcName)) {
|
||||
#if defined(CEF_BUILD_BOOTSTRAP_CONSOLE)
|
||||
return pFunc(argc, argv, sandbox_info);
|
||||
#else
|
||||
return pFunc(hInstance, lpCmdLine, nCmdShow, sandbox_info);
|
||||
#endif
|
||||
} else if (!is_sandboxed) {
|
||||
const auto subst = std::to_array<std::u16string>(
|
||||
{base::WideToUTF16(dll_name),
|
||||
base::NumberToString16(::GetLastError()),
|
||||
base::ASCIIToUTF16(std::string(kProcName))});
|
||||
error = FormatErrorString(IDS_ERROR_NO_PROC_EXPORT, subst);
|
||||
}
|
||||
} else if (!is_sandboxed) {
|
||||
const auto subst =
|
||||
std::to_array<std::u16string>({base::WideToUTF16(dll_name)});
|
||||
error = FormatErrorString(IDS_ERROR_INVALID_LOCATION, subst);
|
||||
}
|
||||
FreeLibrary(hModule);
|
||||
} else if (!is_sandboxed) {
|
||||
const auto subst = std::to_array<std::u16string>(
|
||||
{base::WideToUTF16(dll_name),
|
||||
base::NumberToString16(::GetLastError())});
|
||||
error = FormatErrorString(IDS_ERROR_LOAD_FAILED, subst);
|
||||
}
|
||||
|
||||
// Don't try to show errors while sandboxed.
|
||||
if (!error.empty() && !is_sandboxed) {
|
||||
ShowError(error);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
BIN
libcef_dll/bootstrap/win/bootstrap.ico
Normal file
BIN
libcef_dll/bootstrap/win/bootstrap.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
133
libcef_dll/bootstrap/win/bootstrap.rc
Normal file
133
libcef_dll/bootstrap/win/bootstrap.rc
Normal file
@ -0,0 +1,133 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "libcef_dll/bootstrap/win/resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#define APSTUDIO_HIDDEN_SYMBOLS
|
||||
#include "windows.h"
|
||||
#include "include/cef_version.h"
|
||||
#undef APSTUDIO_HIDDEN_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDI_APPLICATION ICON "bootstrap.ico"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION CEF_VERSION_MAJOR,CEF_VERSION_MINOR,CEF_VERSION_PATCH,0
|
||||
PRODUCTVERSION CEF_VERSION_MAJOR,CEF_VERSION_MINOR,CEF_VERSION_PATCH,0
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "FileDescription", "CEF Bootstrap Application"
|
||||
VALUE "FileVersion", CEF_VERSION
|
||||
#if defined(CEF_BUILD_BOOTSTRAP_CONSOLE)
|
||||
VALUE "InternalName", "bootstrapc"
|
||||
VALUE "OriginalFilename", "bootstrapc.exe"
|
||||
#else
|
||||
VALUE "InternalName", "bootstrap"
|
||||
VALUE "OriginalFilename", "bootstrap.exe"
|
||||
#endif
|
||||
VALUE "LegalCopyright", "Copyright (C) " MAKE_STRING(COPYRIGHT_YEAR) " The Chromium Embedded Framework Authors"
|
||||
VALUE "ProductName", "CEF Bootstrap Application"
|
||||
VALUE "ProductVersion", CEF_VERSION
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// String Table
|
||||
//
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_ERROR_TITLE "Runtime Error: $1"
|
||||
IDS_ERROR_EXTRA_INFO "\nTry reinstalling the application to fix this error."
|
||||
IDS_ERROR_NO_MODULE_NAME "Missing module name"
|
||||
IDS_ERROR_NO_PROC_EXPORT "Failed to find $3 in $1.dll (error $2)"
|
||||
IDS_ERROR_INVALID_LOCATION "Found $1.dll in an unexpected location"
|
||||
IDS_ERROR_LOAD_FAILED "Failed to load $1.dll (error $2)"
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
|
||||
"#include ""windows.h""\r\n"
|
||||
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
26
libcef_dll/bootstrap/win/resource.h
Normal file
26
libcef_dll/bootstrap/win/resource.h
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright (c) 2025 The Chromium Embedded Framework Authors. All rights
|
||||
// reserved. Use of this source code is governed by a BSD-style license that
|
||||
// can be found in the LICENSE file.
|
||||
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by cefclient.rc
|
||||
//
|
||||
#define IDS_ERROR_TITLE 100
|
||||
#define IDS_ERROR_EXTRA_INFO 101
|
||||
#define IDS_ERROR_NO_MODULE_NAME 102
|
||||
#define IDS_ERROR_NO_PROC_EXPORT 103
|
||||
#define IDS_ERROR_INVALID_LOCATION 104
|
||||
#define IDS_ERROR_LOAD_FAILED 105
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NO_MFC 1
|
||||
#define _APS_NEXT_RESOURCE_VALUE 106
|
||||
#define _APS_NEXT_COMMAND_VALUE 32000
|
||||
#define _APS_NEXT_CONTROL_VALUE 1000
|
||||
#define _APS_NEXT_SYMED_VALUE 100
|
||||
#endif
|
||||
#endif
|
@ -261,7 +261,7 @@ void OsrWindowWin::Create(HWND parent_hwnd, const RECT& rect) {
|
||||
DCHECK(parent_hwnd);
|
||||
DCHECK(!::IsRectEmpty(&rect));
|
||||
|
||||
HINSTANCE hInst = ::GetModuleHandle(nullptr);
|
||||
HINSTANCE hInst = GetCodeModuleHandle();
|
||||
|
||||
const cef_color_t background_color = MainContext::Get()->GetBackgroundColor();
|
||||
const HBRUSH background_brush = CreateSolidBrush(
|
||||
|
@ -487,7 +487,7 @@ void RootWindowWin::CreateRootWindow(const CefBrowserSettings& settings,
|
||||
REQUIRE_MAIN_THREAD();
|
||||
DCHECK(!hwnd_);
|
||||
|
||||
HINSTANCE hInstance = GetModuleHandle(nullptr);
|
||||
HINSTANCE hInstance = GetCodeModuleHandle();
|
||||
|
||||
// Load strings from the resource file.
|
||||
const std::wstring& window_title = GetResourceString(IDS_APP_TITLE);
|
||||
@ -1079,7 +1079,7 @@ void RootWindowWin::OnFindEvent() {
|
||||
|
||||
void RootWindowWin::OnAbout() {
|
||||
// Show the about box.
|
||||
DialogBox(GetModuleHandle(nullptr), MAKEINTRESOURCE(IDD_ABOUTBOX), hwnd_,
|
||||
DialogBox(GetCodeModuleHandle(), MAKEINTRESOURCE(IDD_ABOUTBOX), hwnd_,
|
||||
AboutWndProc);
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include "include/base/cef_logging.h"
|
||||
#include "tests/shared/browser/util_win.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
@ -16,7 +17,7 @@ const wchar_t kWndClass[] = L"Client_TempWindow";
|
||||
|
||||
// Create the temp window.
|
||||
HWND CreateTempWindow() {
|
||||
HINSTANCE hInstance = ::GetModuleHandle(nullptr);
|
||||
HINSTANCE hInstance = GetCodeModuleHandle();
|
||||
|
||||
WNDCLASSEX wc = {0};
|
||||
wc.cbSize = sizeof(wc);
|
||||
|
@ -20,33 +20,12 @@
|
||||
#include "tests/shared/common/client_switches.h"
|
||||
#include "tests/shared/renderer/client_app_renderer.h"
|
||||
|
||||
// When generating projects with CMake the CEF_USE_SANDBOX value will be defined
|
||||
// automatically if using the required compiler version. Pass -DUSE_SANDBOX=OFF
|
||||
// to the CMake command-line to disable use of the sandbox.
|
||||
// Uncomment this line to manually enable sandbox support.
|
||||
// #define CEF_USE_SANDBOX 1
|
||||
|
||||
#if defined(CEF_USE_SANDBOX)
|
||||
// The cef_sandbox.lib static library may not link successfully with all VS
|
||||
// versions.
|
||||
#pragma comment(lib, "cef_sandbox.lib")
|
||||
#endif
|
||||
|
||||
namespace client {
|
||||
namespace {
|
||||
|
||||
int RunMain(HINSTANCE hInstance, int nCmdShow) {
|
||||
int RunMain(HINSTANCE hInstance, int nCmdShow, void* sandbox_info) {
|
||||
CefMainArgs main_args(hInstance);
|
||||
|
||||
void* sandbox_info = nullptr;
|
||||
|
||||
#if defined(CEF_USE_SANDBOX)
|
||||
// Manage the life span of the sandbox information object. This is necessary
|
||||
// for sandbox support on Windows. See cef_sandbox_win.h for complete details.
|
||||
CefScopedSandboxInfo scoped_sandbox;
|
||||
sandbox_info = scoped_sandbox.sandbox_info();
|
||||
#endif
|
||||
|
||||
// Parse command-line arguments.
|
||||
CefRefPtr<CefCommandLine> command_line = CefCommandLine::CreateCommandLine();
|
||||
command_line->InitFromString(::GetCommandLineW());
|
||||
@ -73,9 +52,9 @@ int RunMain(HINSTANCE hInstance, int nCmdShow) {
|
||||
|
||||
CefSettings settings;
|
||||
|
||||
#if !defined(CEF_USE_SANDBOX)
|
||||
settings.no_sandbox = true;
|
||||
#endif
|
||||
if (!sandbox_info) {
|
||||
settings.no_sandbox = true;
|
||||
}
|
||||
|
||||
// Populate the settings based on command line arguments.
|
||||
context->PopulateSettings(&settings);
|
||||
@ -131,6 +110,18 @@ int RunMain(HINSTANCE hInstance, int nCmdShow) {
|
||||
} // namespace
|
||||
} // namespace client
|
||||
|
||||
#if defined(CEF_USE_BOOTSTRAP)
|
||||
|
||||
// Entry point called by bootstrap.exe when built as a DLL.
|
||||
CEF_BOOTSTRAP_EXPORT int RunWinMain(HINSTANCE hInstance,
|
||||
LPTSTR lpCmdLine,
|
||||
int nCmdShow,
|
||||
void* sandbox_info) {
|
||||
return client::RunMain(hInstance, nCmdShow, sandbox_info);
|
||||
}
|
||||
|
||||
#else // !defined(CEF_USE_BOOTSTRAP)
|
||||
|
||||
// Program entry point function.
|
||||
int APIENTRY wWinMain(HINSTANCE hInstance,
|
||||
HINSTANCE hPrevInstance,
|
||||
@ -155,5 +146,16 @@ int APIENTRY wWinMain(HINSTANCE hInstance,
|
||||
}
|
||||
#endif
|
||||
|
||||
return client::RunMain(hInstance, nCmdShow);
|
||||
void* sandbox_info = nullptr;
|
||||
|
||||
#if defined(CEF_USE_SANDBOX)
|
||||
// Manage the life span of the sandbox information object. This is necessary
|
||||
// for sandbox support on Windows. See cef_sandbox_win.h for complete details.
|
||||
CefScopedSandboxInfo scoped_sandbox;
|
||||
sandbox_info = scoped_sandbox.sandbox_info();
|
||||
#endif
|
||||
|
||||
return client::RunMain(hInstance, nCmdShow, sandbox_info);
|
||||
}
|
||||
|
||||
#endif // !defined(CEF_USE_BOOTSTRAP)
|
||||
|
@ -8,53 +8,14 @@
|
||||
#include "include/cef_sandbox_win.h"
|
||||
#include "tests/cefsimple/simple_app.h"
|
||||
|
||||
// When generating projects with CMake the CEF_USE_SANDBOX value will be defined
|
||||
// automatically if using the required compiler version. Pass -DUSE_SANDBOX=OFF
|
||||
// to the CMake command-line to disable use of the sandbox.
|
||||
// Uncomment this line to manually enable sandbox support.
|
||||
// #define CEF_USE_SANDBOX 1
|
||||
|
||||
#if defined(CEF_USE_SANDBOX)
|
||||
// The cef_sandbox.lib static library may not link successfully with all VS
|
||||
// versions.
|
||||
#pragma comment(lib, "cef_sandbox.lib")
|
||||
#endif
|
||||
|
||||
// Entry point function for all processes.
|
||||
int APIENTRY wWinMain(HINSTANCE hInstance,
|
||||
HINSTANCE hPrevInstance,
|
||||
LPTSTR lpCmdLine,
|
||||
int nCmdShow) {
|
||||
UNREFERENCED_PARAMETER(hPrevInstance);
|
||||
UNREFERENCED_PARAMETER(lpCmdLine);
|
||||
namespace {
|
||||
|
||||
int RunMain(HINSTANCE hInstance,
|
||||
LPTSTR lpCmdLine,
|
||||
int nCmdShow,
|
||||
void* sandbox_info) {
|
||||
int exit_code;
|
||||
|
||||
#if defined(ARCH_CPU_32_BITS)
|
||||
// Run the main thread on 32-bit Windows using a fiber with the preferred 4MiB
|
||||
// stack size. This function must be called at the top of the executable entry
|
||||
// point function (`main()` or `wWinMain()`). It is used in combination with
|
||||
// the initial stack size of 0.5MiB configured via the `/STACK:0x80000` linker
|
||||
// flag on executable targets. This saves significant memory on threads (like
|
||||
// those in the Windows thread pool, and others) whose stack size can only be
|
||||
// controlled via the linker flag.
|
||||
exit_code = CefRunWinMainWithPreferredStackSize(wWinMain, hInstance,
|
||||
lpCmdLine, nCmdShow);
|
||||
if (exit_code >= 0) {
|
||||
// The fiber has completed so return here.
|
||||
return exit_code;
|
||||
}
|
||||
#endif
|
||||
|
||||
void* sandbox_info = nullptr;
|
||||
|
||||
#if defined(CEF_USE_SANDBOX)
|
||||
// Manage the life span of the sandbox information object. This is necessary
|
||||
// for sandbox support on Windows. See cef_sandbox_win.h for complete details.
|
||||
CefScopedSandboxInfo scoped_sandbox;
|
||||
sandbox_info = scoped_sandbox.sandbox_info();
|
||||
#endif
|
||||
|
||||
// Provide CEF with command-line arguments.
|
||||
CefMainArgs main_args(hInstance);
|
||||
|
||||
@ -74,9 +35,9 @@ int APIENTRY wWinMain(HINSTANCE hInstance,
|
||||
// Specify CEF global settings here.
|
||||
CefSettings settings;
|
||||
|
||||
#if !defined(CEF_USE_SANDBOX)
|
||||
settings.no_sandbox = true;
|
||||
#endif
|
||||
if (!sandbox_info) {
|
||||
settings.no_sandbox = true;
|
||||
}
|
||||
|
||||
// SimpleApp implements application-level callbacks for the browser process.
|
||||
// It will create the first browser instance in OnContextInitialized() after
|
||||
@ -99,3 +60,55 @@ int APIENTRY wWinMain(HINSTANCE hInstance,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#if defined(CEF_USE_BOOTSTRAP)
|
||||
|
||||
// Entry point called by bootstrap.exe when built as a DLL.
|
||||
CEF_BOOTSTRAP_EXPORT int RunWinMain(HINSTANCE hInstance,
|
||||
LPTSTR lpCmdLine,
|
||||
int nCmdShow,
|
||||
void* sandbox_info) {
|
||||
return ::RunMain(hInstance, lpCmdLine, nCmdShow, sandbox_info);
|
||||
}
|
||||
|
||||
#else // !defined(CEF_USE_BOOTSTRAP)
|
||||
|
||||
// Entry point function for all processes.
|
||||
int APIENTRY wWinMain(HINSTANCE hInstance,
|
||||
HINSTANCE hPrevInstance,
|
||||
LPTSTR lpCmdLine,
|
||||
int nCmdShow) {
|
||||
UNREFERENCED_PARAMETER(hPrevInstance);
|
||||
UNREFERENCED_PARAMETER(lpCmdLine);
|
||||
|
||||
#if defined(ARCH_CPU_32_BITS)
|
||||
// Run the main thread on 32-bit Windows using a fiber with the preferred 4MiB
|
||||
// stack size. This function must be called at the top of the executable entry
|
||||
// point function (`main()` or `wWinMain()`). It is used in combination with
|
||||
// the initial stack size of 0.5MiB configured via the `/STACK:0x80000` linker
|
||||
// flag on executable targets. This saves significant memory on threads (like
|
||||
// those in the Windows thread pool, and others) whose stack size can only be
|
||||
// controlled via the linker flag.
|
||||
int exit_code = CefRunWinMainWithPreferredStackSize(wWinMain, hInstance,
|
||||
lpCmdLine, nCmdShow);
|
||||
if (exit_code >= 0) {
|
||||
// The fiber has completed so return here.
|
||||
return exit_code;
|
||||
}
|
||||
#endif
|
||||
|
||||
void* sandbox_info = nullptr;
|
||||
|
||||
#if defined(CEF_USE_SANDBOX)
|
||||
// Manage the life span of the sandbox information object. This is necessary
|
||||
// for sandbox support on Windows. See cef_sandbox_win.h for complete details.
|
||||
CefScopedSandboxInfo scoped_sandbox;
|
||||
sandbox_info = scoped_sandbox.sandbox_info();
|
||||
#endif
|
||||
|
||||
return ::RunMain(hInstance, lpCmdLine, nCmdShow, sandbox_info);
|
||||
}
|
||||
|
||||
#endif // !defined(CEF_USE_BOOTSTRAP)
|
||||
|
@ -21,8 +21,10 @@
|
||||
#elif defined(OS_LINUX)
|
||||
#include <X11/keysym.h>
|
||||
#elif defined(OS_WIN)
|
||||
#include "tests/shared/browser/util_win.h"
|
||||
|
||||
// Required for resource_util_win, which uses this as an extern
|
||||
HINSTANCE hInst = ::GetModuleHandle(nullptr);
|
||||
HINSTANCE hInst = client::GetCodeModuleHandle();
|
||||
#endif
|
||||
|
||||
// Set to 1 to enable verbose debugging info logging.
|
||||
|
@ -39,15 +39,9 @@
|
||||
#include "include/wrapper/cef_library_loader.h"
|
||||
#endif
|
||||
|
||||
// When generating projects with CMake the CEF_USE_SANDBOX value will be defined
|
||||
// automatically if using the required compiler version. Pass -DUSE_SANDBOX=OFF
|
||||
// to the CMake command-line to disable use of the sandbox.
|
||||
#if defined(OS_WIN) && defined(CEF_USE_SANDBOX)
|
||||
#if defined(OS_WIN)
|
||||
#include "include/cef_sandbox_win.h"
|
||||
|
||||
// The cef_sandbox.lib static library may not link successfully with all VS
|
||||
// versions.
|
||||
#pragma comment(lib, "cef_sandbox.lib")
|
||||
#include "tests/shared/browser/util_win.h"
|
||||
#endif
|
||||
|
||||
#if defined(OS_MAC)
|
||||
@ -132,31 +126,13 @@ class ScopedPlatformSetup final {
|
||||
};
|
||||
#endif // defined(OS_MAC)
|
||||
|
||||
} // namespace
|
||||
|
||||
NO_STACK_PROTECTOR
|
||||
int main(int argc, char* argv[]) {
|
||||
int RunMain(int argc, char* argv[], void* sandbox_info) {
|
||||
int exit_code;
|
||||
|
||||
#if CEF_API_VERSION != CEF_EXPERIMENTAL
|
||||
printf("Running with configured CEF API version %d\n", CEF_API_VERSION);
|
||||
#endif
|
||||
|
||||
#if defined(OS_WIN) && defined(ARCH_CPU_32_BITS)
|
||||
// Run the main thread on 32-bit Windows using a fiber with the preferred 4MiB
|
||||
// stack size. This function must be called at the top of the executable entry
|
||||
// point function (`main()` or `wWinMain()`). It is used in combination with
|
||||
// the initial stack size of 0.5MiB configured via the `/STACK:0x80000` linker
|
||||
// flag on executable targets. This saves significant memory on threads (like
|
||||
// those in the Windows thread pool, and others) whose stack size can only be
|
||||
// controlled via the linker flag.
|
||||
exit_code = CefRunMainWithPreferredStackSize(main, argc, argv);
|
||||
if (exit_code >= 0) {
|
||||
// The fiber has completed so return here.
|
||||
return exit_code;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(OS_MAC)
|
||||
// Load the CEF framework library at runtime instead of linking directly
|
||||
// as required by the macOS sandbox implementation.
|
||||
@ -170,19 +146,11 @@ int main(int argc, char* argv[]) {
|
||||
CefTestSuite test_suite(argc, argv);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
CefMainArgs main_args(::GetModuleHandle(nullptr));
|
||||
CefMainArgs main_args(client::GetCodeModuleHandle());
|
||||
#else
|
||||
CefMainArgs main_args(argc, argv);
|
||||
#endif
|
||||
|
||||
void* windows_sandbox_info = nullptr;
|
||||
|
||||
#if defined(OS_WIN) && defined(CEF_USE_SANDBOX)
|
||||
// Manages the life span of the sandbox information object.
|
||||
CefScopedSandboxInfo scoped_sandbox;
|
||||
windows_sandbox_info = scoped_sandbox.sandbox_info();
|
||||
#endif
|
||||
|
||||
// Create a ClientApp of the correct type.
|
||||
CefRefPtr<CefApp> app;
|
||||
client::ClientApp::ProcessType process_type =
|
||||
@ -198,7 +166,7 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
// Execute the secondary process, if any.
|
||||
exit_code = CefExecuteProcess(main_args, app, windows_sandbox_info);
|
||||
exit_code = CefExecuteProcess(main_args, app, sandbox_info);
|
||||
if (exit_code >= 0) {
|
||||
return exit_code;
|
||||
}
|
||||
@ -211,7 +179,11 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
CefSettings settings;
|
||||
|
||||
#if !defined(CEF_USE_SANDBOX)
|
||||
#if defined(OS_WIN)
|
||||
if (!sandbox_info) {
|
||||
settings.no_sandbox = true;
|
||||
}
|
||||
#elif !defined(CEF_USE_SANDBOX)
|
||||
settings.no_sandbox = true;
|
||||
#endif
|
||||
|
||||
@ -231,7 +203,7 @@ int main(int argc, char* argv[]) {
|
||||
#endif
|
||||
|
||||
// Initialize CEF.
|
||||
if (!CefInitialize(main_args, settings, app, windows_sandbox_info)) {
|
||||
if (!CefInitialize(main_args, settings, app, sandbox_info)) {
|
||||
exit_code = CefGetExitCode();
|
||||
LOG(ERROR) << "CefInitialize exited with code " << exit_code;
|
||||
return exit_code;
|
||||
@ -304,3 +276,47 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#if defined(OS_WIN) && defined(CEF_USE_BOOTSTRAP)
|
||||
|
||||
// Entry point called by bootstrapc.exe when built as a DLL.
|
||||
CEF_BOOTSTRAP_EXPORT int RunConsoleMain(int argc,
|
||||
char* argv[],
|
||||
void* sandbox_info) {
|
||||
return ::RunMain(argc, argv, sandbox_info);
|
||||
}
|
||||
|
||||
#else // !(defined(OS_WIN) && defined(CEF_USE_BOOTSTRAP))
|
||||
|
||||
// Program entry point function.
|
||||
NO_STACK_PROTECTOR
|
||||
int main(int argc, char* argv[]) {
|
||||
#if defined(OS_WIN) && defined(ARCH_CPU_32_BITS)
|
||||
// Run the main thread on 32-bit Windows using a fiber with the preferred 4MiB
|
||||
// stack size. This function must be called at the top of the executable entry
|
||||
// point function (`main()` or `wWinMain()`). It is used in combination with
|
||||
// the initial stack size of 0.5MiB configured via the `/STACK:0x80000` linker
|
||||
// flag on executable targets. This saves significant memory on threads (like
|
||||
// those in the Windows thread pool, and others) whose stack size can only be
|
||||
// controlled via the linker flag.
|
||||
exit_code = CefRunMainWithPreferredStackSize(main, argc, argv);
|
||||
if (exit_code >= 0) {
|
||||
// The fiber has completed so return here.
|
||||
return exit_code;
|
||||
}
|
||||
#endif
|
||||
|
||||
void* sandbox_info = nullptr;
|
||||
|
||||
#if defined(OS_WIN) && defined(CEF_USE_SANDBOX)
|
||||
// Manages the life span of the sandbox information object.
|
||||
CefScopedSandboxInfo scoped_sandbox;
|
||||
sandbox_info = scoped_sandbox.sandbox_info();
|
||||
#endif
|
||||
|
||||
return ::RunMain(argc, argv, sandbox_info);
|
||||
}
|
||||
|
||||
#endif // !(defined(OS_WIN) && defined(CEF_USE_BOOTSTRAP))
|
||||
|
@ -51,7 +51,7 @@ class MainMessageLoopExternalPumpWin : public MainMessageLoopExternalPump {
|
||||
};
|
||||
|
||||
MainMessageLoopExternalPumpWin::MainMessageLoopExternalPumpWin() {
|
||||
HINSTANCE hInstance = GetModuleHandle(nullptr);
|
||||
HINSTANCE hInstance = GetCodeModuleHandle();
|
||||
const wchar_t* const kClassName = L"CEFMainTargetHWND";
|
||||
|
||||
WNDCLASSEX wcex = {};
|
||||
|
@ -8,13 +8,14 @@
|
||||
#include "include/cef_stream.h"
|
||||
#include "include/wrapper/cef_byte_read_handler.h"
|
||||
#include "include/wrapper/cef_stream_resource_handler.h"
|
||||
#include "tests/shared/browser/util_win.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
namespace {
|
||||
|
||||
bool LoadBinaryResource(int binaryId, DWORD& dwSize, LPBYTE& pBytes) {
|
||||
HINSTANCE hInst = GetModuleHandle(nullptr);
|
||||
HINSTANCE hInst = GetCodeModuleHandle();
|
||||
HRSRC hRes =
|
||||
FindResource(hInst, MAKEINTRESOURCE(binaryId), MAKEINTRESOURCE(256));
|
||||
if (hRes) {
|
||||
|
@ -44,7 +44,7 @@ WNDPROC SetWndProcPtr(HWND hWnd, WNDPROC wndProc) {
|
||||
std::wstring GetResourceString(UINT id) {
|
||||
#define MAX_LOADSTRING 100
|
||||
TCHAR buff[MAX_LOADSTRING] = {0};
|
||||
LoadString(::GetModuleHandle(nullptr), id, buff, MAX_LOADSTRING);
|
||||
LoadString(GetCodeModuleHandle(), id, buff, MAX_LOADSTRING);
|
||||
return buff;
|
||||
}
|
||||
|
||||
@ -191,4 +191,13 @@ float GetDeviceScaleFactor() {
|
||||
return scale_factor;
|
||||
}
|
||||
|
||||
HINSTANCE GetCodeModuleHandle() {
|
||||
HMODULE hModule = nullptr;
|
||||
CHECK(::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
|
||||
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
|
||||
reinterpret_cast<LPCWSTR>(GetCodeModuleHandle),
|
||||
&hModule));
|
||||
return hModule;
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
|
@ -40,6 +40,10 @@ bool IsKeyDown(WPARAM wparam);
|
||||
// return 2.0.
|
||||
float GetDeviceScaleFactor();
|
||||
|
||||
// Returns the module handle that contains this code. When built as a DLL this
|
||||
// will be the DLL handle instead of the EXE handle.
|
||||
HINSTANCE GetCodeModuleHandle();
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_SHARED_BROWSER_UTIL_WIN_H_
|
||||
|
@ -16,13 +16,11 @@ import sys
|
||||
import tempfile
|
||||
import zipfile
|
||||
|
||||
is_python2 = sys.version_info.major == 2
|
||||
if sys.version_info.major != 3:
|
||||
sys.stderr.write('Python3 is required!')
|
||||
sys.exit(1)
|
||||
|
||||
if is_python2:
|
||||
from urllib import FancyURLopener
|
||||
from urllib2 import urlopen
|
||||
else:
|
||||
from urllib.request import FancyURLopener, urlopen
|
||||
from urllib.request import FancyURLopener, urlopen
|
||||
|
||||
##
|
||||
# Default URLs.
|
||||
@ -218,19 +216,12 @@ def read_file(path):
|
||||
raise Exception("Path does not exist: %s" % (path))
|
||||
|
||||
|
||||
def write_fp(fp, data):
|
||||
if is_python2:
|
||||
fp.write(data.decode('utf-8'))
|
||||
else:
|
||||
fp.write(data)
|
||||
|
||||
|
||||
def write_file(path, data):
|
||||
""" Write a file. """
|
||||
msg('Writing %s' % path)
|
||||
if not options.dryrun:
|
||||
with open(path, 'w', encoding='utf-8') as fp:
|
||||
write_fp(fp, data)
|
||||
fp.write(data)
|
||||
|
||||
|
||||
def read_config_file(path):
|
||||
@ -446,21 +437,20 @@ def check_pattern_matches(output_file=None):
|
||||
if not skip:
|
||||
if write_msg:
|
||||
if has_output:
|
||||
write_fp(fp, '\n')
|
||||
write_fp(fp,
|
||||
'!!!! WARNING: FOUND PATTERN: %s\n' % entry['pattern'])
|
||||
fp.write('\n')
|
||||
fp.write('!!!! WARNING: FOUND PATTERN: %s\n' % entry['pattern'])
|
||||
if 'message' in entry:
|
||||
write_fp(fp, entry['message'] + '\n')
|
||||
write_fp(fp, '\n')
|
||||
fp.write(entry['message'] + '\n')
|
||||
fp.write('\n')
|
||||
write_msg = False
|
||||
write_fp(fp, line + '\n')
|
||||
fp.write(line + '\n')
|
||||
has_output = True
|
||||
|
||||
if not output_file is None:
|
||||
if has_output:
|
||||
msg('ERROR Matches found. See %s for output.' % out_file)
|
||||
else:
|
||||
write_fp(fp, 'Good news! No matches.\n')
|
||||
fp.write('Good news! No matches.\n')
|
||||
fp.close()
|
||||
|
||||
if has_output:
|
||||
@ -901,27 +891,13 @@ if not branch_is_master:
|
||||
sys.exit(1)
|
||||
|
||||
# Verify the minimum supported branch number.
|
||||
if int(cef_branch) < 3071:
|
||||
if int(cef_branch) < 5060:
|
||||
print('The requested branch (%s) is too old to build using this tool. ' +
|
||||
'The minimum supported branch is 3071.' % cef_branch)
|
||||
sys.exit(1)
|
||||
|
||||
# True if the requested branch is 3538 or newer.
|
||||
branch_is_3538_or_newer = (branch_is_master or int(cef_branch) >= 3538)
|
||||
|
||||
# True if the requested branch is 3945 or newer.
|
||||
branch_is_3945_or_newer = (branch_is_master or int(cef_branch) >= 3945)
|
||||
|
||||
# Enable Python 3 usage in Chromium for branches 3945 and newer.
|
||||
if branch_is_3945_or_newer and not is_python2 and \
|
||||
not 'GCLIENT_PY3' in os.environ.keys():
|
||||
os.environ['GCLIENT_PY3'] = '1'
|
||||
|
||||
if not branch_is_3945_or_newer and \
|
||||
(not is_python2 or bool(int(os.environ.get('GCLIENT_PY3', '0')))):
|
||||
print('Python 3 is not supported with branch 3904 and older ' +
|
||||
'(set GCLIENT_PY3=0 and run with Python 2 executable).')
|
||||
sys.exit(1)
|
||||
# True if the requested branch is 7151 or older.
|
||||
branch_is_7151_or_older = not branch_is_master and int(cef_branch) <= 7151
|
||||
|
||||
if options.armbuild:
|
||||
if platform != 'linux':
|
||||
@ -936,9 +912,9 @@ if platform == 'mac' and not (options.x64build or options.arm64build):
|
||||
sys.exit(1)
|
||||
|
||||
# Platforms that build a cef_sandbox library.
|
||||
sandbox_lib_platforms = ['windows']
|
||||
if branch_is_3538_or_newer:
|
||||
sandbox_lib_platforms.append('mac')
|
||||
sandbox_lib_platforms = ['mac']
|
||||
if branch_is_7151_or_older:
|
||||
sandbox_lib_platforms.append('win')
|
||||
|
||||
if not platform in sandbox_lib_platforms and (options.sandboxdistrib or
|
||||
options.sandboxdistribonly):
|
||||
@ -1023,7 +999,7 @@ if platform == 'windows':
|
||||
# Force use of the system installed Git version.
|
||||
git_exe = 'git.exe'
|
||||
# Force use of the Python version bundled with depot_tools.
|
||||
python_bat = 'python.bat' if is_python2 else 'python3.bat'
|
||||
python_bat = 'python3.bat'
|
||||
python_exe = os.path.join(depot_tools_dir, python_bat)
|
||||
if options.dryrun and not os.path.exists(python_exe):
|
||||
sys.stdout.write("WARNING: --dry-run assumes that depot_tools" \
|
||||
@ -1180,7 +1156,7 @@ if not os.path.exists(gclient_file) or options.forceconfig:
|
||||
msg('Writing %s' % gclient_file)
|
||||
if not options.dryrun:
|
||||
with open(gclient_file, 'w', encoding='utf-8') as fp:
|
||||
write_fp(fp, gclient_spec)
|
||||
fp.write(gclient_spec)
|
||||
|
||||
# Initial Chromium checkout.
|
||||
if not options.nochromiumupdate and not os.path.exists(chromium_src_dir):
|
||||
@ -1366,6 +1342,8 @@ if not options.nobuild and (chromium_checkout_changed or \
|
||||
target += ' ' + options.testtarget
|
||||
if platform == 'linux':
|
||||
target += ' chrome_sandbox'
|
||||
if platform == 'windows' and not branch_is_7151_or_older:
|
||||
target += ' bootstrap bootstrapc'
|
||||
|
||||
# Make a CEF Debug build.
|
||||
if not options.nodebugbuild:
|
||||
|
@ -66,12 +66,6 @@ if platform == 'windows':
|
||||
#
|
||||
# set WIN_CUSTOM_TOOLCHAIN=1
|
||||
#
|
||||
# o Used by tools/msvs_env.bat to configure the MSVS tools environment.
|
||||
# Should be set to "none" because VC variables for CEF will be set via
|
||||
# INCLUDE/LIB/PATH.
|
||||
#
|
||||
# set CEF_VCVARS=none
|
||||
#
|
||||
# o Used by the following scripts:
|
||||
# (a) build/vs_toolchain.py SetEnvironmentAndGetRuntimeDllDirs when
|
||||
# determining whether to copy VS runtime binaries to the output directory.
|
||||
|
@ -550,17 +550,6 @@ def GetConfigArgsSandbox(platform, args, is_debug, cpu):
|
||||
'is_cef_sandbox_build': True,
|
||||
}
|
||||
|
||||
if platform == 'windows':
|
||||
# Avoid Debug build linker errors caused by custom libc++.
|
||||
add_args['use_custom_libcxx'] = False
|
||||
|
||||
# Avoid dependency on //third_party/perfetto:libperfetto which fails to
|
||||
# build with MSVC libc++.
|
||||
add_args['enable_base_tracing'] = False
|
||||
|
||||
# Allow non-component Debug builds for the sandbox.
|
||||
add_args['forbid_non_component_debug_builds'] = False
|
||||
|
||||
if not is_debug:
|
||||
# Disable DCHECKs in Release builds.
|
||||
add_args['dcheck_always_on'] = False
|
||||
@ -647,8 +636,7 @@ def GetAllPlatformConfigs(build_args, quiet=False):
|
||||
result['Debug_GN_' + cpu] = GetConfigArgs(args, True, cpu)
|
||||
result['Release_GN_' + cpu] = GetConfigArgs(args, False, cpu)
|
||||
|
||||
if platform in ('windows', 'mac') and GetArgValue(args,
|
||||
'is_official_build'):
|
||||
if platform == 'mac' and GetArgValue(args, 'is_official_build'):
|
||||
# Build cef_sandbox.lib with a different configuration.
|
||||
if create_debug:
|
||||
result['Debug_GN_' + cpu + '_sandbox'] = GetConfigArgsSandbox(
|
||||
|
@ -561,10 +561,7 @@ def get_undefined_symbols(file):
|
||||
def combine_libs(platform, build_dir, libs, dest_lib):
|
||||
""" Combine multiple static libraries into a single static library. """
|
||||
intermediate_obj = None
|
||||
if platform == 'windows':
|
||||
cmdline = 'msvs_env.bat win%s "%s" combine_libs.py -b "%s" -o "%s"' % (
|
||||
platform_arch, sys.executable, build_dir, dest_lib)
|
||||
elif platform == 'mac':
|
||||
if platform == 'mac':
|
||||
# Find CEF_EXPORT symbols from libcef_sandbox.a (include/cef_sandbox_mac.h)
|
||||
# Export only symbols that include these strings.
|
||||
symbol_match = [
|
||||
@ -589,14 +586,14 @@ def combine_libs(platform, build_dir, libs, dest_lib):
|
||||
cmdline = 'ld -arch %s -r -o "%s"' % (arch, intermediate_obj)
|
||||
for symbol in symbols:
|
||||
cmdline += ' -exported_symbol %s' % symbol
|
||||
else:
|
||||
raise Exception('Unsupported platform for combine_libs: %s' % platform)
|
||||
|
||||
for lib in libs:
|
||||
lib_path = os.path.join(build_dir, lib)
|
||||
for path in get_files(lib_path): # Expand wildcards in |lib_path|.
|
||||
if not path_exists(path):
|
||||
raise Exception('File not found: ' + path)
|
||||
if platform == 'windows':
|
||||
path = os.path.relpath(path, build_dir)
|
||||
cmdline += ' "%s"' % path
|
||||
run(cmdline, os.path.join(cef_dir, 'tools'))
|
||||
|
||||
@ -746,7 +743,7 @@ parser.add_option(
|
||||
action='store_true',
|
||||
dest='sandbox',
|
||||
default=False,
|
||||
help='include only the cef_sandbox static library (macOS and Windows only)')
|
||||
help='include only the cef_sandbox static library (macOS only)')
|
||||
parser.add_option(
|
||||
'--tools',
|
||||
action='store_true',
|
||||
@ -794,8 +791,8 @@ if options.armbuild and platform != 'linux':
|
||||
print_error('--arm-build is only supported on Linux.')
|
||||
sys.exit()
|
||||
|
||||
if options.sandbox and not platform in ('mac', 'windows'):
|
||||
print_error('--sandbox is only supported on macOS and Windows.')
|
||||
if options.sandbox and platform != 'mac':
|
||||
print_error('--sandbox is only supported on macOS.')
|
||||
sys.exit()
|
||||
|
||||
if not options.ninjabuild:
|
||||
@ -1130,6 +1127,8 @@ elif platform == 'windows':
|
||||
{'path': 'vulkan-1.dll'},
|
||||
]
|
||||
pdb_files = [
|
||||
{'path': 'bootstrap.exe.pdb'},
|
||||
{'path': 'bootstrapc.exe.pdb'},
|
||||
{'path': 'chrome_elf.dll.pdb'},
|
||||
{'path': 'dxcompiler.dll.pdb', 'conditional': True},
|
||||
{'path': '%s.pdb' % libcef_dll},
|
||||
@ -1145,7 +1144,13 @@ elif platform == 'windows':
|
||||
'path': 'cefsimple.exe' if platform_arch == 'arm64' else 'cefclient.exe'
|
||||
})
|
||||
else:
|
||||
binaries.append({'path': '%s.lib' % libcef_dll, 'out_path': 'libcef.lib'})
|
||||
# yapf: disable
|
||||
binaries.extend([
|
||||
{'path': 'bootstrap.exe'},
|
||||
{'path': 'bootstrapc.exe'},
|
||||
{'path': '%s.lib' % libcef_dll, 'out_path': 'libcef.lib'},
|
||||
])
|
||||
# yapf: enable
|
||||
|
||||
# yapf: disable
|
||||
resources = [
|
||||
@ -1157,43 +1162,6 @@ elif platform == 'windows':
|
||||
]
|
||||
# yapf: enable
|
||||
|
||||
cef_sandbox_lib = 'obj\\cef\\cef_sandbox.lib'
|
||||
sandbox_libs = [
|
||||
'obj\\base\\base.lib',
|
||||
'obj\\base\\base_static.lib',
|
||||
'obj\\base\\third_party\\cityhash\\cityhash\\*.obj',
|
||||
'obj\\base\\third_party\\double_conversion\\double_conversion.lib',
|
||||
'obj\\base\\third_party\\superfasthash\\superfasthash\\*.obj',
|
||||
'obj\\base\\win\\pe_image.lib',
|
||||
cef_sandbox_lib,
|
||||
'obj\\sandbox\\common\\*.obj',
|
||||
'obj\\sandbox\\win\\sandbox.lib',
|
||||
'obj\\sandbox\\win\\service_resolver\\*.obj',
|
||||
'obj\\third_party\\abseil-cpp\\absl\\base\\**\\*.obj',
|
||||
'obj\\third_party\\abseil-cpp\\absl\\debugging\\**\\*.obj',
|
||||
'obj\\third_party\\abseil-cpp\\absl\\numeric\\**\\*.obj',
|
||||
'obj\\third_party\\abseil-cpp\\absl\\strings\\**\\*.obj',
|
||||
'obj\\third_party\\abseil-cpp\\absl\\synchronization\\**\\*.obj',
|
||||
'obj\\third_party\\abseil-cpp\\absl\\time\\**\\*.obj',
|
||||
'obj\\third_party\\abseil-cpp\\absl\\types\\**\\*.obj',
|
||||
]
|
||||
|
||||
# Generate the cef_sandbox.lib merged library. A separate *_sandbox build
|
||||
# should exist when GN is_official_build=true.
|
||||
if mode in ('standard', 'minimal', 'sandbox') and not options.nosandbox:
|
||||
dirs = {
|
||||
'Debug': (build_dir_debug + '_sandbox', build_dir_debug),
|
||||
'Release': (build_dir_release + '_sandbox', build_dir_release)
|
||||
}
|
||||
for dir_name in dirs.keys():
|
||||
for src_dir in dirs[dir_name]:
|
||||
if path_exists(os.path.join(src_dir, cef_sandbox_lib)):
|
||||
dst_dir = os.path.join(output_dir, dir_name)
|
||||
make_dir(dst_dir, options.quiet)
|
||||
combine_libs(platform, src_dir, sandbox_libs,
|
||||
os.path.join(dst_dir, 'cef_sandbox.lib'))
|
||||
break
|
||||
|
||||
valid_build_dir = None
|
||||
|
||||
if mode == 'standard':
|
||||
@ -1214,23 +1182,22 @@ elif platform == 'windows':
|
||||
else:
|
||||
sys.stdout.write("No Debug build files.\n")
|
||||
|
||||
if mode != 'sandbox':
|
||||
# transfer Release files
|
||||
build_dir = build_dir_release
|
||||
if not options.allowpartial or path_exists(
|
||||
os.path.join(build_dir, libcef_dll)):
|
||||
valid_build_dir = build_dir
|
||||
dst_dir = os.path.join(output_dir, 'Release')
|
||||
copy_files_list(build_dir, dst_dir, binaries)
|
||||
# transfer Release files
|
||||
build_dir = build_dir_release
|
||||
if not options.allowpartial or path_exists(
|
||||
os.path.join(build_dir, libcef_dll)):
|
||||
valid_build_dir = build_dir
|
||||
dst_dir = os.path.join(output_dir, 'Release')
|
||||
copy_files_list(build_dir, dst_dir, binaries)
|
||||
|
||||
if not options.nosymbols:
|
||||
# create the symbol output directory
|
||||
symbol_output_dir = create_output_dir(
|
||||
output_dir_name + '_release_symbols', options.outputdir)
|
||||
# transfer contents
|
||||
copy_files_list(build_dir, symbol_output_dir, pdb_files)
|
||||
else:
|
||||
sys.stdout.write("No Release build files.\n")
|
||||
if not options.nosymbols:
|
||||
# create the symbol output directory
|
||||
symbol_output_dir = create_output_dir(
|
||||
output_dir_name + '_release_symbols', options.outputdir)
|
||||
# transfer contents
|
||||
copy_files_list(build_dir, symbol_output_dir, pdb_files)
|
||||
else:
|
||||
sys.stdout.write("No Release build files.\n")
|
||||
|
||||
if not valid_build_dir is None:
|
||||
# transfer resource files
|
||||
|
@ -1,73 +0,0 @@
|
||||
@echo off
|
||||
:: Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
|
||||
:: reserved. Use of this source code is governed by a BSD-style license
|
||||
:: that can be found in the LICENSE file.
|
||||
|
||||
:: Set up the environment for use with MSVS tools and then execute whatever
|
||||
:: was specified on the command-line.
|
||||
|
||||
set RC=
|
||||
|
||||
:: Support !! syntax for delayed variable expansion.
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
:: Require that platform is passed as the first argument.
|
||||
if "%1" == "win32" (
|
||||
set vcvarsbat=vcvars32.bat
|
||||
) else if "%1" == "win64" (
|
||||
set vcvarsbat=vcvars64.bat
|
||||
) else if "%1" == "winarm64" (
|
||||
set vcvarsbat=vcvarsamd64_arm64.bat
|
||||
) else (
|
||||
echo ERROR: Please specify a target platform: win32, win64 or winarm64
|
||||
set ERRORLEVEL=1
|
||||
goto end
|
||||
)
|
||||
|
||||
:: Check if vcvars is already provided via the environment.
|
||||
set vcvars="%CEF_VCVARS%"
|
||||
if %vcvars% == "none" goto found_vcvars
|
||||
if exist %vcvars% goto found_vcvars
|
||||
|
||||
:: Search for the default VS installation path.
|
||||
for %%x in (2022) do (
|
||||
for %%y in ("%PROGRAMFILES%" "%PROGRAMFILES(X86)%") do (
|
||||
for %%z in (Professional Enterprise Community BuildTools) do (
|
||||
set vcvars="%%~y\Microsoft Visual Studio\%%x\%%z\VC\Auxiliary\Build\%vcvarsbat%"
|
||||
if exist !vcvars! goto found_vcvars
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
echo ERROR: Failed to find vcvars
|
||||
set ERRORLEVEL=1
|
||||
goto end
|
||||
|
||||
:found_vcvars
|
||||
echo vcvars:
|
||||
echo %vcvars%
|
||||
|
||||
if not %vcvars% == "none" (
|
||||
:: Set this variable to keep VS2017 < 15.5 from changing the current working directory.
|
||||
set "VSCMD_START_DIR=%CD%"
|
||||
call %vcvars%
|
||||
)
|
||||
|
||||
echo PATH:
|
||||
echo %PATH%
|
||||
|
||||
:: Remove the first argument and execute the command.
|
||||
for /f "tokens=1,* delims= " %%a in ("%*") do set ALL_BUT_FIRST=%%b
|
||||
echo command:
|
||||
echo %ALL_BUT_FIRST%
|
||||
%ALL_BUT_FIRST%
|
||||
|
||||
:end
|
||||
endlocal & set RC=%ERRORLEVEL%
|
||||
goto omega
|
||||
|
||||
:returncode
|
||||
exit /B %RC%
|
||||
|
||||
:omega
|
||||
call :returncode %RC%
|
Reference in New Issue
Block a user