2022-10-04 13:21:05 +08:00
|
|
|
|
//----------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Copyright © yanghy. All Rights Reserved.
|
|
|
|
|
//
|
2022-10-04 16:38:43 +08:00
|
|
|
|
// Licensed under GNU General Public License v3.0
|
2022-10-04 13:21:05 +08:00
|
|
|
|
//
|
|
|
|
|
//----------------------------------------
|
|
|
|
|
|
|
|
|
|
package cef
|
|
|
|
|
|
|
|
|
|
import (
|
2022-12-13 11:49:32 +08:00
|
|
|
|
"fmt"
|
2022-12-05 10:44:24 +08:00
|
|
|
|
. "github.com/energye/energy/common"
|
2022-10-04 22:34:57 +08:00
|
|
|
|
. "github.com/energye/energy/consts"
|
|
|
|
|
"github.com/energye/energy/ipc"
|
2022-12-13 11:49:32 +08:00
|
|
|
|
"github.com/energye/energy/logger"
|
|
|
|
|
"github.com/energye/golcl/lcl"
|
2022-10-04 13:21:05 +08:00
|
|
|
|
"github.com/energye/golcl/lcl/api"
|
2022-12-13 11:49:32 +08:00
|
|
|
|
"strings"
|
2022-10-04 13:21:05 +08:00
|
|
|
|
"unsafe"
|
|
|
|
|
)
|
|
|
|
|
|
2022-10-05 16:38:43 +08:00
|
|
|
|
//CEF应用对象
|
2022-10-04 13:21:05 +08:00
|
|
|
|
type TCEFApplication struct {
|
2022-12-04 18:27:20 +08:00
|
|
|
|
instance unsafe.Pointer
|
2022-10-04 13:21:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//创建应用程序
|
|
|
|
|
func NewApplication(cfg *tCefApplicationConfig) *TCEFApplication {
|
|
|
|
|
if cfg == nil {
|
|
|
|
|
cfg = NewApplicationConfig()
|
|
|
|
|
}
|
2022-11-17 11:12:42 +08:00
|
|
|
|
cfg.framework()
|
2022-12-09 21:08:30 +08:00
|
|
|
|
result := new(TCEFApplication)
|
2022-12-09 21:51:11 +08:00
|
|
|
|
r1, _, _ := Proc(internale_CEFApplication_Create).Call(uintptr(unsafe.Pointer(cfg)))
|
|
|
|
|
result.instance = unsafe.Pointer(r1)
|
2022-12-09 21:08:30 +08:00
|
|
|
|
//register default function
|
|
|
|
|
result.defaultSetOnContextCreated()
|
|
|
|
|
result.defaultSetOnProcessMessageReceived()
|
|
|
|
|
result.defaultSetOnBeforeChildProcessLaunch()
|
|
|
|
|
return result
|
2022-10-04 13:21:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-12-04 18:27:20 +08:00
|
|
|
|
func (m *TCEFApplication) Instance() uintptr {
|
|
|
|
|
return uintptr(m.instance)
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-05 16:38:43 +08:00
|
|
|
|
//启动主进程
|
2022-10-04 13:21:05 +08:00
|
|
|
|
func (m *TCEFApplication) StartMainProcess() bool {
|
2022-12-04 18:27:20 +08:00
|
|
|
|
if m.instance != nullptr {
|
2022-12-05 10:44:24 +08:00
|
|
|
|
r1, _, _ := Proc(internale_CEFStartMainProcess).Call(m.Instance())
|
|
|
|
|
var b = api.GoBool(r1)
|
2022-10-04 13:21:05 +08:00
|
|
|
|
if b {
|
2022-10-04 22:34:57 +08:00
|
|
|
|
internalBrowserIPCOnEventInit()
|
|
|
|
|
ipc.IPC.StartBrowserIPC()
|
2022-10-04 13:21:05 +08:00
|
|
|
|
bindGoToJS(nil, nil)
|
|
|
|
|
}
|
|
|
|
|
return b
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-09 21:08:30 +08:00
|
|
|
|
//启动子进程, 如果指定了子进程执行程序, 将执行指定的子进程程序
|
|
|
|
|
func (m *TCEFApplication) StartSubProcess() (result bool) {
|
2022-12-04 18:27:20 +08:00
|
|
|
|
if m.instance != nullptr {
|
2022-12-05 10:44:24 +08:00
|
|
|
|
r1, _, _ := Proc(internale_CEFStartSubProcess).Call(m.Instance())
|
2022-12-09 21:08:30 +08:00
|
|
|
|
result = api.GoBool(r1)
|
2022-10-04 13:21:05 +08:00
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-09 21:08:30 +08:00
|
|
|
|
func (m *TCEFApplication) StopScheduler() {
|
|
|
|
|
Proc(internale_CEFApplication_StopScheduler).Call()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (m *TCEFApplication) Destroy() {
|
|
|
|
|
Proc(internale_CEFApplication_Destroy).Call()
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-04 13:21:05 +08:00
|
|
|
|
func (m *TCEFApplication) Free() {
|
2022-12-04 18:27:20 +08:00
|
|
|
|
if m.instance != nullptr {
|
2022-12-05 10:44:24 +08:00
|
|
|
|
Proc(internale_CEFApplication_Free).Call()
|
2022-12-04 18:27:20 +08:00
|
|
|
|
m.instance = nullptr
|
2022-10-04 13:21:05 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-05 10:44:24 +08:00
|
|
|
|
func (m *TCEFApplication) ExecuteJS(browserId int32, code string) {
|
|
|
|
|
Proc(internale_CEFApplication_ExecuteJS).Call()
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-04 13:21:05 +08:00
|
|
|
|
//上下文件创建回调
|
|
|
|
|
//
|
2022-10-05 17:20:20 +08:00
|
|
|
|
//返回值 false 将会创建 render进程的IPC和GO绑定变量
|
2022-10-04 13:21:05 +08:00
|
|
|
|
//
|
2022-10-05 17:20:20 +08:00
|
|
|
|
//对于一些不想GO绑定变量的URL地址,实现该函数,通过 frame.Url
|
2022-10-04 13:21:05 +08:00
|
|
|
|
func (m *TCEFApplication) SetOnContextCreated(fn GlobalCEFAppEventOnContextCreated) {
|
2022-12-07 20:34:16 +08:00
|
|
|
|
Proc(internale_CEFGlobalApp_SetOnContextCreated).Call(api.MakeEventDataPtr(fn))
|
2022-10-04 13:21:05 +08:00
|
|
|
|
}
|
2022-12-05 10:44:24 +08:00
|
|
|
|
|
2022-10-04 13:21:05 +08:00
|
|
|
|
func (m *TCEFApplication) defaultSetOnContextCreated() {
|
|
|
|
|
m.SetOnContextCreated(func(browse *ICefBrowser, frame *ICefFrame, context *ICefV8Context) bool {
|
|
|
|
|
return false
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//初始化设置全局回调
|
|
|
|
|
func (m *TCEFApplication) SetOnWebKitInitialized(fn GlobalCEFAppEventOnWebKitInitialized) {
|
2022-12-08 15:27:49 +08:00
|
|
|
|
Proc(internale_CEFGlobalApp_SetOnWebKitInitialized).Call(api.MakeEventDataPtr(fn))
|
2022-10-04 13:21:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//进程间通信处理消息接收
|
|
|
|
|
func (m *TCEFApplication) SetOnProcessMessageReceived(fn RenderProcessMessageReceived) {
|
2022-12-08 15:27:49 +08:00
|
|
|
|
Proc(internale_CEFGlobalApp_SetOnProcessMessageReceived).Call(api.MakeEventDataPtr(fn))
|
2022-10-04 13:21:05 +08:00
|
|
|
|
}
|
|
|
|
|
func (m *TCEFApplication) defaultSetOnProcessMessageReceived() {
|
2022-10-04 22:34:57 +08:00
|
|
|
|
m.SetOnProcessMessageReceived(func(browse *ICefBrowser, frame *ICefFrame, sourceProcess CefProcessId, processMessage *ipc.ICefProcessMessage) bool {
|
2022-10-04 13:21:05 +08:00
|
|
|
|
return false
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (m *TCEFApplication) AddCustomCommandLine(commandLine, value string) {
|
2022-12-05 10:44:24 +08:00
|
|
|
|
Proc(internale_AddCustomCommandLine).Call(api.PascalStr(commandLine), api.PascalStr(value))
|
2022-10-04 13:21:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//启动子进程之前自定义命令行参数设置
|
|
|
|
|
func (m *TCEFApplication) SetOnBeforeChildProcessLaunch(fn GlobalCEFAppEventOnBeforeChildProcessLaunch) {
|
2022-12-08 15:27:49 +08:00
|
|
|
|
Proc(internale_CEFGlobalApp_SetOnBeforeChildProcessLaunch).Call(api.MakeEventDataPtr(fn))
|
2022-10-04 13:21:05 +08:00
|
|
|
|
}
|
|
|
|
|
func (m *TCEFApplication) defaultSetOnBeforeChildProcessLaunch() {
|
|
|
|
|
m.SetOnBeforeChildProcessLaunch(func(commandLine *TCefCommandLine) {})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (m *TCEFApplication) SetOnBrowserDestroyed(fn GlobalCEFAppEventOnBrowserDestroyed) {
|
2022-12-08 15:27:49 +08:00
|
|
|
|
Proc(internale_CEFGlobalApp_SetOnBrowserDestroyed).Call(api.MakeEventDataPtr(fn))
|
2022-10-04 13:21:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (m *TCEFApplication) SetOnLoadStart(fn GlobalCEFAppEventOnRenderLoadStart) {
|
2022-12-08 15:27:49 +08:00
|
|
|
|
Proc(internale_CEFGlobalApp_SetOnLoadStart).Call(api.MakeEventDataPtr(fn))
|
2022-10-04 13:21:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (m *TCEFApplication) SetOnLoadEnd(fn GlobalCEFAppEventOnRenderLoadEnd) {
|
2022-12-08 15:27:49 +08:00
|
|
|
|
Proc(internale_CEFGlobalApp_SetOnLoadEnd).Call(api.MakeEventDataPtr(fn))
|
2022-10-04 13:21:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (m *TCEFApplication) SetOnLoadError(fn GlobalCEFAppEventOnRenderLoadError) {
|
2022-12-08 15:27:49 +08:00
|
|
|
|
Proc(internale_CEFGlobalApp_SetOnLoadError).Call(api.MakeEventDataPtr(fn))
|
2022-10-04 13:21:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (m *TCEFApplication) SetOnLoadingStateChange(fn GlobalCEFAppEventOnRenderLoadingStateChange) {
|
2022-12-08 15:27:49 +08:00
|
|
|
|
Proc(internale_CEFGlobalApp_SetOnLoadingStateChange).Call(api.MakeEventDataPtr(fn))
|
2022-12-07 15:50:59 +08:00
|
|
|
|
}
|
2022-12-12 17:34:57 +08:00
|
|
|
|
|
|
|
|
|
func (m *TCEFApplication) SetOnGetDefaultClient(fn GlobalCEFAppEventOnGetDefaultClient) {
|
|
|
|
|
Proc(internale_CEFGlobalApp_SetOnGetDefaultClient).Call(api.MakeEventDataPtr(fn))
|
|
|
|
|
}
|
2022-12-13 11:49:32 +08:00
|
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
|
lcl.RegisterExtEventCallback(func(fn interface{}, getVal func(idx int) uintptr) bool {
|
|
|
|
|
defer func() {
|
|
|
|
|
if err := recover(); err != nil {
|
|
|
|
|
logger.Error("GlobalCEFApp Error:", err)
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
getPtr := func(i int) unsafe.Pointer {
|
|
|
|
|
return unsafe.Pointer(getVal(i))
|
|
|
|
|
}
|
|
|
|
|
switch fn.(type) {
|
|
|
|
|
case GlobalCEFAppEventOnBrowserDestroyed:
|
|
|
|
|
fn.(GlobalCEFAppEventOnBrowserDestroyed)(&ICefBrowser{browseId: int32(getVal(0))})
|
|
|
|
|
case GlobalCEFAppEventOnRenderLoadStart:
|
|
|
|
|
browser := &ICefBrowser{browseId: int32(getVal(0))}
|
|
|
|
|
tempFrame := (*cefFrame)(getPtr(1))
|
|
|
|
|
frame := &ICefFrame{
|
|
|
|
|
Browser: browser,
|
|
|
|
|
Name: api.GoStr(tempFrame.Name),
|
|
|
|
|
Url: api.GoStr(tempFrame.Url),
|
|
|
|
|
Id: StrToInt64(api.GoStr(tempFrame.Identifier)),
|
|
|
|
|
}
|
|
|
|
|
fn.(GlobalCEFAppEventOnRenderLoadStart)(browser, frame, TCefTransitionType(getVal(2)))
|
|
|
|
|
case GlobalCEFAppEventOnRenderLoadEnd:
|
|
|
|
|
browser := &ICefBrowser{browseId: int32(getVal(0))}
|
|
|
|
|
tempFrame := (*cefFrame)(getPtr(1))
|
|
|
|
|
frame := &ICefFrame{
|
|
|
|
|
Browser: browser,
|
|
|
|
|
Name: api.GoStr(tempFrame.Name),
|
|
|
|
|
Url: api.GoStr(tempFrame.Url),
|
|
|
|
|
Id: StrToInt64(api.GoStr(tempFrame.Identifier)),
|
|
|
|
|
}
|
|
|
|
|
fn.(GlobalCEFAppEventOnRenderLoadEnd)(browser, frame, int32(getVal(2)))
|
|
|
|
|
case GlobalCEFAppEventOnRenderLoadError:
|
|
|
|
|
browser := &ICefBrowser{browseId: int32(getVal(0))}
|
|
|
|
|
tempFrame := (*cefFrame)(getPtr(1))
|
|
|
|
|
frame := &ICefFrame{
|
|
|
|
|
Browser: browser,
|
|
|
|
|
Name: api.GoStr(tempFrame.Name),
|
|
|
|
|
Url: api.GoStr(tempFrame.Url),
|
|
|
|
|
Id: StrToInt64(api.GoStr(tempFrame.Identifier)),
|
|
|
|
|
}
|
|
|
|
|
fn.(GlobalCEFAppEventOnRenderLoadError)(browser, frame, TCefErrorCode(getVal(2)), api.GoStr(getVal(3)), api.GoStr(getVal(4)))
|
|
|
|
|
case GlobalCEFAppEventOnRenderLoadingStateChange:
|
|
|
|
|
browser := &ICefBrowser{browseId: int32(getVal(0))}
|
|
|
|
|
tempFrame := (*cefFrame)(getPtr(1))
|
|
|
|
|
frame := &ICefFrame{
|
|
|
|
|
Browser: browser,
|
|
|
|
|
Name: api.GoStr(tempFrame.Name),
|
|
|
|
|
Url: api.GoStr(tempFrame.Url),
|
|
|
|
|
Id: StrToInt64(api.GoStr(tempFrame.Identifier)),
|
|
|
|
|
}
|
|
|
|
|
fn.(GlobalCEFAppEventOnRenderLoadingStateChange)(browser, frame, api.GoBool(getVal(2)), api.GoBool(getVal(3)), api.GoBool(getVal(4)))
|
|
|
|
|
case RenderProcessMessageReceived:
|
|
|
|
|
browser := &ICefBrowser{browseId: int32(getVal(0))}
|
|
|
|
|
tempFrame := (*cefFrame)(getPtr(1))
|
|
|
|
|
frame := &ICefFrame{
|
|
|
|
|
Browser: browser,
|
|
|
|
|
Name: api.GoStr(tempFrame.Name),
|
|
|
|
|
Url: api.GoStr(tempFrame.Url),
|
|
|
|
|
Id: StrToInt64(api.GoStr(tempFrame.Identifier)),
|
|
|
|
|
}
|
|
|
|
|
cefProcMsg := (*ipc.CefProcessMessagePtr)(getPtr(3))
|
|
|
|
|
args := ipc.NewArgumentList()
|
|
|
|
|
args.UnPackageBytePtr(cefProcMsg.Data, int32(cefProcMsg.DataLen))
|
|
|
|
|
processMessage := &ipc.ICefProcessMessage{
|
|
|
|
|
Name: api.GoStr(cefProcMsg.Name),
|
|
|
|
|
ArgumentList: args,
|
|
|
|
|
}
|
|
|
|
|
var result = (*bool)(getPtr(4))
|
|
|
|
|
*result = fn.(RenderProcessMessageReceived)(browser, frame, CefProcessId(getVal(2)), processMessage)
|
|
|
|
|
args.Clear()
|
|
|
|
|
cefProcMsg.Data = 0
|
|
|
|
|
cefProcMsg.DataLen = 0
|
|
|
|
|
cefProcMsg.Name = 0
|
|
|
|
|
cefProcMsg = nil
|
|
|
|
|
args = nil
|
|
|
|
|
case GlobalCEFAppEventOnContextCreated:
|
|
|
|
|
browser := &ICefBrowser{browseId: int32(getVal(0))}
|
|
|
|
|
tempFrame := (*cefFrame)(getPtr(1))
|
|
|
|
|
frame := &ICefFrame{
|
|
|
|
|
Browser: browser,
|
|
|
|
|
Name: api.GoStr(tempFrame.Name),
|
|
|
|
|
Url: api.GoStr(tempFrame.Url),
|
|
|
|
|
Id: StrToInt64(api.GoStr(tempFrame.Identifier)),
|
|
|
|
|
}
|
|
|
|
|
if strings.Index(frame.Url, "devtools://") == 0 {
|
|
|
|
|
processName = PT_DEVTOOLS
|
|
|
|
|
return true
|
|
|
|
|
} else {
|
|
|
|
|
processName = Args.ProcessType()
|
|
|
|
|
}
|
2022-12-13 22:43:31 +08:00
|
|
|
|
v8ctx := (*iCefV8ContextPtr)(getPtr(2))
|
2022-12-13 11:49:32 +08:00
|
|
|
|
ctx := &ICefV8Context{
|
|
|
|
|
Browser: browser,
|
|
|
|
|
Frame: frame,
|
|
|
|
|
Global: &ICEFv8Value{instance: v8ctx.Global, ptr: unsafe.Pointer(v8ctx.Global)},
|
|
|
|
|
}
|
|
|
|
|
var status = (*bool)(getPtr(3))
|
|
|
|
|
//用户定义返回 false 创建 render IPC 及 变量绑定
|
|
|
|
|
var result = fn.(GlobalCEFAppEventOnContextCreated)(browser, frame, ctx)
|
|
|
|
|
if !result {
|
|
|
|
|
cefAppContextCreated(browser, frame)
|
|
|
|
|
*status = true
|
|
|
|
|
} else {
|
|
|
|
|
*status = false
|
|
|
|
|
}
|
|
|
|
|
case GlobalCEFAppEventOnWebKitInitialized:
|
|
|
|
|
fn.(GlobalCEFAppEventOnWebKitInitialized)()
|
|
|
|
|
case GlobalCEFAppEventOnBeforeChildProcessLaunch:
|
|
|
|
|
commands := (*uintptr)(getPtr(0))
|
|
|
|
|
commandLine := &TCefCommandLine{commandLines: make(map[string]string)}
|
|
|
|
|
ipc.IPC.SetPort()
|
|
|
|
|
commandLine.AppendSwitch(MAINARGS_NETIPCPORT, fmt.Sprintf("%d", ipc.IPC.Port()))
|
|
|
|
|
fn.(GlobalCEFAppEventOnBeforeChildProcessLaunch)(commandLine)
|
|
|
|
|
*commands = api.PascalStr(commandLine.toString())
|
|
|
|
|
case GlobalCEFAppEventOnGetDefaultClient:
|
|
|
|
|
client := (*uintptr)(getPtr(0))
|
|
|
|
|
getClient := &ICefClient{instance: unsafe.Pointer(client)}
|
|
|
|
|
fn.(GlobalCEFAppEventOnGetDefaultClient)(getClient)
|
|
|
|
|
*client = uintptr(getClient.instance)
|
|
|
|
|
default:
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
return true
|
|
|
|
|
})
|
|
|
|
|
}
|