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-11-02 12:47:47 +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-10-04 13:21:05 +08:00
|
|
|
"github.com/energye/golcl/lcl"
|
2023-01-16 22:29:28 +08:00
|
|
|
"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 {
|
2022-12-07 22:19:43 +08:00
|
|
|
*lcl.TComponent
|
2023-01-16 22:29:28 +08:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2022-12-01 15:24:22 +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()
|
|
|
|
}
|
2022-12-05 12:07:58 +08:00
|
|
|
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)
|
2023-02-04 23:52:15 +08:00
|
|
|
m.initDefault()
|
2022-10-04 13:21:05 +08:00
|
|
|
return m
|
|
|
|
}
|
|
|
|
|
2023-02-04 23:52:15 +08:00
|
|
|
// 默认的初始配置
|
|
|
|
func (m *TCEFChromium) initDefault() {
|
|
|
|
//通过设置这些首选项,可以降低/避免WebRTC的IP泄漏
|
|
|
|
m.SetWebRTCIPHandlingPolicy(HpDisableNonProxiedUDP)
|
|
|
|
m.SetWebRTCMultipleRoutes(STATE_DISABLED)
|
|
|
|
m.SetWebRTCNonproxiedUDP(STATE_DISABLED)
|
|
|
|
}
|
|
|
|
|
2022-12-05 12:07:58 +08:00
|
|
|
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()
|
2022-10-27 21:03:15 +08:00
|
|
|
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) {
|
2022-12-05 12:07:58 +08:00
|
|
|
_CEFChromium_ExecuteJavaScript(uintptr(m.instance), code, scriptURL, startLine)
|
2022-10-04 13:21:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// 触发JS监听的事件-异步执行
|
|
|
|
//
|
2022-10-24 22:52:08 +08:00
|
|
|
// 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 {
|
2022-10-24 22:52:08 +08:00
|
|
|
bsr := m.Browser()
|
|
|
|
browseId = bsr.Identifier()
|
|
|
|
frameId = bsr.MainFrame().Id
|
2022-10-04 13:21:05 +08:00
|
|
|
} else {
|
2022-10-24 22:52:08 +08:00
|
|
|
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监听的事件-异步执行-带回调
|
|
|
|
//
|
2022-10-24 22:52:08 +08:00
|
|
|
// 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 {
|
2022-10-24 22:52:08 +08:00
|
|
|
bsr := m.Browser()
|
|
|
|
browseId = bsr.Identifier()
|
|
|
|
frameId = bsr.MainFrame().Id
|
2022-10-04 13:21:05 +08:00
|
|
|
} else {
|
2022-10-24 22:52:08 +08:00
|
|
|
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线程 锁死
|
|
|
|
//
|
2022-10-24 22:52:08 +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 {
|
2022-10-24 22:52:08 +08:00
|
|
|
bsr := m.Browser()
|
|
|
|
browseId = bsr.Identifier()
|
|
|
|
frameId = bsr.MainFrame().Id
|
2022-10-04 13:21:05 +08:00
|
|
|
} else {
|
2022-10-24 22:52:08 +08:00
|
|
|
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
|
|
|
|
}
|