energy/cef/cef-chromium.go

230 lines
6.4 KiB
Go
Raw Normal View History

2022-10-04 13:21:05 +08:00
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
2022-10-04 13:21:05 +08:00
//
//----------------------------------------
2023-02-20 00:20:01 +08:00
// CEF Chromium组件
2022-10-04 13:21:05 +08:00
package cef
import (
. "github.com/energye/energy/common"
2022-10-04 22:34:57 +08:00
. "github.com/energye/energy/consts"
"github.com/energye/energy/ipc"
2022-10-04 13:21:05 +08:00
"github.com/energye/golcl/lcl"
"github.com/energye/golcl/lcl/types"
2022-10-04 13:21:05 +08:00
"sync"
"unsafe"
)
var executeJS = &ExecuteJS{
2022-10-04 22:34:57 +08:00
msgID: &MsgID{},
emitSync: &ipc.EmitSyncCollection{Mutex: new(sync.Mutex), EmitCollection: sync.Map{}},
emitCallback: &ipc.EmitCallbackCollection{EmitCollection: sync.Map{}},
2022-10-04 13:21:05 +08:00
}
type ExecuteJS struct {
2022-10-04 22:34:57 +08:00
msgID *MsgID //ipc 消息ID生成
emitCallback *ipc.EmitCallbackCollection //回调函数集合
emitSync *ipc.EmitSyncCollection //触发同步事件集合
2022-10-04 13:21:05 +08:00
}
2023-02-20 00:20:01 +08:00
// IChromium 组件接口
2022-10-04 13:21:05 +08:00
type IChromium interface {
IChromiumProc
IChromiumEvent
}
2023-02-20 00:20:01 +08:00
// TCEFChromium 组件
2022-10-04 13:21:05 +08:00
type TCEFChromium struct {
*lcl.TComponent
instance unsafe.Pointer
cfg *tCefChromiumConfig
2023-03-01 14:18:39 +08:00
browser *ICefBrowser
emitLock *sync.Mutex
browserHandle types.HWND
widgetHandle types.HWND
renderHandle types.HWND
2022-10-04 13:21:05 +08:00
}
2023-02-20 00:20:01 +08:00
// NewChromium 创建一个新的 TCEFChromium
func NewChromium(owner lcl.IComponent, config *tCefChromiumConfig) IChromium {
2022-10-04 13:21:05 +08:00
m := new(TCEFChromium)
if config != nil {
m.cfg = config
} else {
m.cfg = NewChromiumConfig()
}
m.instance = unsafe.Pointer(_CEFChromium_Create(lcl.CheckPtr(owner), uintptr(unsafe.Pointer(m.cfg))))
2022-10-04 13:21:05 +08:00
m.emitLock = new(sync.Mutex)
m.initDefault()
2022-10-04 13:21:05 +08:00
return m
}
// 默认的初始配置
func (m *TCEFChromium) initDefault() {
//通过设置这些首选项,可以降低/避免WebRTC的IP泄漏
m.SetWebRTCIPHandlingPolicy(HpDisableNonProxiedUDP)
m.SetWebRTCMultipleRoutes(STATE_DISABLED)
m.SetWebRTCNonproxiedUDP(STATE_DISABLED)
}
2023-02-20 00:20:01 +08:00
// Instance 组件实例指针
func (m *TCEFChromium) Instance() uintptr {
return uintptr(m.instance)
}
2022-10-04 22:34:57 +08:00
func (m *TCEFChromium) browseEmitJsOnEvent(browseId int32, frameId int64, name string, argumentList ipc.IArgumentList) ProcessMessageError {
2023-02-26 19:14:49 +08:00
//data := argumentList.Package()
//r1 := _CEFFrame_SendProcessMessageByIPC(browseId, frameId, name, PID_RENDER, int32(argumentList.Size()), uintptr(unsafe.Pointer(&data[0])), uintptr(len(data)))
//return ProcessMessageError(r1)
return 1 //TODO dev
2022-10-04 13:21:05 +08:00
}
2023-02-20 00:20:01 +08:00
// On 监听事件,事件驱动在Go中监听JS中触发
2022-10-04 22:34:57 +08:00
func (m *TCEFChromium) On(name string, eventCallback ipc.EventCallback) {
2022-10-04 13:21:05 +08:00
if eventCallback == nil {
return
}
2022-10-04 22:34:57 +08:00
ipc.IPC.Browser().On(name, eventCallback)
2022-10-04 13:21:05 +08:00
}
2023-02-20 00:20:01 +08:00
// ExecuteJavaScript
2022-10-04 13:21:05 +08:00
// 执行JS代码
//
// code: js代码
//
2023-02-20 00:20:01 +08:00
// scriptURL: js脚本地址 默认about:blank
2022-10-04 13:21:05 +08:00
//
// startLine: js脚本启始执行行号
func (m *TCEFChromium) ExecuteJavaScript(code, scriptURL string, startLine int32) {
_CEFChromium_ExecuteJavaScript(uintptr(m.instance), code, scriptURL, startLine)
2022-10-04 13:21:05 +08:00
}
2023-02-20 00:20:01 +08:00
// Emit
2022-10-04 13:21:05 +08:00
// 触发JS监听的事件-异步执行
//
2023-02-20 00:20:01 +08:00
// EmitTarget 接收目标, nil:mainBrowser&mainFrame, 可传递browser和指定浏览器窗口JS监听事件的接收
func (m *TCEFChromium) Emit(eventName string, args ipc.IArgumentList, target IEmitTarget) ProcessMessageError {
2022-10-04 13:21:05 +08:00
if eventName == "" {
return PMErr_NAME_IS_NULL
}
m.emitLock.Lock()
defer m.emitLock.Unlock()
var (
browseId int32
frameId int64
)
if args == nil {
2022-10-04 22:34:57 +08:00
args = ipc.NewArgumentList()
2022-10-04 13:21:05 +08:00
}
if target == nil {
bsr := m.Browser()
browseId = bsr.Identifier()
2023-02-26 19:14:49 +08:00
frameId = bsr.MainFrame().Identifier()
2022-10-04 13:21:05 +08:00
} else {
browseId = target.GetBrowserId()
frameId = target.GetFrameId()
2023-02-26 19:14:49 +08:00
if m.BrowserById(browseId).GetFrameById(frameId) == nil {
2022-10-04 13:21:05 +08:00
return PMErr_NOT_FOUND_FRAME
}
}
var idx = args.Size()
2022-10-04 22:34:57 +08:00
args.SetInt32(idx, int32(Tm_Async))
2022-10-04 13:21:05 +08:00
args.SetInt32(idx+1, 0)
args.SetString(idx+2, eventName, true)
2022-10-04 22:34:57 +08:00
m.browseEmitJsOnEvent(browseId, frameId, ipc.Ln_IPC_GoEmitJS, args)
2022-10-04 13:21:05 +08:00
return PME_OK
}
2023-02-20 00:20:01 +08:00
// EmitAndCallback
2022-10-04 13:21:05 +08:00
// 触发JS监听的事件-异步执行-带回调
//
// EmitTarget 接收目标, nil = mainBrowser mainFrame
func (m *TCEFChromium) EmitAndCallback(eventName string, args ipc.IArgumentList, target IEmitTarget, callback ipc.IPCCallback) ProcessMessageError {
2022-10-04 13:21:05 +08:00
if eventName == "" {
return PMErr_NAME_IS_NULL
}
m.emitLock.Lock()
defer m.emitLock.Unlock()
var (
browseId int32
frameId int64
2022-10-04 22:34:57 +08:00
ipcId = executeJS.msgID.New()
2022-10-04 13:21:05 +08:00
idx = args.Size()
)
if args == nil {
2022-10-04 22:34:57 +08:00
args = ipc.NewArgumentList()
2022-10-04 13:21:05 +08:00
}
if target == nil {
bsr := m.Browser()
browseId = bsr.Identifier()
2023-02-26 19:14:49 +08:00
frameId = bsr.MainFrame().Identifier()
2022-10-04 13:21:05 +08:00
} else {
browseId = target.GetBrowserId()
frameId = target.GetFrameId()
2023-02-26 19:14:49 +08:00
if m.BrowserById(browseId).GetFrameById(frameId) == nil {
2022-10-04 13:21:05 +08:00
return PMErr_NOT_FOUND_FRAME
}
}
2022-10-04 22:34:57 +08:00
args.SetInt32(idx, int32(Tm_Callback))
2022-10-04 13:21:05 +08:00
args.SetInt32(idx+1, ipcId)
args.SetString(idx+2, eventName, true)
2022-10-04 22:34:57 +08:00
executeJS.emitCallback.EmitCollection.Store(ipcId, callback)
m.browseEmitJsOnEvent(browseId, frameId, ipc.Ln_IPC_GoEmitJS, args)
2022-10-04 13:21:05 +08:00
return PME_OK
}
2023-02-20 00:20:01 +08:00
// EmitAndReturn
2022-10-04 13:21:05 +08:00
// 触发JS监听的事件-同步执行-阻塞UI主线程
//
2023-02-20 00:20:01 +08:00
// 使用不当会造成 UI线程 锁死一搬不在与JS监听中使用与其它子进程通信时使用
2022-10-04 13:21:05 +08:00
//
// EmitTarget 接收目标, nil = mainBrowser mainFrame
func (m *TCEFChromium) EmitAndReturn(eventName string, args ipc.IArgumentList, target IEmitTarget) (ipc.IIPCContext, ProcessMessageError) {
2022-10-04 13:21:05 +08:00
if eventName == "" {
return nil, PMErr_NAME_IS_NULL
}
m.emitLock.Lock()
defer m.emitLock.Unlock()
var (
browseId int32
frameId int64
2022-10-04 22:34:57 +08:00
ipcId = executeJS.msgID.New()
2022-10-04 13:21:05 +08:00
idx = args.Size()
)
if args == nil {
2022-10-04 22:34:57 +08:00
args = ipc.NewArgumentList()
2022-10-04 13:21:05 +08:00
}
if target == nil {
bsr := m.Browser()
browseId = bsr.Identifier()
2023-02-26 19:14:49 +08:00
frameId = bsr.MainFrame().Identifier()
2022-10-04 13:21:05 +08:00
} else {
browseId = target.GetBrowserId()
frameId = target.GetFrameId()
2023-02-26 19:14:49 +08:00
if m.BrowserById(browseId).GetFrameById(frameId) == nil {
2022-10-04 13:21:05 +08:00
return nil, PMErr_NOT_FOUND_FRAME
}
}
2022-10-04 22:34:57 +08:00
args.SetInt32(idx, int32(Tm_Sync))
2022-10-04 13:21:05 +08:00
args.SetInt32(idx+1, ipcId)
args.SetString(idx+2, eventName, true)
2022-10-04 22:34:57 +08:00
var callback = func(emitAsync *ipc.EmitSyncCollection, ipcId int32) ipc.IIPCContext {
emitAsync.Mutex.Lock()
defer emitAsync.Mutex.Unlock()
var chn = make(chan ipc.IIPCContext)
var ret ipc.IIPCContext
emitAsync.EmitCollection.Store(ipcId, chn)
2022-10-04 13:21:05 +08:00
ret = <-chn //锁住当前线程
2022-10-04 22:34:57 +08:00
executeJS.emitSync.EmitCollection.Delete(ipcId)
2022-10-04 13:21:05 +08:00
return ret
}
2022-10-04 22:34:57 +08:00
m.browseEmitJsOnEvent(browseId, frameId, ipc.Ln_IPC_GoEmitJS, args)
2022-10-04 13:21:05 +08:00
return callback(executeJS.emitSync, ipcId), PME_OK
}