Fix: #32 The rendering process ipc listens for adding a frameId group.

Add a frame object to implement the ipc target.IWindow interface
This commit is contained in:
yanghy 2024-06-23 15:34:51 +08:00
parent 8a7cedb131
commit 70c2fb82e1
7 changed files with 86 additions and 34 deletions

View File

@ -13,6 +13,7 @@
package cef
import (
"fmt"
"github.com/energye/energy/v2/cef/internal/ipc"
"github.com/energye/energy/v2/cef/internal/process"
"github.com/energye/energy/v2/consts"
@ -21,11 +22,12 @@ import (
// 创建应用上下文 - 默认实现
func appOnContextCreated(browser *ICefBrowser, frame *ICefFrame, context *ICefV8Context) {
fmt.Println("appOnContextCreated browserId:", browser.Identifier(), " frameId:", frame.Identifier(), "IsMain:", frame.IsMain())
process.Current.SetBrowserId(browser.Identifier()) // 当前进程 browserID
process.Current.SetFrameId(frame.Identifier()) // 当前进程 frameId
ipc.RenderChan().SetRealityChannel(browser.Identifier(), frame.Identifier()) // 设置并更新真实的通道ID
ipcRender.registerGoWaitReplayEvent() // render ipc
ipcRender.makeIPC(context) // render ipc make
ipcRender.makeIPC(frame.Identifier(), context) // render ipc make
makeProcess(browser, frame, context) // process make
}

View File

@ -654,6 +654,7 @@ func init() {
dllimports.NewEnergyImport("CEFBrowser_StopLoad", 0),
dllimports.NewEnergyImport("CEFBrowser_FrameCount", 0),
dllimports.NewEnergyImport("CEFBrowser_GetFrameNames", 0),
dllimports.NewEnergyImport("CEFBrowser_GetFrameIdentifiers", 0),
dllimports.NewEnergyImport("CEFBrowser_Find", 0),
dllimports.NewEnergyImport("CEFBrowser_StopFinding", 0),
dllimports.NewEnergyImport("CEFBrowser_GetRequestContext", 0),

View File

@ -654,6 +654,7 @@ const (
CEFBrowser_StopLoad
CEFBrowser_FrameCount
CEFBrowser_GetFrameNames
CEFBrowser_GetFrameIdentifiers
CEFBrowser_Find
CEFBrowser_StopFinding
CEFBrowser_GetRequestContext

View File

@ -52,7 +52,7 @@ var (
ipcBrowser *ipcBrowserProcess // 主进程 IPC
)
// ipcEmitHandler ipc.emit 处理器
// ipc.emit 处理器
type ipcEmitHandler struct {
handler *ICefV8Handler // ipc.emit handler
handlerSync *ICefV8Handler // ipc.emitSync handler
@ -61,14 +61,14 @@ type ipcEmitHandler struct {
callbackLock sync.Mutex // ipc.emit lock
}
// ipcOnHandler ipc.on 处理器
// ipc.on 处理器
type ipcOnHandler struct {
handler *ICefV8Handler // ipc.on handler
callbackList map[string]*ipcCallback // ipc.on callbackList
callbackLock sync.Mutex // ipc.emit lock
}
// ipcCallback ipc.emit 回调结果
// ipc.emit 回调结果
type ipcCallback struct {
isSync bool //同否同步 true:同步 false:异步, 默认false
resultType result_type //返回值类型 0:function 1:variable 默认:0
@ -77,7 +77,7 @@ type ipcCallback struct {
name *ICefV8Value //事件名称
}
// isIPCInternalKey IPC 内部定义使用 key 不允许使用
// IPC 内部定义使用 key 不允许使用
func isIPCInternalKey(key string) bool {
return key == internalIPC || key == internalIPCEmit || key == internalIPCOn || key == internalIPCDRAG || key == internalIPCEmitWait ||
key == internalIPCJSExecuteGoEvent || key == internalIPCJSExecuteGoEventReplay ||
@ -86,15 +86,15 @@ func isIPCInternalKey(key string) bool {
}
// ipcInit 初始化
// 初始化
func ipcInit() {
isSingleProcess := application.SingleProcess()
if isSingleProcess {
ipcBrowser = &ipcBrowserProcess{}
ipcRender = &ipcRenderProcess{
waitChan: &ipc.WaitChan{Pending: new(sync.Map)},
emitHandler: &ipcEmitHandler{callbackList: make(map[int32]*ipcCallback)},
onHandler: &ipcOnHandler{callbackList: make(map[string]*ipcCallback)},
waitChan: &ipc.WaitChan{Pending: new(sync.Map)},
emitHandler: &ipcEmitHandler{callbackList: make(map[int32]*ipcCallback)},
onFrameHandler: make(map[int64]*ipcOnHandler),
}
ipc.CreateBrowserIPC() // Go IPC browser
ipc.CreateRenderIPC(0, time.Now().UnixNano()/1e6) // Go IPC render
@ -104,16 +104,16 @@ func ipcInit() {
ipc.CreateBrowserIPC() // Go IPC browser
} else if process.Args.IsRender() {
ipcRender = &ipcRenderProcess{
waitChan: &ipc.WaitChan{Pending: new(sync.Map)},
emitHandler: &ipcEmitHandler{callbackList: make(map[int32]*ipcCallback)},
onHandler: &ipcOnHandler{callbackList: make(map[string]*ipcCallback)},
waitChan: &ipc.WaitChan{Pending: new(sync.Map)},
emitHandler: &ipcEmitHandler{callbackList: make(map[int32]*ipcCallback)},
onFrameHandler: make(map[int64]*ipcOnHandler),
}
ipc.CreateRenderIPC(0, time.Now().UnixNano()/1e6) // Go IPC render
}
}
}
// addCallback
// 添加一个回调函数
func (m *ipcEmitHandler) addCallback(callback *ipcCallback) int32 {
//return uintptr(unsafe.Pointer(m.callbackList.PushBack(callback)))
m.callbackLock.Lock()
@ -122,7 +122,7 @@ func (m *ipcEmitHandler) addCallback(callback *ipcCallback) int32 {
return m.callbackMessageId
}
// nextMessageId 获取下一个消息ID
// 获取下一个消息ID
func (m *ipcEmitHandler) nextMessageId() int32 {
m.callbackMessageId++
if m.callbackMessageId == -1 {
@ -131,7 +131,7 @@ func (m *ipcEmitHandler) nextMessageId() int32 {
return m.callbackMessageId
}
// getCallback 返回回调函数
// 返回回调函数
func (m *ipcEmitHandler) getCallback(messageId int32) *ipcCallback {
//return (*list.Element)(unsafe.Pointer(ptr)).Value.(*ipcCallback)
m.callbackLock.Lock()
@ -143,7 +143,7 @@ func (m *ipcEmitHandler) getCallback(messageId int32) *ipcCallback {
return nil
}
// clear 清空所有回调函数
// 清空所有回调函数
func (m *ipcEmitHandler) clear() {
for _, v := range m.callbackList {
v.function.SetCanNotFree(false)
@ -154,7 +154,7 @@ func (m *ipcEmitHandler) clear() {
m.callbackList = make(map[int32]*ipcCallback)
}
// addCallback 根据事件名添加回调函数
// 根据事件名添加回调函数
func (m *ipcOnHandler) addCallback(eventName string, callback *ipcCallback) {
//return uintptr(unsafe.Pointer(m.callbackList.PushBack(callback)))
m.callbackLock.Lock()
@ -168,7 +168,7 @@ func (m *ipcOnHandler) addCallback(eventName string, callback *ipcCallback) {
m.callbackList[eventName] = callback
}
// removeCallback 根据事件名移除回调函数
// 根据事件名移除回调函数
func (m *ipcOnHandler) removeCallback(eventName string) {
//m.callbackList.Remove((*list.Element)(unsafe.Pointer(ptr)))
m.callbackLock.Lock()
@ -176,7 +176,7 @@ func (m *ipcOnHandler) removeCallback(eventName string) {
delete(m.callbackList, eventName)
}
// getCallback 根据事件名返回回调函数
// 根据事件名返回回调函数
func (m *ipcOnHandler) getCallback(eventName string) *ipcCallback {
//return (*list.Element)(unsafe.Pointer(ptr)).Value.(*ipcCallback)
m.callbackLock.Lock()
@ -184,7 +184,7 @@ func (m *ipcOnHandler) getCallback(eventName string) *ipcCallback {
return m.callbackList[eventName]
}
// clear 清空所有回调函数
// 清空所有回调函数
func (m *ipcOnHandler) clear() {
for _, v := range m.callbackList {
v.function.SetCanNotFree(false)

View File

@ -26,24 +26,27 @@ import (
// ipcRenderProcess 渲染进程
type ipcRenderProcess struct {
isInitRenderIPC bool
ipcObject *ICefV8Value // ipc object
emitHandler *ipcEmitHandler // ipc.emit handler
onHandler *ipcOnHandler // ipc.on handler
ipcObject *ICefV8Value // ipc object
emitHandler *ipcEmitHandler // ipc.emit handler
onHandler map[int64]*ipcOnHandler // ipc.on handler
waitChan *ipc.WaitChan
}
func (m *ipcRenderProcess) clear() {
func (m *ipcRenderProcess) clear(frameId int64) {
if m.ipcObject != nil {
m.ipcObject.Free()
m.ipcObject = nil
}
if m.onHandler != nil {
m.onHandler.clear()
if on, ok := m.onHandler[frameId]; ok {
on.clear()
delete(m.onHandler, frameId)
}
}
}
// jsOnEvent JS ipc.on 监听事件
func (m *ipcRenderProcess) jsOnEvent(name string, object *ICefV8Value, arguments *TCefV8ValueArray, retVal *ResultV8Value, exception *ResultString) (result bool) {
// JS ipc.on 监听事件
func (m *ipcOnHandler) jsOnEvent(name string, object *ICefV8Value, arguments *TCefV8ValueArray, retVal *ResultV8Value, exception *ResultString) (result bool) {
if name != internalIPCOn {
return
} else if arguments.Size() != 2 { //必须是2个参数
@ -74,13 +77,17 @@ func (m *ipcRenderProcess) jsOnEvent(name string, object *ICefV8Value, arguments
onCallback.SetCanNotFree(true)
onNameValue = onName.GetStringValue()
//ipc on
m.onHandler.addCallback(onNameValue, &ipcCallback{function: V8ValueRef.UnWrap(onCallback), name: V8ValueRef.UnWrap(onName)})
m.addCallback(onNameValue, &ipcCallback{function: V8ValueRef.UnWrap(onCallback), name: V8ValueRef.UnWrap(onName)})
result = true
return
}
// Go ipc.emit 执行JS事件
func (m *ipcRenderProcess) ipcGoExecuteJSEvent(browser *ICefBrowser, frame *ICefFrame, sourceProcess consts.CefProcessId, message *ICefProcessMessage) (result bool) {
on, ok := m.onHandler[frame.Identifier()]
if !ok {
return false
}
result = true
argumentListBytes := message.ArgumentList().GetBinary(0)
//接收二进制数据失败
@ -120,7 +127,7 @@ func (m *ipcRenderProcess) ipcGoExecuteJSEvent(browser *ICefBrowser, frame *ICef
}
}()
if callback := ipcRender.onHandler.getCallback(emitName); callback != nil {
if callback := on.getCallback(emitName); callback != nil {
var callbackArgsBytes interface{}
//enter v8context
ctx := frame.V8Context()
@ -737,10 +744,10 @@ func (m *ipcRenderProcess) ipcJSExecuteGoSyncEventMessageReply(messageId int32,
}
// ipc
func (m *ipcRenderProcess) makeIPC(context *ICefV8Context) {
func (m *ipcRenderProcess) makeIPC(frameId int64, context *ICefV8Context) {
if m.ipcObject != nil {
// 刷新时释放掉
m.clear()
m.clear(frameId)
}
// ipc emit
m.emitHandler.handler = V8HandlerRef.New()
@ -751,14 +758,24 @@ func (m *ipcRenderProcess) makeIPC(context *ICefV8Context) {
m.emitHandler.handlerSync.Execute(m.jsExecuteGoEvent)
// ipc on
m.onHandler.handler = V8HandlerRef.New()
m.onHandler.handler.Execute(m.jsOnEvent)
var on *ipcOnHandler
if handler, ok := m.onHandler[frameId]; ok {
on = handler
} else {
on = &ipcOnHandler{handler: V8HandlerRef.New(), callbackList: make(map[string]*ipcCallback)}
on.handler.Execute(on.jsOnEvent)
m.onHandler[frameId] = on
}
//m.onHandler.handler = V8HandlerRef.New()
//m.onHandler.handler.Execute(m.jsOnEvent)
//on.handler = V8HandlerRef.New()
// ipc object
m.ipcObject = V8ValueRef.NewObject(nil)
m.ipcObject.setValueByKey(internalIPCEmit, V8ValueRef.newFunction(internalIPCEmit, m.emitHandler.handler), consts.V8_PROPERTY_ATTRIBUTE_READONLY)
m.ipcObject.setValueByKey(internalIPCEmitWait, V8ValueRef.newFunction(internalIPCEmitWait, m.emitHandler.handlerSync), consts.V8_PROPERTY_ATTRIBUTE_READONLY)
m.ipcObject.setValueByKey(internalIPCOn, V8ValueRef.newFunction(internalIPCOn, m.onHandler.handler), consts.V8_PROPERTY_ATTRIBUTE_READONLY)
m.ipcObject.setValueByKey(internalIPCOn, V8ValueRef.newFunction(internalIPCOn, on.handler), consts.V8_PROPERTY_ATTRIBUTE_READONLY)
// ipc key to v8 global
context.Global().setValueByKey(internalIPC, m.ipcObject, consts.V8_PROPERTY_ATTRIBUTE_READONLY)

View File

@ -520,6 +520,15 @@ func (m *ICefBrowser) GetFrameNames() []*FrameNames {
return frameNames
}
func (m *ICefBrowser) GetFrameIdentifiers() []int64 {
var list uintptr
var count uint32
var ids uintptr
imports.Proc(def.CEFBrowser_GetFrameIdentifiers).Call(m.Instance(), uintptr(unsafe.Pointer(&list)), uintptr(unsafe.Pointer(&count)), uintptr(unsafe.Pointer(&ids)))
// TODO 未取到正确结果
return nil
}
// Find 检索页面文本
func (m *ICefBrowser) Find(searchText string, forward, matchCase, findNext bool) {
if !m.IsValid() {

View File

@ -264,6 +264,28 @@ func (m *ICefFrame) Parent() *ICefFrame {
return &ICefFrame{instance: unsafe.Pointer(result)}
}
func (m *ICefFrame) Target(targetType ...target.Type) target.ITarget {
if !m.IsValid() {
return nil
}
browse := m.Browser()
if !browse.IsValid() {
return nil
}
return target.NewTarget(m, browse.Identifier(), m.Identifier(), targetType...)
}
func (m *ICefFrame) IsClosing() bool {
return false //Determine whether the window has been closed by oneself
}
func (m *ICefFrame) ProcessMessage() target.IProcessMessage {
if m == nil {
return nil
}
return m
}
func (m *ICefFrame) Free() {
if !m.IsValid() {
return