diff --git a/BUILD.gn b/BUILD.gn index dc19646c7..cd8419afe 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1028,6 +1028,15 @@ if (is_win) { } } +if (is_mac) { + static_library("cef_sandbox") { + sources = [ "libcef_dll/sandbox/sandbox_mac.mm" ] + # CEF sources use include paths relative to the CEF root directory. + include_dirs = [ "." ] + deps = [ "//sandbox/mac:seatbelt" ] + } +} + # # Service manifests. @@ -1568,6 +1577,7 @@ if (is_mac) { sources = invoker.helper_sources deps = [ + ":cef_sandbox", ":libcef_dll_wrapper", ] if (defined(invoker.helper_deps)) { @@ -1582,6 +1592,10 @@ if (is_mac) { ] info_plist_target = ":${app_name}_helper_plist" + + if (defined(invoker.helper_defines)) { + defines = invoker.helper_defines + } } bundle_data("${app_name}_framework_bundle_data") { @@ -1628,6 +1642,10 @@ if (is_mac) { libs = invoker.libs } + if (defined(invoker.defines)) { + defines = invoker.defines + } + info_plist_target = ":${app_name}_plist" } } @@ -1687,6 +1705,9 @@ if (is_mac) { helper_deps = [ ":libcef_dll_wrapper", ] + helper_defines = [ + "CEF_USE_SANDBOX", + ] info_plist = "tests/cefclient/resources/mac/Info.plist" sources = gypi_paths2.includes_mac + @@ -1710,6 +1731,9 @@ if (is_mac) { "AppKit.framework", "OpenGL.framework", ] + defines = [ + "CEF_USE_SANDBOX", + ] } @@ -1755,6 +1779,9 @@ if (is_mac) { helper_deps = [ ":libcef_dll_wrapper", ] + helper_defines = [ + "CEF_USE_SANDBOX", + ] info_plist = "tests/cefsimple/mac/Info.plist" sources = gypi_paths2.includes_mac + @@ -1769,6 +1796,9 @@ if (is_mac) { ":cefsimple_xibs", ":libcef_dll_wrapper", ] + defines = [ + "CEF_USE_SANDBOX", + ] } @@ -1816,6 +1846,9 @@ if (is_mac) { ":libcef_dll_wrapper", "//testing/gtest", ] + helper_defines = [ + "CEF_USE_SANDBOX", + ] info_plist = "tests/ceftests/resources/mac/Info.plist" sources = gypi_paths2.includes_mac + @@ -1837,6 +1870,9 @@ if (is_mac) { libs = [ "AppKit.framework", ] + defines = [ + "CEF_USE_SANDBOX", + ] } } else { # @@ -1893,6 +1929,10 @@ if (is_mac) { ":libcef_dll_wrapper", ] + defines = [ + "CEF_USE_SANDBOX", + ] + if (is_win) { sources += gypi_paths2.includes_win + gypi_paths2.shared_sources_win + @@ -1902,9 +1942,8 @@ if (is_mac) { configs -= [ "//build/config/win:console" ] configs += [ "//build/config/win:windowed" ] - defines = [ + defines += [ "CEF_USE_ATL", - "CEF_USE_SANDBOX", ] deps += [ @@ -1966,6 +2005,10 @@ if (is_mac) { ":libcef_dll_wrapper", ] + defines = [ + "CEF_USE_SANDBOX", + ] + if (is_win) { sources += gypi_paths2.includes_win + gypi_paths2.cefsimple_sources_win @@ -1974,10 +2017,6 @@ if (is_mac) { configs -= [ "//build/config/win:console" ] configs += [ "//build/config/win:windowed" ] - defines = [ - "CEF_USE_SANDBOX", - ] - deps += [ ":cef_sandbox", "//build/win:default_exe_manifest", @@ -2035,14 +2074,14 @@ if (is_mac) { "//testing/gtest", ] + defines = [ + "CEF_USE_SANDBOX", + ] + if (is_win) { sources += gypi_paths2.shared_sources_win + gypi_paths2.ceftests_sources_win - defines = [ - "CEF_USE_SANDBOX", - ] - deps += [ ":cef_sandbox", "//build/win:default_exe_manifest", diff --git a/cef_paths2.gypi b/cef_paths2.gypi index 39dcd42e3..da930d1a8 100644 --- a/cef_paths2.gypi +++ b/cef_paths2.gypi @@ -79,6 +79,7 @@ 'include/base/internal/cef_atomicops_atomicword_compat.h', 'include/base/internal/cef_atomicops_mac.h', 'include/cef_application_mac.h', + 'include/cef_sandbox_mac.h', 'include/internal/cef_mac.h', 'include/internal/cef_types_mac.h', ], diff --git a/cmake/cef_macros.cmake.in b/cmake/cef_macros.cmake.in index 59a5749fd..1b667e1cd 100644 --- a/cmake/cef_macros.cmake.in +++ b/cmake/cef_macros.cmake.in @@ -31,10 +31,11 @@ macro(PRINT_CEF_CONFIG) endif() if(OS_WINDOWS) - message(STATUS "CEF Windows sandbox: ${USE_SANDBOX}") message(STATUS "Visual Studio ATL support: ${USE_ATL}") endif() + message(STATUS "CEF sandbox: ${USE_SANDBOX}") + set(_libraries ${CEF_STANDARD_LIBS}) if(OS_WINDOWS AND USE_SANDBOX) list(APPEND _libraries ${CEF_SANDBOX_STANDARD_LIBS}) diff --git a/cmake/cef_variables.cmake.in b/cmake/cef_variables.cmake.in index 15894530f..6539765a5 100644 --- a/cmake/cef_variables.cmake.in +++ b/cmake/cef_variables.cmake.in @@ -66,6 +66,10 @@ list(APPEND CEF_COMPILER_DEFINES ) +# Configure use of the sandbox. +option(USE_SANDBOX "Enable or disable use of the sandbox." ON) + + # # Linux configuration. # @@ -217,6 +221,12 @@ if(OS_LINUX) icudtl.dat locales ) + + if(USE_SANDBOX) + list(APPEND CEF_COMPILER_DEFINES + CEF_USE_SANDBOX # Used by apps to test if the sandbox is enabled + ) + endif() endif() @@ -313,6 +323,16 @@ if(OS_MACOSX) set(CEF_BINARY_DIR "${_CEF_ROOT}/$") set(CEF_BINARY_DIR_DEBUG "${_CEF_ROOT}/Debug") set(CEF_BINARY_DIR_RELEASE "${_CEF_ROOT}/Release") + + if(USE_SANDBOX) + list(APPEND CEF_COMPILER_DEFINES + CEF_USE_SANDBOX # Used by apps to test if the sandbox is enabled + ) + + # CEF sandbox library paths. + set(CEF_SANDBOX_LIB_DEBUG "${CEF_BINARY_DIR_DEBUG}/cef_sandbox.a") + set(CEF_SANDBOX_LIB_RELEASE "${CEF_BINARY_DIR_RELEASE}/cef_sandbox.a") + endif() endif() @@ -329,8 +349,6 @@ if(OS_WINDOWS) set(CMAKE_CXX_FLAGS_RELEASE "") endif() - # Configure use of the sandbox. - option(USE_SANDBOX "Enable or disable use of the sandbox." ON) if(USE_SANDBOX) # Check if the current MSVC version is compatible with the cef_sandbox.lib # static library. For a list of all version numbers see diff --git a/include/cef_sandbox_mac.h b/include/cef_sandbox_mac.h new file mode 100644 index 000000000..fd1b981f3 --- /dev/null +++ b/include/cef_sandbox_mac.h @@ -0,0 +1,87 @@ +// Copyright (c) 2018 Marshall A. Greenblatt. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the name Chromium Embedded +// Framework nor the names of its contributors may be used to endorse +// or promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CEF_INCLUDE_CEF_SANDBOX_MAC_H_ +#define CEF_INCLUDE_CEF_SANDBOX_MAC_H_ +#pragma once + +#include "include/base/cef_build.h" + +#if defined(OS_MACOSX) + +#ifdef __cplusplus +extern "C" { +#endif + +// The sandbox is used to restrict sub-processes (renderer, plugin, GPU, etc) +// from directly accessing system resources. This helps to protect the user +// from untrusted and potentially malicious Web content. +// See http://www.chromium.org/developers/design-documents/sandbox for +// complete details. +// +// To enable the sandbox on macOS the following requirements must be met: +// 1. Link the helper process executable with the cef_sandbox static library. +// 2. Call the cef_sandbox_initialize() function at the beginning of the +// helper executable main() function and before loading the CEF framework +// library. See include/wrapper/cef_library_loader.h for example usage. + +/// +// Initialize the sandbox for this process. Returns the sandbox context +// handle on success or NULL on failure. The returned handle should be +// passed to cef_sandbox_destroy() immediately before process termination. +/// +void* cef_sandbox_initialize(int argc, char** argv); + +/// +// Destroy the specified sandbox context handle. +/// +void cef_sandbox_destroy(void* sandbox_context); + +#ifdef __cplusplus +} + +/// +// Scoped helper for managing the life span of a sandbox context handle. +/// +class CefScopedSandboxContext { + public: + CefScopedSandboxContext(); + ~CefScopedSandboxContext(); + + // Load the sandbox for this process. Returns true on success. + bool Initialize(int argc, char** argv); + + private: + void* sandbox_context_; +}; +#endif // __cplusplus + +#endif // defined(OS_MACOSX) + +#endif // CEF_INCLUDE_CEF_SANDBOX_MAC_H_ diff --git a/include/wrapper/cef_library_loader.h b/include/wrapper/cef_library_loader.h index 6dd6a773d..c15b8559d 100644 --- a/include/wrapper/cef_library_loader.h +++ b/include/wrapper/cef_library_loader.h @@ -66,22 +66,34 @@ int cef_unload_library(); // // Example usage in the main process: // +// #include "include/wrapper/cef_library_loader.h" +// // int main(int argc, char* argv[]) { +// // Dynamically load the CEF framework library. // CefScopedLibraryLoader library_loader; // if (!library_loader.LoadInMain()) // return 1; // -// // Rest of the function here... +// // Continue with CEF initialization... // } // // Example usage in the helper process: // +// #include "include/cef_sandbox_mac.h" +// #include "include/wrapper/cef_library_loader.h" +// // int main(int argc, char* argv[]) { +// // Initialize the macOS sandbox for this helper process. +// CefScopedSandboxContext sandbox_context; +// if (!sandbox_context.Initialize(argc, argv)) +// return 1; +// +// // Dynamically load the CEF framework library. // CefScopedLibraryLoader library_loader; // if (!library_loader.LoadInHelper()) // return 1; // -// // Rest of the function here... +// // Continue with CEF initialization... // } /// class CefScopedLibraryLoader { diff --git a/libcef/common/main_delegate.cc b/libcef/common/main_delegate.cc index cacdd6ba2..e215d2c32 100644 --- a/libcef/common/main_delegate.cc +++ b/libcef/common/main_delegate.cc @@ -98,6 +98,20 @@ void OverrideFrameworkBundlePath() { base::mac::SetOverrideFrameworkBundlePath(framework_path); } +void OverrideOuterBundlePath() { + base::FilePath bundle_path = util_mac::GetMainBundlePath(); + DCHECK(!bundle_path.empty()); + + base::mac::SetOverrideOuterBundlePath(bundle_path); +} + +void OverrideBaseBundleID() { + std::string bundle_id = util_mac::GetMainBundleID(); + DCHECK(!bundle_id.empty()); + + base::mac::SetBaseBundleID(bundle_id.c_str()); +} + void OverrideChildProcessPath() { base::FilePath child_process_path = base::CommandLine::ForCurrentProcess()->GetSwitchValuePath( @@ -436,29 +450,6 @@ bool CefMainDelegate::BasicStartupComplete(int* exit_code) { switches::kUncaughtExceptionStackSize, base::IntToString(settings.uncaught_exception_stack_size)); } - -#if defined(OS_MACOSX) - std::vector disable_features; - - // TODO: Remove once MacV2Sandbox is supported. See issue #2459. - if (features::kMacV2Sandbox.default_state == - base::FEATURE_ENABLED_BY_DEFAULT) { - disable_features.push_back(features::kMacV2Sandbox.name); - } - - if (!disable_features.empty()) { - DCHECK(!base::FeatureList::GetInstance()); - std::string disable_features_str = - command_line->GetSwitchValueASCII(switches::kDisableFeatures); - for (auto feature_str : disable_features) { - if (!disable_features_str.empty()) - disable_features_str += ","; - disable_features_str += feature_str; - } - command_line->AppendSwitchASCII(switches::kDisableFeatures, - disable_features_str); - } -#endif // defined(OS_MACOSX) } if (content_client_.application().get()) { @@ -517,6 +508,8 @@ bool CefMainDelegate::BasicStartupComplete(int* exit_code) { #if defined(OS_MACOSX) OverrideFrameworkBundlePath(); + OverrideOuterBundlePath(); + OverrideBaseBundleID(); #endif return false; diff --git a/libcef/common/util_mac.h b/libcef/common/util_mac.h index 61a80d0db..1d07209ea 100644 --- a/libcef/common/util_mac.h +++ b/libcef/common/util_mac.h @@ -6,6 +6,8 @@ #define CEF_LIBCEF_COMMON_UTIL_MAC_H_ #pragma once +#include + namespace base { class FilePath; } @@ -31,6 +33,13 @@ base::FilePath GetFrameworkResourcesDirectory(); // "myapp.app/Contents/MacOS/myapp"). base::FilePath GetMainProcessPath(); +// Returns the path to the top-level app bundle that contains the main process +// executable (e.g. "myapp.app"). +base::FilePath GetMainBundlePath(); + +// Returns the identifier for the top-level app bundle. +std::string GetMainBundleID(); + // Returns the path to the Resources directory inside the top-level app bundle // (e.g. "myapp.app/Contents/Resources"). May return an empty value if not // running in an app bundle. diff --git a/libcef/common/util_mac.mm b/libcef/common/util_mac.mm index 98c160933..5fea37ce7 100644 --- a/libcef/common/util_mac.mm +++ b/libcef/common/util_mac.mm @@ -9,19 +9,15 @@ #include "base/base_paths.h" #include "base/command_line.h" #include "base/files/file_path.h" +#include "base/mac/bundle_locations.h" #include "base/mac/foundation_util.h" #include "base/path_service.h" +#include "base/strings/sys_string_conversions.h" namespace util_mac { namespace { -// Returns the path to the top-level app bundle that contains the main process -// executable. -base::FilePath GetMainBundlePath() { - return base::mac::GetAppBundlePath(GetMainProcessPath()); -} - // Returns the path to the Frameworks directory inside the top-level app bundle. base::FilePath GetFrameworksPath() { base::FilePath bundle_path = GetMainBundlePath(); @@ -68,6 +64,15 @@ base::FilePath GetMainProcessPath() { return path; } +base::FilePath GetMainBundlePath() { + return base::mac::GetAppBundlePath(GetMainProcessPath()); +} + +std::string GetMainBundleID() { + NSBundle* bundle = base::mac::OuterBundle(); + return base::SysNSStringToUTF8([bundle bundleIdentifier]); +} + base::FilePath GetMainResourcesDirectory() { base::FilePath bundle_path = GetMainBundlePath(); if (bundle_path.empty()) diff --git a/libcef_dll/sandbox/sandbox_mac.mm b/libcef_dll/sandbox/sandbox_mac.mm new file mode 100644 index 000000000..cfdcae75e --- /dev/null +++ b/libcef_dll/sandbox/sandbox_mac.mm @@ -0,0 +1,65 @@ +// Copyright 2018 The Chromium Embedded Framework Authors. Portions Copyright +// 2018 the Chromium 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 +#include + +#include + +#include "sandbox/mac/seatbelt_exec.h" + +#include "include/cef_sandbox_mac.h" + +void* cef_sandbox_initialize(int argc, char** argv) { + uint32_t exec_path_size = 0; + int rv = _NSGetExecutablePath(NULL, &exec_path_size); + if (rv != -1) { + return NULL; + } + + std::unique_ptr exec_path(new char[exec_path_size]); + rv = _NSGetExecutablePath(exec_path.get(), &exec_path_size); + if (rv != 0) { + return NULL; + } + + sandbox::SeatbeltExecServer::CreateFromArgumentsResult seatbelt = + sandbox::SeatbeltExecServer::CreateFromArguments(exec_path.get(), argc, + argv); + if (seatbelt.sandbox_required) { + if (!seatbelt.server) { + fprintf(stderr, "Failed to create the seatbelt sandbox server.\n"); + return NULL; + } + if (!seatbelt.server->InitializeSandbox()) { + fprintf(stderr, "Failed to initialize the sandbox.\n"); + return NULL; + } + } + + auto* copy = new sandbox::SeatbeltExecServer::CreateFromArgumentsResult(); + copy->sandbox_required = seatbelt.sandbox_required; + copy->server.swap(seatbelt.server); + return copy; +} + +void cef_sandbox_destroy(void* sandbox_context) { + delete static_cast( + sandbox_context); +} + +CefScopedSandboxContext::CefScopedSandboxContext() : sandbox_context_(NULL) {} + +CefScopedSandboxContext::~CefScopedSandboxContext() { + if (sandbox_context_) { + cef_sandbox_destroy(sandbox_context_); + } +} + +bool CefScopedSandboxContext::Initialize(int argc, char** argv) { + if (sandbox_context_) + return false; + sandbox_context_ = cef_sandbox_initialize(argc, argv); + return !!sandbox_context_; +} diff --git a/tests/cefclient/CMakeLists.txt.in b/tests/cefclient/CMakeLists.txt.in index 417e20568..bf17d06ba 100644 --- a/tests/cefclient/CMakeLists.txt.in +++ b/tests/cefclient/CMakeLists.txt.in @@ -186,6 +186,12 @@ if(OS_MACOSX) OUTPUT_NAME ${CEF_HELPER_OUTPUT_NAME} ) + if(USE_SANDBOX) + # Logical target used to link the cef_sandbox library. + ADD_LOGICAL_TARGET("cef_sandbox_lib" "${CEF_SANDBOX_LIB_DEBUG}" "${CEF_SANDBOX_LIB_RELEASE}") + target_link_libraries(${CEF_HELPER_TARGET} cef_sandbox_lib) + endif() + # Main executable target. add_executable(${CEF_TARGET} MACOSX_BUNDLE ${CEFCLIENT_RESOURCES_SRCS} ${CEFCLIENT_SRCS}) SET_EXECUTABLE_TARGET_PROPERTIES(${CEF_TARGET}) diff --git a/tests/cefclient/cefclient_gtk.cc b/tests/cefclient/cefclient_gtk.cc index 57938ae05..362c7695a 100644 --- a/tests/cefclient/cefclient_gtk.cc +++ b/tests/cefclient/cefclient_gtk.cc @@ -87,6 +87,13 @@ int RunMain(int argc, char* argv[]) { CefSettings settings; +// When generating projects with CMake the CEF_USE_SANDBOX value will be defined +// automatically. Pass -DUSE_SANDBOX=OFF to the CMake command-line to disable +// use of the sandbox. +#if !defined(CEF_USE_SANDBOX) + settings.no_sandbox = true; +#endif + // Populate the settings based on command line arguments. context->PopulateSettings(&settings); diff --git a/tests/cefclient/cefclient_mac.mm b/tests/cefclient/cefclient_mac.mm index 9f829a942..b61389a8d 100644 --- a/tests/cefclient/cefclient_mac.mm +++ b/tests/cefclient/cefclient_mac.mm @@ -368,6 +368,13 @@ int RunMain(int argc, char* argv[]) { CefSettings settings; +// When generating projects with CMake the CEF_USE_SANDBOX value will be defined +// automatically. Pass -DUSE_SANDBOX=OFF to the CMake command-line to disable +// use of the sandbox. +#if !defined(CEF_USE_SANDBOX) + settings.no_sandbox = true; +#endif + // Populate the settings based on command line arguments. context->PopulateSettings(&settings); diff --git a/tests/cefclient/cefclient_win.cc b/tests/cefclient/cefclient_win.cc index d4950d265..de291282e 100644 --- a/tests/cefclient/cefclient_win.cc +++ b/tests/cefclient/cefclient_win.cc @@ -25,8 +25,8 @@ // #define CEF_USE_SANDBOX 1 #if defined(CEF_USE_SANDBOX) -// The cef_sandbox.lib static library is currently built with VS2015. It may not -// link successfully with other VS versions. +// The cef_sandbox.lib static library may not link successfully with all VS +// versions. #pragma comment(lib, "cef_sandbox.lib") #endif diff --git a/tests/cefsimple/CMakeLists.txt.in b/tests/cefsimple/CMakeLists.txt.in index 0c415a137..471f1d82f 100644 --- a/tests/cefsimple/CMakeLists.txt.in +++ b/tests/cefsimple/CMakeLists.txt.in @@ -101,6 +101,12 @@ if(OS_MACOSX) OUTPUT_NAME ${CEF_HELPER_OUTPUT_NAME} ) + if(USE_SANDBOX) + # Logical target used to link the cef_sandbox library. + ADD_LOGICAL_TARGET("cef_sandbox_lib" "${CEF_SANDBOX_LIB_DEBUG}" "${CEF_SANDBOX_LIB_RELEASE}") + target_link_libraries(${CEF_HELPER_TARGET} cef_sandbox_lib) + endif() + # Main executable target. add_executable(${CEF_TARGET} MACOSX_BUNDLE ${CEFSIMPLE_RESOURCES_SRCS} ${CEFSIMPLE_SRCS}) SET_EXECUTABLE_TARGET_PROPERTIES(${CEF_TARGET}) diff --git a/tests/cefsimple/cefsimple_linux.cc b/tests/cefsimple/cefsimple_linux.cc index 41774defb..94a63f77a 100644 --- a/tests/cefsimple/cefsimple_linux.cc +++ b/tests/cefsimple/cefsimple_linux.cc @@ -49,6 +49,13 @@ int main(int argc, char* argv[]) { // Specify CEF global settings here. CefSettings settings; +// When generating projects with CMake the CEF_USE_SANDBOX value will be defined +// automatically. Pass -DUSE_SANDBOX=OFF to the CMake command-line to disable +// use of the sandbox. +#if !defined(CEF_USE_SANDBOX) + settings.no_sandbox = true; +#endif + // SimpleApp implements application-level callbacks for the browser process. // It will create the first browser instance in OnContextInitialized() after // CEF has initialized. diff --git a/tests/cefsimple/cefsimple_mac.mm b/tests/cefsimple/cefsimple_mac.mm index 9506dd279..a60b53c6f 100644 --- a/tests/cefsimple/cefsimple_mac.mm +++ b/tests/cefsimple/cefsimple_mac.mm @@ -128,6 +128,13 @@ int main(int argc, char* argv[]) { // Specify CEF global settings here. CefSettings settings; +// When generating projects with CMake the CEF_USE_SANDBOX value will be defined +// automatically. Pass -DUSE_SANDBOX=OFF to the CMake command-line to disable +// use of the sandbox. +#if !defined(CEF_USE_SANDBOX) + settings.no_sandbox = true; +#endif + // SimpleApp implements application-level callbacks for the browser process. // It will create the first browser instance in OnContextInitialized() after // CEF has initialized. diff --git a/tests/cefsimple/cefsimple_win.cc b/tests/cefsimple/cefsimple_win.cc index a5ba95c43..1e9af869d 100644 --- a/tests/cefsimple/cefsimple_win.cc +++ b/tests/cefsimple/cefsimple_win.cc @@ -14,8 +14,8 @@ // #define CEF_USE_SANDBOX 1 #if defined(CEF_USE_SANDBOX) -// The cef_sandbox.lib static library is currently built with VS2013. It may not -// link successfully with other VS versions. +// The cef_sandbox.lib static library may not link successfully with all VS +// versions. #pragma comment(lib, "cef_sandbox.lib") #endif diff --git a/tests/cefsimple/process_helper_mac.cc b/tests/cefsimple/process_helper_mac.cc index fa1fc6940..f1f42c337 100644 --- a/tests/cefsimple/process_helper_mac.cc +++ b/tests/cefsimple/process_helper_mac.cc @@ -5,8 +5,22 @@ #include "include/cef_app.h" #include "include/wrapper/cef_library_loader.h" +// When generating projects with CMake the CEF_USE_SANDBOX value will be defined +// automatically. Pass -DUSE_SANDBOX=OFF to the CMake command-line to disable +// use of the sandbox. +#if defined(CEF_USE_SANDBOX) +#include "include/cef_sandbox_mac.h" +#endif + // Entry point function for sub-processes. int main(int argc, char* argv[]) { +#if defined(CEF_USE_SANDBOX) + // Initialize the macOS sandbox for this helper process. + CefScopedSandboxContext sandbox_context; + if (!sandbox_context.Initialize(argc, argv)) + return 1; +#endif + // Load the CEF framework library at runtime instead of linking directly // as required by the macOS sandbox implementation. CefScopedLibraryLoader library_loader; diff --git a/tests/ceftests/CMakeLists.txt.in b/tests/ceftests/CMakeLists.txt.in index cc89bde40..af0403817 100644 --- a/tests/ceftests/CMakeLists.txt.in +++ b/tests/ceftests/CMakeLists.txt.in @@ -121,6 +121,12 @@ if(OS_MACOSX) OUTPUT_NAME ${CEF_HELPER_OUTPUT_NAME} ) + if(USE_SANDBOX) + # Logical target used to link the cef_sandbox library. + ADD_LOGICAL_TARGET("cef_sandbox_lib" "${CEF_SANDBOX_LIB_DEBUG}" "${CEF_SANDBOX_LIB_RELEASE}") + target_link_libraries(${CEF_HELPER_TARGET} cef_sandbox_lib) + endif() + # Main executable target. add_executable(${CEF_TARGET} MACOSX_BUNDLE ${UNITTESTS_RESOURCES_SRCS} ${UNITTESTS_SRCS}) SET_EXECUTABLE_TARGET_PROPERTIES(${CEF_TARGET}) diff --git a/tests/ceftests/run_all_unittests.cc b/tests/ceftests/run_all_unittests.cc index 71b37b14b..30b0d850a 100644 --- a/tests/ceftests/run_all_unittests.cc +++ b/tests/ceftests/run_all_unittests.cc @@ -33,8 +33,15 @@ #include "include/wrapper/cef_library_loader.h" #endif -#if defined(OS_WIN) +// 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) #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") #endif namespace { @@ -121,7 +128,7 @@ int main(int argc, char* argv[]) { void* windows_sandbox_info = NULL; -#if defined(OS_WIN) +#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(); @@ -153,6 +160,11 @@ int main(int argc, char* argv[]) { #endif CefSettings settings; + +#if !defined(CEF_USE_SANDBOX) + settings.no_sandbox = true; +#endif + test_suite.GetSettings(settings); #if defined(OS_MACOSX) diff --git a/tests/shared/process_helper_mac.cc b/tests/shared/process_helper_mac.cc index c22b99950..775dd4e9f 100644 --- a/tests/shared/process_helper_mac.cc +++ b/tests/shared/process_helper_mac.cc @@ -3,14 +3,28 @@ // be found in the LICENSE file. #include "include/cef_app.h" -#import "include/wrapper/cef_library_loader.h" +#include "include/wrapper/cef_library_loader.h" #include "tests/shared/common/client_app_other.h" #include "tests/shared/renderer/client_app_renderer.h" +// When generating projects with CMake the CEF_USE_SANDBOX value will be defined +// automatically. Pass -DUSE_SANDBOX=OFF to the CMake command-line to disable +// use of the sandbox. +#if defined(CEF_USE_SANDBOX) +#include "include/cef_sandbox_mac.h" +#endif + namespace client { int RunMain(int argc, char* argv[]) { +#if defined(CEF_USE_SANDBOX) + // Initialize the macOS sandbox for this helper process. + CefScopedSandboxContext sandbox_context; + if (!sandbox_context.Initialize(argc, argv)) + return 1; +#endif + // Load the CEF framework library at runtime instead of linking directly // as required by the macOS sandbox implementation. CefScopedLibraryLoader library_loader; diff --git a/tools/automate/automate-git.py b/tools/automate/automate-git.py index d7c81cb60..769549ee0 100644 --- a/tools/automate/automate-git.py +++ b/tools/automate/automate-git.py @@ -1002,11 +1002,6 @@ if options.clientdistrib or options.clientdistribonly: parser.print_help(sys.stderr) sys.exit() -if platform != 'windows' and (options.sandboxdistrib or - options.sandboxdistribonly): - print 'The sandbox distribution is only supported on Windows.' - sys.exit() - # CEF branch. if options.branch != 'trunk' and not options.branch.isdigit(): print 'Invalid branch value: %s' % (options.branch) @@ -1033,6 +1028,9 @@ branch_is_newer_than_2785 = (cef_branch == 'trunk' or int(cef_branch) > 2785) # True if the requested branch is 3029 or older. branch_is_3029_or_older = (cef_branch != 'trunk' and int(cef_branch) <= 3029) +# True if the requested branch is newer than 3497. +branch_is_newer_than_3497 = (cef_branch == 'trunk' or int(cef_branch) > 3497) + # Enable GN by default for branches newer than 2785. if branch_is_newer_than_2785 and not 'CEF_USE_GN' in os.environ.keys(): os.environ['CEF_USE_GN'] = '1' @@ -1082,6 +1080,16 @@ if platform == 'macosx' and not options.x64build and branch_is_2272_or_newer: 'newer. Add --x64-build flag to generate a 64-bit build.' sys.exit() +# Platforms that build a cef_sandbox library. +sandbox_lib_platforms = ['windows'] +if branch_is_newer_than_3497: + sandbox_lib_platforms.append('macosx') + +if not platform in sandbox_lib_platforms and (options.sandboxdistrib or + options.sandboxdistribonly): + print 'The sandbox distribution is not supported on this platform.' + sys.exit() + # Options that force the sources to change. force_change = options.forceclean or options.forceupdate @@ -1519,8 +1527,8 @@ if not options.nobuild and (chromium_checkout_changed or \ os.path.join(download_dir, 'build-%s-debug.log' % (cef_branch)) \ if options.buildlogfile else None) - if use_gn and platform == 'windows': - # Make the separate cef_sandbox.lib build when GN is_official_build=true. + if use_gn and platform in sandbox_lib_platforms: + # Make the separate cef_sandbox build when GN is_official_build=true. build_path += '_sandbox' if os.path.exists(os.path.join(chromium_src_dir, build_path)): args_path = os.path.join(chromium_src_dir, build_path, 'args.gn') @@ -1541,8 +1549,8 @@ if not options.nobuild and (chromium_checkout_changed or \ os.path.join(download_dir, 'build-%s-release.log' % (cef_branch)) \ if options.buildlogfile else None) - if use_gn and platform == 'windows': - # Make the separate cef_sandbox.lib build when GN is_official_build=true. + if use_gn and platform in sandbox_lib_platforms: + # Make the separate cef_sandbox build when GN is_official_build=true. build_path += '_sandbox' if os.path.exists(os.path.join(chromium_src_dir, build_path)): args_path = os.path.join(chromium_src_dir, build_path, 'args.gn') diff --git a/tools/gn_args.py b/tools/gn_args.py index b99488f7c..fe3ef7126 100644 --- a/tools/gn_args.py +++ b/tools/gn_args.py @@ -436,10 +436,9 @@ def GetConfigArgs(args, is_debug, cpu): return result -def WinGetConfigArgsSandbox(args, is_debug, cpu): +def GetConfigArgsSandbox(platform, args, is_debug, cpu): """ - Return merged GN args for the Windows cef_sandbox.lib configuration and - validate. + Return merged GN args for the cef_sandbox configuration and validate. """ add_args = { # Avoid libucrt.lib linker errors. @@ -520,13 +519,14 @@ def GetAllPlatformConfigs(build_args): result['Debug_GN_' + cpu] = GetConfigArgs(args, True, cpu) result['Release_GN_' + cpu] = GetConfigArgs(args, False, cpu) - if platform == 'windows' and GetArgValue(args, 'is_official_build'): + if platform in ('windows', 'macosx') and GetArgValue( + args, 'is_official_build'): # Build cef_sandbox.lib with a different configuration. if create_debug: - result['Debug_GN_' + cpu + '_sandbox'] = WinGetConfigArgsSandbox( - args, True, cpu) - result['Release_GN_' + cpu + '_sandbox'] = WinGetConfigArgsSandbox( - args, False, cpu) + result['Debug_GN_' + cpu + '_sandbox'] = GetConfigArgsSandbox( + platform, args, True, cpu) + result['Release_GN_' + cpu + '_sandbox'] = GetConfigArgsSandbox( + platform, args, False, cpu) return result diff --git a/tools/make_distrib.py b/tools/make_distrib.py index 8c80abb68..8c42e730c 100644 --- a/tools/make_distrib.py +++ b/tools/make_distrib.py @@ -301,16 +301,19 @@ def copy_files_list(build_dir, dst_dir, paths): raise Exception('Missing required path: %s' % source_path) -def combine_libs(build_dir, libs, dest_lib): +def combine_libs(platform, build_dir, libs, dest_lib): """ Combine multiple static libraries into a single static library. """ - cmdline = 'msvs_env.bat win%s python combine_libs.py -o "%s"' % ( - platform_arch, dest_lib) + if platform == 'windows': + cmdline = 'msvs_env.bat win%s python combine_libs.py -o "%s"' % ( + platform_arch, dest_lib) + else: + cmdline = 'libtool -static -o "%s"' % dest_lib 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) - cmdline = cmdline + ' "%s"' % path + cmdline += ' "%s"' % path run(cmdline, os.path.join(cef_dir, 'tools')) @@ -745,7 +748,7 @@ if platform == 'windows': 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(src_dir, sandbox_libs, + combine_libs(platform, src_dir, sandbox_libs, os.path.join(dst_dir, 'cef_sandbox.lib')) break @@ -849,6 +852,30 @@ elif platform == 'macosx': framework_dsym = '%s.dSYM' % framework_name cefclient_app = 'cefclient.app' + cef_sandbox_lib = 'obj/cef/libcef_sandbox.a' + sandbox_libs = [ + cef_sandbox_lib, + 'obj/sandbox/mac/libseatbelt.a', + 'obj/sandbox/mac/libseatbelt_proto.a', + 'obj/third_party/protobuf/libprotobuf_lite.a', + ] + + # Generate the cef_sandbox.a merged library. A separate *_sandbox build + # should exist when GN is_official_build=true. + if mode in ('standard', 'minimal', 'sandbox'): + 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.a')) + break + valid_build_dir = None if mode == 'standard': @@ -879,42 +906,44 @@ elif platform == 'macosx': else: sys.stdout.write("No Debug build files.\n") - # transfer Release files - build_dir = build_dir_release - if not options.allowpartial or path_exists( - os.path.join(build_dir, cefclient_app)): - valid_build_dir = build_dir - dst_dir = os.path.join(output_dir, 'Release') - make_dir(dst_dir, options.quiet) - framework_src_dir = os.path.join( - build_dir, '%s/Contents/Frameworks/%s.framework/Versions/A' % - (cefclient_app, framework_name)) - if mode != 'client': - framework_dst_dir = os.path.join(dst_dir, '%s.framework' % framework_name) + if mode != 'sandbox': + # transfer Release files + build_dir = build_dir_release + if not options.allowpartial or path_exists( + os.path.join(build_dir, cefclient_app)): + valid_build_dir = build_dir + dst_dir = os.path.join(output_dir, 'Release') + make_dir(dst_dir, options.quiet) + framework_src_dir = os.path.join( + build_dir, '%s/Contents/Frameworks/%s.framework/Versions/A' % + (cefclient_app, framework_name)) + if mode != 'client': + framework_dst_dir = os.path.join(dst_dir, + '%s.framework' % framework_name) + else: + copy_dir( + os.path.join(build_dir, cefclient_app), + os.path.join(dst_dir, cefclient_app), options.quiet) + # Replace the versioned framework with an unversioned framework in the sample app. + framework_dst_dir = os.path.join( + dst_dir, '%s/Contents/Frameworks/%s.framework' % (cefclient_app, + framework_name)) + remove_dir(framework_dst_dir, options.quiet) + copy_dir(framework_src_dir, framework_dst_dir, options.quiet) + + if not options.nosymbols: + # create the symbol output directory + symbol_output_dir = create_output_dir( + output_dir_name + '_release_symbols', options.outputdir) + + # The real dSYM already exists, just copy it to the output directory. + # dSYMs are only generated when is_official_build=true or enable_dsyms=true. + # See //build/config/mac/symbols.gni. + copy_dir( + os.path.join(build_dir, framework_dsym), + os.path.join(symbol_output_dir, framework_dsym), options.quiet) else: - copy_dir( - os.path.join(build_dir, cefclient_app), - os.path.join(dst_dir, cefclient_app), options.quiet) - # Replace the versioned framework with an unversioned framework in the sample app. - framework_dst_dir = os.path.join( - dst_dir, '%s/Contents/Frameworks/%s.framework' % (cefclient_app, - framework_name)) - remove_dir(framework_dst_dir, options.quiet) - copy_dir(framework_src_dir, framework_dst_dir, options.quiet) - - if not options.nosymbols: - # create the symbol output directory - symbol_output_dir = create_output_dir( - output_dir_name + '_release_symbols', options.outputdir) - - # The real dSYM already exists, just copy it to the output directory. - # dSYMs are only generated when is_official_build=true or enable_dsyms=true. - # See //build/config/mac/symbols.gni. - copy_dir( - os.path.join(build_dir, framework_dsym), - os.path.join(symbol_output_dir, framework_dsym), options.quiet) - else: - sys.stdout.write("No Release build files.\n") + sys.stdout.write("No Release build files.\n") if mode == 'standard' or mode == 'minimal': # transfer include files