• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      '#include "include/base/cef_compiler_specific.h"',
65      '#include "include/wrapper/cef_library_loader.h"',
66  ]
67  ptr_typedef = ''
68  ptr_declare = ''
69  ptr_init = ''
70  ptr_impl = ''
71
72  # Include required headers for global functions.
73  for func in header.get_funcs():
74    typedef, declare, init, impl = make_libcef_dll_dylib_impl_func(func)
75    ptr_typedef += typedef
76    ptr_declare += declare
77    ptr_init += init
78    ptr_impl += impl
79
80    filename = func.get_file_name()
81    if not filename in filenames:
82      includes.append('#include "include/capi/%s"' % func.get_capi_file_name())
83      filenames.append(filename)
84
85  # Include required headers for static class functions.
86  allclasses = header.get_classes()
87  for cls in allclasses:
88    funcs = cls.get_static_funcs()
89    for func in funcs:
90      typedef, declare, init, impl = make_libcef_dll_dylib_impl_func(func)
91      ptr_typedef += typedef
92      ptr_declare += declare
93      ptr_init += init
94      ptr_impl += impl
95
96    if len(funcs) > 0:
97      filename = cls.get_file_name()
98      if not filename in filenames:
99        includes.append('#include "include/capi/%s"' % cls.get_capi_file_name())
100        filenames.append(filename)
101
102  # Parse other headers.
103  root_directory = header.get_root_directory()
104  for other in OTHER_HEADERS:
105    path = os.path.join(root_directory, other)
106    content = read_file(path)
107    funcs = get_function_impls(content, 'CEF_EXPORT', False)
108    for func in funcs:
109      typedef, declare, init, impl = make_libcef_dll_dylib_impl_parts(
110          func['name'], func['retval'], func['args'])
111      ptr_typedef += typedef
112      ptr_declare += declare
113      ptr_init += init
114      ptr_impl += impl
115
116    includes.append('#include "include/%s"' % other)
117
118  # Build the final output.
119  result = get_copyright() + """
120
121#include <dlfcn.h>
122#include <stdio.h>
123
124""" + "\n".join(sorted(includes)) + """
125
126// GLOBAL WRAPPER FUNCTIONS - Do not edit by hand.
127
128namespace {
129
130void* g_libcef_handle = nullptr;
131
132void* libcef_get_ptr(const char* path, const char* name) {
133  void* ptr = dlsym(g_libcef_handle, name);
134  if (!ptr) {
135    fprintf(stderr, "dlsym %s: %s\\n", path, dlerror());
136  }
137  return ptr;
138}
139
140""" + ptr_typedef + """
141
142struct libcef_pointers {
143""" + ptr_declare + """
144} g_libcef_pointers = {0};
145
146#define INIT_ENTRY(name) \
147  g_libcef_pointers.name = (name##_ptr)libcef_get_ptr(path, #name); \
148  if (!g_libcef_pointers.name) { \
149    return 0; \
150  }
151
152int libcef_init_pointers(const char* path) {
153""" + ptr_init + """
154  return 1;
155}
156
157}  // namespace
158
159int cef_load_library(const char* path) {
160  if (g_libcef_handle)
161    return 0;
162
163  g_libcef_handle = dlopen(path, RTLD_LAZY | RTLD_LOCAL | RTLD_FIRST);
164  if (!g_libcef_handle) {
165    fprintf(stderr, "dlopen %s: %s\\n", path, dlerror());
166    return 0;
167  }
168
169  if (!libcef_init_pointers(path)) {
170    cef_unload_library();
171    return 0;
172  }
173
174  return 1;
175}
176
177int cef_unload_library() {
178  int result = 0;
179  if (g_libcef_handle) {
180    result = !dlclose(g_libcef_handle);
181    if (!result) {
182      fprintf(stderr, "dlclose: %s\\n", dlerror());
183    }
184    g_libcef_handle = nullptr;
185  }
186  return result;
187}
188
189""" + ptr_impl
190  return result
191
192
193def write_libcef_dll_dylib_impl(header, file):
194  newcontents = make_libcef_dll_dylib_impl(header)
195  return (file, newcontents)
196
197
198# Test the module.
199if __name__ == "__main__":
200  import sys
201
202  # Verify that the correct number of command-line arguments are provided.
203  if len(sys.argv) < 2:
204    sys.stderr.write('Usage: ' + sys.argv[0] + ' <cpp_header_dir>\n')
205    sys.exit()
206
207  cpp_header_dir = sys.argv[1]
208
209  # Create the header object. Should match the logic in translator.py.
210  header = obj_header()
211  header.set_root_directory(cpp_header_dir)
212  excluded_files = ['cef_api_hash.h', 'cef_application_mac.h', 'cef_version.h']
213  header.add_directory(cpp_header_dir, excluded_files)
214  header.add_directory(os.path.join(cpp_header_dir, 'test'))
215  header.add_directory(os.path.join(cpp_header_dir, 'views'))
216
217  # Dump the result to stdout.
218  sys.stdout.write(make_libcef_dll_dylib_impl(header))
219