diff --git a/BUILD.gn b/BUILD.gn index 3ded3fdb4..a0f80dfe4 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1229,7 +1229,7 @@ if (is_win) { } if (is_mac) { - static_library("cef_sandbox") { + shared_library("cef_sandbox") { sources = [ "libcef_dll/sandbox/sandbox_mac.mm" ] configs += [ ":libcef_includes_config" ] deps = [ @@ -1634,6 +1634,33 @@ if (is_mac) { ] } + # We need to copy the CEF libraries so that the bundle_data dependencies have + # a "copy" target type. Otherwise for "shared_library" target types it will + # try to link things into the CEF Framework when we want to keep the libraries + # separate instead. + copy("cef_library_copy") { + sources = [ + "$root_out_dir/libcef_sandbox.dylib", + ] + outputs = [ "$root_out_dir/cef_intermediates/{{source_file_part}}" ] + deps = [ + ":cef_sandbox", + ] + } + + # Add the CEF .dylibs in the MODULE_DIR of the Framework app bundle. + bundle_data("cef_framework_cef_binaries") { + sources = [ + "$root_out_dir/cef_intermediates/libcef_sandbox.dylib", + ] + outputs = [ + "{{bundle_contents_dir}}/Libraries/{{source_file_part}}", + ] + public_deps = [ + ":cef_library_copy", + ] + } + # Add the SwiftShader .dylibs in the MODULE_DIR of the Framework app bundle. bundle_data("cef_framework_swiftshader_binaries") { sources = [ @@ -1664,6 +1691,7 @@ if (is_mac) { deps = libcef_deps_common + [ ":cef_framework_angle_binaries", + ":cef_framework_cef_binaries", ":cef_framework_resources", ":cef_framework_swiftshader_binaries", ] @@ -1828,7 +1856,6 @@ if (is_mac) { deps = [ ":cef_make_headers", - ":cef_sandbox", ":libcef_dll_wrapper", ] if (defined(invoker.helper_deps)) { diff --git a/cef_paths2.gypi b/cef_paths2.gypi index 8306e352b..83fe00690 100644 --- a/cef_paths2.gypi +++ b/cef_paths2.gypi @@ -166,6 +166,7 @@ ], 'libcef_dll_wrapper_sources_mac': [ 'libcef_dll/wrapper/cef_library_loader_mac.mm', + 'libcef_dll/wrapper/cef_scoped_sandbox_context_mac.mm', 'libcef_dll/wrapper/libcef_dll_dylib.cc', ], 'shared_sources_browser': [ diff --git a/include/cef_sandbox_mac.h b/include/cef_sandbox_mac.h index 42d1b4457..f3690e894 100644 --- a/include/cef_sandbox_mac.h +++ b/include/cef_sandbox_mac.h @@ -48,14 +48,8 @@ extern "C" { /// The sandbox is used to restrict sub-processes (renderer, 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. +/// https://bitbucket.org/chromiumembedded/cef/wiki/SandboxSetup.md for usage +/// details. See include/wrapper/cef_library_loader.h for example usage. /// /// @@ -76,7 +70,7 @@ CEF_EXPORT void cef_sandbox_destroy(void* sandbox_context); /// /// Scoped helper for managing the life span of a sandbox context handle. /// -class CEF_EXPORT CefScopedSandboxContext { +class CefScopedSandboxContext final { public: CefScopedSandboxContext(); ~CefScopedSandboxContext(); @@ -87,7 +81,8 @@ class CEF_EXPORT CefScopedSandboxContext { bool Initialize(int argc, char** argv); private: - void* sandbox_context_; + void* library_handle_ = nullptr; + void* sandbox_context_ = nullptr; }; #endif // __cplusplus diff --git a/include/cef_sandbox_win.h b/include/cef_sandbox_win.h index 4b48ead40..37101fd26 100644 --- a/include/cef_sandbox_win.h +++ b/include/cef_sandbox_win.h @@ -50,38 +50,9 @@ extern "C" { /// The sandbox is used to restrict sub-processes (renderer, 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 +/// https://bitbucket.org/chromiumembedded/cef/wiki/SandboxSetup.md for usage /// details. /// -/// 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. -/// /// /// Create the sandbox information object for this process. It is safe to create @@ -101,7 +72,7 @@ void cef_sandbox_info_destroy(void* sandbox_info); /// /// Manages the life span of a sandbox information object. /// -class CefScopedSandboxInfo { +class CefScopedSandboxInfo final { public: CefScopedSandboxInfo() { sandbox_info_ = cef_sandbox_info_create(); } ~CefScopedSandboxInfo() { cef_sandbox_info_destroy(sandbox_info_); } diff --git a/include/wrapper/cef_library_loader.h b/include/wrapper/cef_library_loader.h index 4fa8343fd..604148669 100644 --- a/include/wrapper/cef_library_loader.h +++ b/include/wrapper/cef_library_loader.h @@ -84,7 +84,8 @@ int cef_unload_library(void); /// #include "include/wrapper/cef_library_loader.h" /// /// int main(int argc, char* argv[]) { -/// // Initialize the macOS sandbox for this helper process. +/// // Dynamically load and initialize the macOS sandbox for this helper +/// // process. /// CefScopedSandboxContext sandbox_context; /// if (!sandbox_context.Initialize(argc, argv)) /// return 1; diff --git a/libcef_dll/sandbox/sandbox_mac.mm b/libcef_dll/sandbox/sandbox_mac.mm index b8d2602c2..3b65702d7 100644 --- a/libcef_dll/sandbox/sandbox_mac.mm +++ b/libcef_dll/sandbox/sandbox_mac.mm @@ -47,19 +47,3 @@ 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/libcef_dll/wrapper/cef_scoped_sandbox_context_mac.mm b/libcef_dll/wrapper/cef_scoped_sandbox_context_mac.mm new file mode 100644 index 000000000..497bdb20e --- /dev/null +++ b/libcef_dll/wrapper/cef_scoped_sandbox_context_mac.mm @@ -0,0 +1,113 @@ +// Copyright 2025 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 + +#include +#include + +#include "include/cef_sandbox_mac.h" + +namespace { + +// Relative path to the library from the Helper executable. +constexpr char kLibraryPath[] = + "../../../Chromium Embedded Framework.framework/" + "Libraries/libcef_sandbox.dylib"; + +std::string GetLibraryPath() { + uint32_t exec_path_size = 0; + int rv = _NSGetExecutablePath(NULL, &exec_path_size); + if (rv != -1) { + return std::string(); + } + + std::unique_ptr exec_path(new char[exec_path_size]); + rv = _NSGetExecutablePath(exec_path.get(), &exec_path_size); + if (rv != 0) { + return std::string(); + } + + // Get the directory path of the executable. + const char* parent_dir = dirname(exec_path.get()); + if (!parent_dir) { + return std::string(); + } + + // Append the relative path to the library. + std::stringstream ss; + ss << parent_dir << "/" << kLibraryPath; + return ss.str(); +} + +void* LoadLibrary(const char* path) { + void* handle = dlopen(path, RTLD_LAZY | RTLD_LOCAL | RTLD_FIRST); + if (!handle) { + fprintf(stderr, "dlopen %s: %s\n", path, dlerror()); + return nullptr; + } + return handle; +} + +void UnloadLibrary(void* handle) { + // Returns 0 on success. + if (dlclose(handle)) { + fprintf(stderr, "dlclose: %s\n", dlerror()); + } +} + +void* GetLibraryPtr(void* handle, const char* name) { + void* ptr = dlsym(handle, name); + if (!ptr) { + fprintf(stderr, "dlsym: %s\n", dlerror()); + } + return ptr; +} + +void* SandboxInitialize(void* handle, int argc, char** argv) { + if (auto* ptr = (decltype(&cef_sandbox_initialize))GetLibraryPtr( + handle, "cef_sandbox_initialize")) { + return ptr(argc, argv); + } + return nullptr; +} + +void SandboxDestroy(void* handle, void* sandbox_context) { + if (auto* ptr = (decltype(&cef_sandbox_destroy))GetLibraryPtr( + handle, "cef_sandbox_destroy")) { + ptr(sandbox_context); + } +} + +} // namespace + +CefScopedSandboxContext::CefScopedSandboxContext() = default; + +CefScopedSandboxContext::~CefScopedSandboxContext() { + if (library_handle_) { + if (sandbox_context_) { + SandboxDestroy(library_handle_, sandbox_context_); + } + UnloadLibrary(library_handle_); + } +} + +bool CefScopedSandboxContext::Initialize(int argc, char** argv) { + if (!library_handle_) { + const std::string& library_path = GetLibraryPath(); + if (library_path.empty()) { + fprintf(stderr, "App does not have the expected bundle structure.\n"); + return false; + } + library_handle_ = LoadLibrary(library_path.c_str()); + } + if (!library_handle_ || sandbox_context_) { + return false; + } + sandbox_context_ = SandboxInitialize(library_handle_, argc, argv); + return !!sandbox_context_; +} diff --git a/tools/automate/automate-git.py b/tools/automate/automate-git.py index 772512db1..207ca237d 100644 --- a/tools/automate/automate-git.py +++ b/tools/automate/automate-git.py @@ -757,13 +757,13 @@ parser.add_option( action='store_true', dest='sandboxdistrib', default=False, - help='Create a cef_sandbox static library distribution.') + help='Create a sandbox distribution.') parser.add_option( '--sandbox-distrib-only', action='store_true', dest='sandboxdistribonly', default=False, - help='Create a cef_sandbox static library distribution only.') + help='Create a sandbox distribution only.') parser.add_option( '--tools-distrib', action='store_true', @@ -911,18 +911,23 @@ if platform == 'mac' and not (options.x64build or options.arm64build): 'Add --x64-build or --arm64-build flag to generate a 64-bit build.') sys.exit(1) -# Platforms that build a cef_sandbox library in a separate output directory. -sandbox_lib_platforms = ['mac'] +# Platforms that build a cef_sandbox static library in a separate output directory. +sandbox_static_platforms = [] + +# Platforms that build a cef_sandbox shared library in the same output directory. +sandbox_shared_platforms = [] # Platforms that build a bootstrap executable in the same output directory. bootstrap_exe_platforms = [] if branch_is_7151_or_older: - sandbox_lib_platforms.append('windows') + sandbox_static_platforms.extend(['windows', 'mac']) else: bootstrap_exe_platforms.append('windows') + sandbox_shared_platforms.append('mac') -if not platform in sandbox_lib_platforms and \ +if not platform in sandbox_static_platforms and \ + not platform in sandbox_shared_platforms and \ not platform in bootstrap_exe_platforms and \ (options.sandboxdistrib or options.sandboxdistribonly): print('The sandbox distribution is not supported on this platform.') @@ -1362,7 +1367,7 @@ 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 platform in sandbox_lib_platforms: + if platform in sandbox_static_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)): @@ -1383,7 +1388,7 @@ 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 platform in sandbox_lib_platforms: + if platform in sandbox_static_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)): diff --git a/tools/distrib/mac/README.sandbox.txt b/tools/distrib/mac/README.sandbox.txt index 8d2258d91..3bf7d0397 100644 --- a/tools/distrib/mac/README.sandbox.txt +++ b/tools/distrib/mac/README.sandbox.txt @@ -1,9 +1,9 @@ CONTENTS -------- -Debug Contains the Debug build of cef_sandbox.a. +Debug Contains the Debug build of libcef_sandbox.dylib -Release Contains the Release build of cef_sandbox.a. +Release Contains the Release build of libcef_sandbox.dylib USAGE @@ -11,4 +11,4 @@ USAGE Please visit the CEF Website for usage information. -https://bitbucket.org/chromiumembedded/cef/ +https://bitbucket.org/chromiumembedded/cef/wiki/SandboxSetup.md diff --git a/tools/gn_args.py b/tools/gn_args.py index 16a3e0f3e..d194ce35e 100644 --- a/tools/gn_args.py +++ b/tools/gn_args.py @@ -518,47 +518,6 @@ def GetConfigArgs(args, is_debug, cpu): return result -def GetConfigArgsSandbox(platform, args, is_debug, cpu): - """ - Return merged GN args for the cef_sandbox configuration and validate. - """ - add_args = { - # Avoid libucrt.lib linker errors. - 'use_allocator_shim': False, - - # PartitionAlloc is selected as the default allocator in some cases. - # We can't use it because it requires use_allocator_shim=true. - 'use_partition_alloc_as_malloc': False, - 'use_partition_alloc': False, - - # These require use_partition_alloc_as_malloc=true, so disable them. - 'enable_backup_ref_ptr_support': False, - 'enable_dangling_raw_ptr_checks': False, - 'enable_dangling_raw_ptr_feature_flag': False, - - # Avoid /LTCG linker warnings and generate smaller lib files. - 'is_official_build': False, - - # Disable use of thin archives with lld. Thin archives contain just the - # symbol table and the path to find the original .o files. They are - # generally incompatible with default platform ld/link versions and - # shouldn't be distributed due to the external .o file dependencies. - 'use_thin_archives': False, - } - - if not is_debug: - # Disable DCHECKs in Release builds. - add_args['dcheck_always_on'] = False - - result = MergeDicts(args, add_args, { - 'is_debug': is_debug, - 'target_cpu': cpu, - }) - - ValidateArgs(result, is_debug) - return result - - def LinuxSysrootExists(cpu): """ Returns true if the sysroot for the specified |cpu| architecture exists. @@ -632,14 +591,6 @@ def GetAllPlatformConfigs(build_args, quiet=False): result['Debug_GN_' + cpu] = GetConfigArgs(args, True, cpu) result['Release_GN_' + cpu] = GetConfigArgs(args, False, cpu) - 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( - platform, args, True, cpu) - result['Release_GN_' + cpu + '_sandbox'] = GetConfigArgsSandbox( - platform, args, False, cpu) - out_configs = os.environ.get('GN_OUT_CONFIGS', None) if not out_configs is None: # Only generate the specified configurations. diff --git a/tools/make_distrib.py b/tools/make_distrib.py index a74ea06cd..f9057d591 100644 --- a/tools/make_distrib.py +++ b/tools/make_distrib.py @@ -165,8 +165,12 @@ def create_readme(): 'licensing terms and conditions.' elif mode == 'sandbox': distrib_type = 'Sandbox' - distrib_desc = 'This distribution contains only the cef_sandbox static library. Please see\n' \ - 'the LICENSING section of this document for licensing terms and conditions.' + if platform == 'windows': + distrib_desc = 'This distribution contains only the bootstrap executables. Please see\n' \ + 'the LICENSING section of this document for licensing terms and conditions.' + elif platform == 'mac': + distrib_desc = 'This distribution contains only the cef_sandbox dynamic library. Please see\n' \ + 'the LICENSING section of this document for licensing terms and conditions.' elif mode == 'tools': distrib_type = 'Tools' distrib_desc = 'This distribution contains additional tools for building CEF-based applications.' @@ -520,113 +524,6 @@ def copy_files_list(build_dir, dst_dir, paths): raise Exception('Missing required path: %s' % source_path) -def get_exported_symbols(file): - """ Returns the global symbols exported by |file|. """ - symbols = [] - - # Each symbol line has a value like: - # 0000000000000000 T _cef_sandbox_initialize - cmdline = 'nm -g -U %s' % file - result = exec_cmd(cmdline, os.path.join(cef_dir, 'tools')) - if len(result['err']) > 0: - raise Exception('ERROR: nm failed: %s' % result['err']) - for line in result['out'].split('\n'): - if line.find(' T ') < 0: - continue - symbol = line[line.rfind(' ') + 1:] - symbols.append(symbol) - - return symbols - - -def get_undefined_symbols(file): - """ Returns the undefined symbols imported by |file|. """ - symbols = [] - - # Each symbol line has a value like: - # cef_sandbox.a:cef_sandbox.o: _memcpy - cmdline = 'nm -u -A %s' % file - result = exec_cmd(cmdline, os.path.join(cef_dir, 'tools')) - if len(result['err']) > 0: - raise Exception('ERROR: nm failed: %s' % result['err']) - for line in result['out'].split('\n'): - if line.find(': ') < 0: - continue - symbol = line[line.rfind(': ') + 2:] - symbols.append(symbol) - - return symbols - - -def combine_libs(platform, build_dir, libs, dest_lib): - """ Combine multiple static libraries into a single static library. """ - intermediate_obj = None - 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 = [ - '_cef_', # C symbols - 'Cef', # C++ symbols - ] - - print('Finding exported symbols...') - assert 'libcef_sandbox.a' in libs[0], libs[0] - symbols = [] - for symbol in get_exported_symbols(os.path.join(build_dir, libs[0])): - for match in symbol_match: - if symbol.find(match) >= 0: - symbols.append(symbol) - break - assert len(symbols) > 0 - - # Create an intermediate object file that combines all other object files. - # Symbols not identified above will be made private (local). - intermediate_obj = os.path.splitext(dest_lib)[0] + '.o' - arch = 'arm64' if options.arm64build else 'x86_64' - 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) - cmdline += ' "%s"' % path - run(cmdline, os.path.join(cef_dir, 'tools')) - - if not intermediate_obj is None: - # Create an archive file containing the new object file. - cmdline = 'libtool -static -o "%s" "%s"' % (dest_lib, intermediate_obj) - run(cmdline, os.path.join(cef_dir, 'tools')) - remove_file(intermediate_obj) - - # Verify that only the expected symbols are exported from the archive file. - print('Verifying exported symbols...') - result_symbols = get_exported_symbols(dest_lib) - if set(symbols) != set(result_symbols): - print('Expected', symbols) - print('Got', result_symbols) - raise Exception('Failure verifying exported symbols') - - # Verify that no C++ symbols are imported by the archive file. If the - # archive imports C++ symbols and the client app links an incompatible C++ - # library, the result will be undefined behavior. - # For example, to avoid importing libc++ symbols the cef_sandbox target - # should have a dependency on libc++abi. This dependency can be verified - # with the following command: - # gn path out/[config] //cef:cef_sandbox //buildtools/third_party/libc++abi - print('Verifying imported (undefined) symbols...') - undefined_symbols = get_undefined_symbols(dest_lib) - cpp_symbols = list( - filter(lambda symbol: symbol.startswith('__Z'), undefined_symbols)) - if cpp_symbols: - print('Found C++ symbols:', cpp_symbols) - raise Exception('Failure verifying imported (undefined) symbols') - - def run(command_line, working_dir): """ Run a command. """ sys.stdout.write('-------- Running "'+command_line+'" in "'+\ @@ -1255,15 +1152,6 @@ elif platform == 'mac': framework_name = 'Chromium Embedded Framework' 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', - 'obj/buildtools/third_party/libc++/libc++/*.o', - 'obj/buildtools/third_party/libc++abi/libc++abi/*.o', - ] dsym_dirs = [ '%s.dSYM' % framework_name, 'libEGL.dylib.dSYM', @@ -1271,25 +1159,15 @@ elif platform == 'mac': 'libvk_swiftshader.dylib.dSYM', ] - # 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') 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.a')) - break + sandbox_lib = 'libcef_sandbox.dylib' + if mode == 'sandbox': + # Only transfer the sandbox dSYM. + dsym_dirs = [] + dsym_dirs.append('%s.dSYM' % sandbox_lib) valid_build_dir = None - if mode == 'standard': + if mode == 'standard' or mode == 'sandbox': # transfer Debug files build_dir = build_dir_debug if not options.allowpartial or path_exists( @@ -1300,8 +1178,16 @@ elif platform == 'mac': framework_src_dir = os.path.join( build_dir, '%s/Contents/Frameworks/%s.framework/Versions/A' % (cefclient_app, framework_name)) - framework_dst_dir = os.path.join(dst_dir, '%s.framework' % framework_name) - copy_dir(framework_src_dir, framework_dst_dir, options.quiet) + + if mode == 'sandbox': + # Only transfer the sandbox library. + copy_file( + os.path.join(framework_src_dir, 'Libraries', sandbox_lib), dst_dir, + options.quiet) + else: + framework_dst_dir = os.path.join(dst_dir, + '%s.framework' % framework_name) + copy_dir(framework_src_dir, framework_dst_dir, options.quiet) if not options.nosymbols: # create the symbol output directory @@ -1318,17 +1204,23 @@ elif platform == 'mac': 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, 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)) + # 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 == 'sandbox': + # Only transfer the sandbox library. + copy_file( + os.path.join(framework_src_dir, 'Libraries', sandbox_lib), dst_dir, + options.quiet) + else: if mode != 'client': framework_dst_dir = os.path.join(dst_dir, '%s.framework' % framework_name) @@ -1343,20 +1235,20 @@ elif platform == 'mac': 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) + 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. - for dsym in dsym_dirs: - copy_dir( - os.path.join(build_dir, dsym), - os.path.join(symbol_output_dir, dsym), options.quiet) - else: - sys.stdout.write("No Release build files.\n") + # 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. + for dsym in dsym_dirs: + copy_dir( + os.path.join(build_dir, dsym), + os.path.join(symbol_output_dir, dsym), options.quiet) + else: + sys.stdout.write("No Release build files.\n") if mode == 'standard' or mode == 'minimal': # transfer include files