diff --git a/cef/application_callback.go b/cef/application_callback.go index 9912080a..0300a6ae 100644 --- a/cef/application_callback.go +++ b/cef/application_callback.go @@ -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 } diff --git a/cef/internal/def/proc_def.go b/cef/internal/def/proc_def.go index 7b8b4f73..2255534a 100644 --- a/cef/internal/def/proc_def.go +++ b/cef/internal/def/proc_def.go @@ -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), diff --git a/cef/internal/def/proc_def_index.go b/cef/internal/def/proc_def_index.go index 331888c8..d7c150ff 100644 --- a/cef/internal/def/proc_def_index.go +++ b/cef/internal/def/proc_def_index.go @@ -654,6 +654,7 @@ const ( CEFBrowser_StopLoad CEFBrowser_FrameCount CEFBrowser_GetFrameNames + CEFBrowser_GetFrameIdentifiers CEFBrowser_Find CEFBrowser_StopFinding CEFBrowser_GetRequestContext diff --git a/cef/ipc.go b/cef/ipc.go index bbad431a..9e787200 100644 --- a/cef/ipc.go +++ b/cef/ipc.go @@ -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) diff --git a/cef/ipc_render.go b/cef/ipc_render.go index c1e5c50b..13eadd51 100644 --- a/cef/ipc_render.go +++ b/cef/ipc_render.go @@ -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) diff --git a/cef/types_browser.go b/cef/types_browser.go index 27b184cb..39ba3ed3 100644 --- a/cef/types_browser.go +++ b/cef/types_browser.go @@ -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() { diff --git a/cef/types_frame.go b/cef/types_frame.go index f6ae8fdd..1f0c24bb 100644 --- a/cef/types_frame.go +++ b/cef/types_frame.go @@ -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