-
-
Notifications
You must be signed in to change notification settings - Fork 127
/
cef.go
264 lines (226 loc) · 8.53 KB
/
cef.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
// Copyright (c) 2014 The cef2go authors. All rights reserved.
// License: BSD 3-clause.
// Website: https://github.com/CzarekTomczak/cef2go
package cef
/*
CEF capi fixes
--------------
In cef_string.h:
this => typedef cef_string_utf16_t cef_string_t;
to => #define cef_string_t cef_string_utf16_t
*/
/*
#cgo CFLAGS: -I./../../
#include <stdlib.h>
#include "string.h"
#include "include/capi/cef_app_capi.h"
#include "handlers/cef_app.h"
#include "handlers/cef_client.h"
*/
import "C"
import "unsafe"
import (
"os"
"log"
"runtime"
)
var Logger *log.Logger = log.New(os.Stdout, "[cef] ", log.Lshortfile)
var _MainArgs *C.struct__cef_main_args_t
var _AppHandler *C.cef_app_t // requires reference counting
var _ClientHandler *C.struct__cef_client_t // requires reference counting
// Sandbox is disabled. Including the "cef_sandbox.lib"
// library results in lots of GCC warnings/errors. It is
// compatible only with VS 2010. It would be required to
// build it using GCC. Add -lcef_sandbox to LDFLAGS.
// capi doesn't expose sandbox functions, you need do add
// these before import "C":
// void* cef_sandbox_info_create();
// void cef_sandbox_info_destroy(void* sandbox_info);
var _SandboxInfo unsafe.Pointer
type Settings struct {
CachePath string
LogSeverity int
LogFile string
ResourcesDirPath string
LocalesDirPath string
}
type BrowserSettings struct {
}
const (
LOGSEVERITY_DEFAULT = C.LOGSEVERITY_DEFAULT
LOGSEVERITY_VERBOSE = C.LOGSEVERITY_VERBOSE
LOGSEVERITY_INFO = C.LOGSEVERITY_INFO
LOGSEVERITY_WARNING = C.LOGSEVERITY_WARNING
LOGSEVERITY_ERROR = C.LOGSEVERITY_ERROR
LOGSEVERITY_ERROR_REPORT = C.LOGSEVERITY_ERROR_REPORT
LOGSEVERITY_DISABLE = C.LOGSEVERITY_DISABLE
)
func SetLogger(logger *log.Logger) {
Logger = logger
}
func _InitializeGlobalCStructures() {
_MainArgs = (*C.struct__cef_main_args_t)(
C.calloc(1, C.sizeof_struct__cef_main_args_t))
// Some bug in Go on Windows: "unexpected fault address 0xffffffff".
// Happens in cef_execute_process() when initialize_app_handler()
// or initialize_client_handler() are called here. This same code
// works perfectly fine on Linux and OS X. From the logs:
// [cef] cef.go:88: ExecuteProcess, args= [cef2go.exe]
// initialize_app_handler
// initialize_cef_base
// cef_base_t.size = 36
// initialize_client_handler
// initialize_cef_base
// cef_base_t.size = 72
// [cef] cef_windows.go:19: FillMainArgs
// cef_base_t.add_ref
// unexpected fault address 0xffffffff
// fatal error: fault
// So it looks like the problem occurs after the first call to
// add_ref made by CEF.
// Maybe that's the bug - some problem during linking:
// "cmd/ld: order of files in archives matters on Windows"
// https://code.google.com/p/go/issues/detail?id=2601
_AppHandler = (*C.cef_app_t)(
C.calloc(1, C.sizeof_cef_app_t))
if runtime.GOOS != "windows" {
C.initialize_app_handler(_AppHandler)
}
_ClientHandler = (*C.struct__cef_client_t)(
C.calloc(1, C.sizeof_struct__cef_client_t))
if runtime.GOOS != "windows" {
C.initialize_client_handler(_ClientHandler)
}
}
func ExecuteProcess(appHandle unsafe.Pointer) int {
Logger.Println("ExecuteProcess, args=", os.Args)
_InitializeGlobalCStructures()
FillMainArgs(_MainArgs, appHandle)
// Sandbox info needs to be passed to both cef_execute_process()
// and cef_initialize().
// OFF: _SandboxInfo = C.cef_sandbox_info_create()
var exitCode C.int = C.cef_execute_process(_MainArgs, _AppHandler,
_SandboxInfo)
if (exitCode >= 0) {
os.Exit(int(exitCode))
}
return int(exitCode)
}
func Initialize(settings Settings) int {
Logger.Println("Initialize")
if _MainArgs == nil {
// _MainArgs structure is initialized and filled in ExecuteProcess.
// If cef_execute_process is not called, and there is a call
// to cef_initialize, then it would result in creation of infinite
// number of processes. See Issue 1199 in CEF:
// https://code.google.com/p/chromiumembedded/issues/detail?id=1199
Logger.Println("ERROR: missing a call to ExecuteProcess")
return 0
}
// Initialize cef_settings_t structure.
var cefSettings *C.struct__cef_settings_t
cefSettings = (*C.struct__cef_settings_t)(
C.calloc(1, C.sizeof_struct__cef_settings_t))
cefSettings.size = C.sizeof_struct__cef_settings_t
// cache_path
// ----------
if (settings.CachePath != "") {
Logger.Println("CachePath=", settings.CachePath)
}
var cachePath *C.char = C.CString(settings.CachePath)
defer C.free(unsafe.Pointer(cachePath))
C.cef_string_from_utf8(cachePath, C.strlen(cachePath),
&cefSettings.cache_path)
// log_severity
// ------------
cefSettings.log_severity =
(C.cef_log_severity_t)(C.int(settings.LogSeverity))
// log_file
// --------
if (settings.LogFile != "") {
Logger.Println("LogFile=", settings.LogFile)
}
var logFile *C.char = C.CString(settings.LogFile)
defer C.free(unsafe.Pointer(logFile))
C.cef_string_from_utf8(logFile, C.strlen(logFile),
&cefSettings.log_file)
// resources_dir_path
// ------------------
if settings.ResourcesDirPath == "" && runtime.GOOS != "darwin" {
// Setting this path is required for the tests to run fine.
cwd, _ := os.Getwd()
settings.ResourcesDirPath = cwd
}
if (settings.ResourcesDirPath != "") {
Logger.Println("ResourcesDirPath=", settings.ResourcesDirPath)
}
var resourcesDirPath *C.char = C.CString(settings.ResourcesDirPath)
defer C.free(unsafe.Pointer(resourcesDirPath))
C.cef_string_from_utf8(resourcesDirPath, C.strlen(resourcesDirPath),
&cefSettings.resources_dir_path)
// locales_dir_path
// ----------------
if settings.LocalesDirPath == "" && runtime.GOOS != "darwin" {
// Setting this path is required for the tests to run fine.
cwd, _ := os.Getwd()
settings.LocalesDirPath = cwd + "/locales"
}
if (settings.LocalesDirPath != "") {
Logger.Println("LocalesDirPath=", settings.LocalesDirPath)
}
var localesDirPath *C.char = C.CString(settings.LocalesDirPath)
defer C.free(unsafe.Pointer(localesDirPath))
C.cef_string_from_utf8(localesDirPath, C.strlen(localesDirPath),
&cefSettings.locales_dir_path)
// no_sandbox
// ----------
cefSettings.no_sandbox = C.int(1)
ret := C.cef_initialize(_MainArgs, cefSettings, _AppHandler, _SandboxInfo)
return int(ret)
}
func CreateBrowser(hwnd unsafe.Pointer, browserSettings BrowserSettings,
url string) {
Logger.Println("CreateBrowser, url=", url)
// Initialize cef_window_info_t structure.
var windowInfo *C.cef_window_info_t
windowInfo = (*C.cef_window_info_t)(
C.calloc(1, C.sizeof_cef_window_info_t))
FillWindowInfo(windowInfo, hwnd)
// url
var cefUrl *C.cef_string_t
cefUrl = (*C.cef_string_t)(
C.calloc(1, C.sizeof_cef_string_t))
var charUrl *C.char = C.CString(url)
defer C.free(unsafe.Pointer(charUrl))
C.cef_string_from_utf8(charUrl, C.strlen(charUrl), cefUrl)
// Initialize cef_browser_settings_t structure.
var cefBrowserSettings *C.struct__cef_browser_settings_t
cefBrowserSettings = (*C.struct__cef_browser_settings_t)(
C.calloc(1, C.sizeof_struct__cef_browser_settings_t))
cefBrowserSettings.size = C.sizeof_struct__cef_browser_settings_t
// Do not create the browser synchronously using the
// cef_browser_host_create_browser_sync() function, as
// it is unreliable. Instead obtain browser object in
// life_span_handler::on_after_created. In that callback
// keep CEF browser objects in a global map (cef window
// handle -> cef browser) and introduce
// a GetBrowserByWindowHandle() function. This function
// will first guess the CEF window handle using for example
// WinAPI functions and then search the global map of cef
// browser objects.
C.cef_browser_host_create_browser(windowInfo, _ClientHandler, cefUrl,
cefBrowserSettings, nil)
}
func RunMessageLoop() {
Logger.Println("RunMessageLoop")
C.cef_run_message_loop()
}
func QuitMessageLoop() {
Logger.Println("QuitMessageLoop")
C.cef_quit_message_loop()
}
func Shutdown() {
Logger.Println("Shutdown")
C.cef_shutdown()
// OFF: cef_sandbox_info_destroy(_SandboxInfo)
}