1# Copyright (c) 2018 The Chromium Embedded Framework Authors. All rights 2# reserved. Use of this source code is governed by a BSD-style license that 3# can be found in the LICENSE file. 4 5from __future__ import absolute_import 6from cef_parser import * 7from file_util import * 8import os 9 10# Other headers that export C API functions. 11OTHER_HEADERS = [ 12 'cef_api_hash.h', 13 'cef_version.h', 14 'internal/cef_logging_internal.h', 15 'internal/cef_string_list.h', 16 'internal/cef_string_map.h', 17 'internal/cef_string_multimap.h', 18 'internal/cef_string_types.h', 19 'internal/cef_thread_internal.h', 20 'internal/cef_time.h', 21 'internal/cef_trace_event_internal.h', 22] 23 24 25def make_libcef_dll_dylib_impl_parts(name, retval, args): 26 # Split arguments into types and names. 27 arg_types = '' 28 arg_names = '' 29 for arg in args: 30 if len(arg_types) > 0: 31 arg_types += ', ' 32 arg_names += ', ' 33 pos = arg.rfind(' ') 34 arg_types += arg[0:pos] 35 arg_names += arg[pos + 1:] 36 37 typedef = 'typedef %s (*%s_ptr)(%s);\n' % (retval, name, arg_types) 38 39 declare = '%s_ptr %s;\n' % (name, name) 40 41 init = ' INIT_ENTRY(%s);' % name 42 43 impl = """NO_SANITIZE("cfi-icall") %s %s(%s) { 44 %sg_libcef_pointers.%s(%s); 45} 46 47""" % (retval, name, ', '.join(args), 'return ' 48 if retval != 'void' else '', name, arg_names) 49 50 return (typedef, declare, init, impl) 51 52 53def make_libcef_dll_dylib_impl_func(func): 54 name = func.get_capi_name() 55 parts = func.get_capi_parts([]) 56 retval = parts['retval'] 57 args = parts['args'] 58 return make_libcef_dll_dylib_impl_parts(name, retval, args) 59 60 61def make_libcef_dll_dylib_impl(header): 62 filenames = [] 63 includes = [] 64 ptr_typedef = '' 65 ptr_declare = '' 66 ptr_init = '' 67 ptr_impl = '' 68 69 # Include required headers for global functions. 70 for func in header.get_funcs(): 71 typedef, declare, init, impl = make_libcef_dll_dylib_impl_func(func) 72 ptr_typedef += typedef 73 ptr_declare += declare 74 ptr_init += init 75 ptr_impl += impl 76 77 filename = func.get_file_name() 78 if not filename in filenames: 79 includes.append('#include "include/capi/%s"' % func.get_capi_file_name()) 80 filenames.append(filename) 81 82 # Include required headers for static class functions. 83 allclasses = header.get_classes() 84 for cls in allclasses: 85 funcs = cls.get_static_funcs() 86 for func in funcs: 87 typedef, declare, init, impl = make_libcef_dll_dylib_impl_func(func) 88 ptr_typedef += typedef 89 ptr_declare += declare 90 ptr_init += init 91 ptr_impl += impl 92 93 if len(funcs) > 0: 94 filename = cls.get_file_name() 95 if not filename in filenames: 96 includes.append('#include "include/capi/%s"' % cls.get_capi_file_name()) 97 filenames.append(filename) 98 99 # Parse other headers. 100 root_directory = header.get_root_directory() 101 for other in OTHER_HEADERS: 102 path = os.path.join(root_directory, other) 103 content = read_file(path) 104 funcs = get_function_impls(content, 'CEF_EXPORT', False) 105 for func in funcs: 106 typedef, declare, init, impl = make_libcef_dll_dylib_impl_parts( 107 func['name'], func['retval'], func['args']) 108 ptr_typedef += typedef 109 ptr_declare += declare 110 ptr_init += init 111 ptr_impl += impl 112 113 includes.append('#include "include/%s"' % other) 114 115 # Build the final output. 116 result = get_copyright() + """ 117 118#include <dlfcn.h> 119#include <stdio.h> 120 121""" + "\n".join(sorted(includes)) + """ 122#include "include/wrapper/cef_library_loader.h" 123 124// GLOBAL WRAPPER FUNCTIONS - Do not edit by hand. 125 126namespace { 127 128void* g_libcef_handle = nullptr; 129 130void* libcef_get_ptr(const char* path, const char* name) { 131 void* ptr = dlsym(g_libcef_handle, name); 132 if (!ptr) { 133 fprintf(stderr, "dlsym %s: %s\\n", path, dlerror()); 134 } 135 return ptr; 136} 137 138""" + ptr_typedef + """ 139 140struct libcef_pointers { 141""" + ptr_declare + """ 142} g_libcef_pointers = {0}; 143 144#define INIT_ENTRY(name) \ 145 g_libcef_pointers.name = (name##_ptr)libcef_get_ptr(path, #name); \ 146 if (!g_libcef_pointers.name) { \ 147 return 0; \ 148 } 149 150int libcef_init_pointers(const char* path) { 151""" + ptr_init + """ 152 return 1; 153} 154 155} // namespace 156 157int cef_load_library(const char* path) { 158 if (g_libcef_handle) 159 return 0; 160 161 g_libcef_handle = dlopen(path, RTLD_LAZY | RTLD_LOCAL | RTLD_FIRST); 162 if (!g_libcef_handle) { 163 fprintf(stderr, "dlopen %s: %s\\n", path, dlerror()); 164 return 0; 165 } 166 167 if (!libcef_init_pointers(path)) { 168 cef_unload_library(); 169 return 0; 170 } 171 172 return 1; 173} 174 175int cef_unload_library() { 176 int result = 0; 177 if (g_libcef_handle) { 178 result = !dlclose(g_libcef_handle); 179 if (!result) { 180 fprintf(stderr, "dlclose: %s\\n", dlerror()); 181 } 182 g_libcef_handle = nullptr; 183 } 184 return result; 185} 186 187""" + ptr_impl 188 return result 189 190 191def write_libcef_dll_dylib_impl(header, file): 192 newcontents = make_libcef_dll_dylib_impl(header) 193 return (file, newcontents) 194 195 196# Test the module. 197if __name__ == "__main__": 198 import sys 199 200 # Verify that the correct number of command-line arguments are provided. 201 if len(sys.argv) < 2: 202 sys.stderr.write('Usage: ' + sys.argv[0] + ' <cpp_header_dir>\n') 203 sys.exit() 204 205 cpp_header_dir = sys.argv[1] 206 207 # Create the header object. Should match the logic in translator.py. 208 header = obj_header() 209 header.set_root_directory(cpp_header_dir) 210 excluded_files = ['cef_api_hash.h', 'cef_application_mac.h', 'cef_version.h'] 211 header.add_directory(cpp_header_dir, excluded_files) 212 header.add_directory(os.path.join(cpp_header_dir, 'test')) 213 header.add_directory(os.path.join(cpp_header_dir, 'views')) 214 215 # Dump the result to stdout. 216 sys.stdout.write(make_libcef_dll_dylib_impl(header)) 217