energy/cef/cef-chromium.go

223 lines
6.0 KiB
Go
Raw Normal View History

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 (
. "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
}
type IChromium interface {
IChromiumProc
IChromiumEvent
}
type TCEFChromium struct {
*lcl.TComponent
instance unsafe.Pointer
cfg *tCefChromiumConfig
emitLock *sync.Mutex
browserHandle types.HWND
widgetHandle types.HWND
renderHandle types.HWND
2022-10-04 13:21:05 +08:00
}
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)
}
func (m *TCEFChromium) Instance() uintptr {
return uintptr(m.instance)
}
2022-10-04 13:21:05 +08:00
func (m *TCEFChromium) GetBrowserById(browserId int32) *ICefBrowser {
return &ICefBrowser{
browseId: browserId,
chromium: m.instance,
}
}
2022-10-04 22:34:57 +08:00
func (m *TCEFChromium) browseEmitJsOnEvent(browseId int32, frameId int64, name string, argumentList ipc.IArgumentList) ProcessMessageError {
2022-10-04 13:21:05 +08:00
data := argumentList.Package()
r1 := _CEFFrame_SendProcessMessage(browseId, frameId, name, PID_RENDER, int32(argumentList.Size()), uintptr(unsafe.Pointer(&data[0])), uintptr(len(data)))
2022-10-04 13:21:05 +08:00
return ProcessMessageError(r1)
}
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
}
// 执行JS代码
//
// code: js代码
//
// scriptURL: js脚本地址默认about:blank
//
// 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
}
// 触发JS监听的事件-异步执行
//
// EmitTarget 接收目标, nil = mainBrowser mainFrame
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()
frameId = bsr.MainFrame().Id
2022-10-04 13:21:05 +08:00
} else {
browseId = target.GetBrowserId()
frameId = target.GetFrameId()
2022-10-04 13:21:05 +08:00
if m.GetBrowserById(browseId).GetFrameById(frameId) == nil {
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
}
// 触发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()
frameId = bsr.MainFrame().Id
2022-10-04 13:21:05 +08:00
} else {
browseId = target.GetBrowserId()
frameId = target.GetFrameId()
2022-10-04 13:21:05 +08:00
if m.GetBrowserById(browseId).GetFrameById(frameId) == nil {
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
}
// 触发JS监听的事件-同步执行-阻塞UI主线程
//
// 使用不当会造成 UI线程 锁死
//
// 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()
frameId = bsr.MainFrame().Id
2022-10-04 13:21:05 +08:00
} else {
browseId = target.GetBrowserId()
frameId = target.GetFrameId()
2022-10-04 13:21:05 +08:00
if m.GetBrowserById(browseId).GetFrameById(frameId) == nil {
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
}