mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
macOS: Load the CEF framework using dlopen instead of direct linking (issue #2459)
This is a prerequisite for using the Chromium V2 sandbox.
This commit is contained in:
214
tools/make_libcef_dll_dylib_impl.py
Normal file
214
tools/make_libcef_dll_dylib_impl.py
Normal file
@ -0,0 +1,214 @@
|
||||
# Copyright (c) 2018 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.
|
||||
|
||||
from cef_parser import *
|
||||
from file_util import *
|
||||
import os
|
||||
|
||||
# Other headers that export C API functions.
|
||||
OTHER_HEADERS = [
|
||||
'cef_version.h',
|
||||
'internal/cef_logging_internal.h',
|
||||
'internal/cef_string_list.h',
|
||||
'internal/cef_string_map.h',
|
||||
'internal/cef_string_multimap.h',
|
||||
'internal/cef_string_types.h',
|
||||
'internal/cef_thread_internal.h',
|
||||
'internal/cef_time.h',
|
||||
'internal/cef_trace_event_internal.h',
|
||||
]
|
||||
|
||||
|
||||
def make_libcef_dll_dylib_impl_parts(name, retval, args):
|
||||
# Split arguments into types and names.
|
||||
arg_types = ''
|
||||
arg_names = ''
|
||||
for arg in args:
|
||||
if len(arg_types) > 0:
|
||||
arg_types += ', '
|
||||
arg_names += ', '
|
||||
pos = arg.rfind(' ')
|
||||
arg_types += arg[0:pos]
|
||||
arg_names += arg[pos + 1:]
|
||||
|
||||
typedef = 'typedef %s (*%s_ptr)(%s);\n' % (retval, name, arg_types)
|
||||
|
||||
declare = '%s_ptr %s;\n' % (name, name)
|
||||
|
||||
init = ' INIT_ENTRY(%s);' % name
|
||||
|
||||
impl = """NO_SANITIZE("cfi-icall") %s %s(%s) {
|
||||
%sg_libcef_pointers.%s(%s);
|
||||
}
|
||||
|
||||
""" % (retval, name, ', '.join(args), 'return '
|
||||
if retval != 'void' else '', name, arg_names)
|
||||
|
||||
return (typedef, declare, init, impl)
|
||||
|
||||
|
||||
def make_libcef_dll_dylib_impl_func(func):
|
||||
name = func.get_capi_name()
|
||||
parts = func.get_capi_parts([])
|
||||
retval = parts['retval']
|
||||
args = parts['args']
|
||||
return make_libcef_dll_dylib_impl_parts(name, retval, args)
|
||||
|
||||
|
||||
def make_libcef_dll_dylib_impl(header):
|
||||
filenames = []
|
||||
includes = []
|
||||
ptr_typedef = ''
|
||||
ptr_declare = ''
|
||||
ptr_init = ''
|
||||
ptr_impl = ''
|
||||
|
||||
# Include required headers for global functions.
|
||||
for func in header.get_funcs():
|
||||
typedef, declare, init, impl = make_libcef_dll_dylib_impl_func(func)
|
||||
ptr_typedef += typedef
|
||||
ptr_declare += declare
|
||||
ptr_init += init
|
||||
ptr_impl += impl
|
||||
|
||||
filename = func.get_file_name()
|
||||
if not filename in filenames:
|
||||
includes.append('#include "include/capi/%s"' % func.get_capi_file_name())
|
||||
filenames.append(filename)
|
||||
|
||||
# Include required headers for static class functions.
|
||||
allclasses = header.get_classes()
|
||||
for cls in allclasses:
|
||||
funcs = cls.get_static_funcs()
|
||||
for func in funcs:
|
||||
typedef, declare, init, impl = make_libcef_dll_dylib_impl_func(func)
|
||||
ptr_typedef += typedef
|
||||
ptr_declare += declare
|
||||
ptr_init += init
|
||||
ptr_impl += impl
|
||||
|
||||
if len(funcs) > 0:
|
||||
filename = cls.get_file_name()
|
||||
if not filename in filenames:
|
||||
includes.append('#include "include/capi/%s"' % cls.get_capi_file_name())
|
||||
filenames.append(filename)
|
||||
|
||||
# Parse other headers.
|
||||
root_directory = header.get_root_directory()
|
||||
for other in OTHER_HEADERS:
|
||||
path = os.path.join(root_directory, other)
|
||||
content = read_file(path)
|
||||
funcs = get_function_impls(content, 'CEF_EXPORT', False)
|
||||
for func in funcs:
|
||||
typedef, declare, init, impl = make_libcef_dll_dylib_impl_parts(
|
||||
func['name'], func['retval'], func['args'])
|
||||
ptr_typedef += typedef
|
||||
ptr_declare += declare
|
||||
ptr_init += init
|
||||
ptr_impl += impl
|
||||
|
||||
includes.append('#include "include/%s"' % other)
|
||||
|
||||
# Build the final output.
|
||||
result = get_copyright() + """
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
|
||||
""" + "\n".join(sorted(includes)) + """
|
||||
#include "include/wrapper/cef_library_loader.h"
|
||||
|
||||
// GLOBAL WRAPPER FUNCTIONS - Do not edit by hand.
|
||||
|
||||
namespace {
|
||||
|
||||
void* g_libcef_handle = NULL;
|
||||
|
||||
void* libcef_get_ptr(const char* path, const char* name) {
|
||||
void* ptr = dlsym(g_libcef_handle, name);
|
||||
if (!ptr) {
|
||||
fprintf(stderr, "dlsym %s: %s\\n", path, dlerror());
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
""" + ptr_typedef + """
|
||||
|
||||
struct libcef_pointers {
|
||||
""" + ptr_declare + """
|
||||
} g_libcef_pointers = {0};
|
||||
|
||||
#define INIT_ENTRY(name) \
|
||||
g_libcef_pointers.name = (name##_ptr)libcef_get_ptr(path, #name); \
|
||||
if (!g_libcef_pointers.name) { \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
int libcef_init_pointers(const char* path) {
|
||||
""" + ptr_init + """
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int cef_load_library(const char* path) {
|
||||
if (g_libcef_handle)
|
||||
return 0;
|
||||
|
||||
g_libcef_handle = dlopen(path, RTLD_LAZY | RTLD_LOCAL | RTLD_FIRST);
|
||||
if (!g_libcef_handle) {
|
||||
fprintf(stderr, "dlopen %s: %s\\n", path, dlerror());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!libcef_init_pointers(path)) {
|
||||
cef_unload_library();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cef_unload_library() {
|
||||
int result = 0;
|
||||
if (g_libcef_handle) {
|
||||
result = !dlclose(g_libcef_handle);
|
||||
if (!result) {
|
||||
fprintf(stderr, "dlclose: %s\\n", dlerror());
|
||||
}
|
||||
g_libcef_handle = NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
""" + ptr_impl
|
||||
return result
|
||||
|
||||
|
||||
def write_libcef_dll_dylib_impl(header, file):
|
||||
newcontents = make_libcef_dll_dylib_impl(header)
|
||||
return (file, newcontents)
|
||||
|
||||
|
||||
# Test the module.
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
||||
# Verify that the correct number of command-line arguments are provided.
|
||||
if len(sys.argv) < 2:
|
||||
sys.stderr.write('Usage: ' + sys.argv[0] + ' <cpp_header_dir>')
|
||||
sys.exit()
|
||||
|
||||
cpp_header_dir = sys.argv[1]
|
||||
|
||||
# Create the header object. Should match the logic in translator.py.
|
||||
header = obj_header()
|
||||
header.set_root_directory(cpp_header_dir)
|
||||
excluded_files = ['cef_application_mac.h', 'cef_version.h']
|
||||
header.add_directory(cpp_header_dir, excluded_files)
|
||||
header.add_directory(os.path.join(cpp_header_dir, 'test'))
|
||||
header.add_directory(os.path.join(cpp_header_dir, 'views'))
|
||||
|
||||
# Dump the result to stdout.
|
||||
sys.stdout.write(make_libcef_dll_dylib_impl(header))
|
Reference in New Issue
Block a user