upgrade-dev v2.3.7

This commit is contained in:
杨红岩 2023-03-15 14:29:45 +08:00
parent 74a2a71955
commit c395ab46d6
13 changed files with 325 additions and 158 deletions

View File

@ -44,6 +44,8 @@ func browserProcessMessageReceived(browser *ICefBrowser, frame *ICefFrame, sourc
result = ipcBrowser.ipcGoExecuteMethodMessage(browser, frame, sourceProcess, message)
} else if message.Name() == internalProcessMessageIPCOn {
result = ipcBrowser.ipcOnMessage(browser, frame, sourceProcess, message)
} else if message.Name() == internalProcessMessageIPCEmitReply {
result = ipcBrowser.ipcGoExecuteMethodMessageReply(browser, frame, sourceProcess, message)
}
return
}

View File

@ -359,7 +359,7 @@ func init() {
if !*result {
*result = renderProcessMessageReceived(browse, frame, processId, message)
}
//frame.Free()
frame.Free()
//browse.Free()
message.Free()
default:

View File

@ -86,7 +86,7 @@ func init() {
if !*result {
*result = browserProcessMessageReceived(browse, frame, processId, message)
}
//frame.Free()
frame.Free()
//browse.Free()
message.Free()
case ChromiumEventOnResourceLoadComplete:

View File

@ -24,6 +24,41 @@ type ipcBrowserProcess struct {
onHandler *ipcOnHandler // ipc.on handler
}
func (m *ipcBrowserProcess) ipcGoExecuteMethodMessageReply(browser *ICefBrowser, frame *ICefFrame, sourceProcess consts.CefProcessId, message *ICefProcessMessage) (result bool) {
messageId := message.ArgumentList().GetInt(0)
if callback := ipc.CheckEmitCallback(messageId); callback != nil {
//第二个参数 true 有返回参数
if isReturn := message.ArgumentList().GetBool(1); isReturn {
//[]byte
binaryValue := message.ArgumentList().GetBinary(2)
var (
count uint32
resultArgsBytes []byte
)
if binaryValue.IsValid() {
size := binaryValue.GetSize()
resultArgsBytes = make([]byte, size)
count = binaryValue.GetData(resultArgsBytes, 0)
binaryValue.Free()
}
if count > 0 {
ipcContext := ipc.NewContext(browser.Identifier(), frame.Identifier(), false, resultArgsBytes)
if ctxCallback := callback.ContextCallback(); ctxCallback != nil {
ctxCallback.Invoke(ipcContext)
} else if argsCallback := callback.ArgumentCallback(); argsCallback != nil {
argsCallback.Invoke(ipcContext)
}
if ipcContext.ArgumentList() != nil {
ipcContext.ArgumentList().Free()
}
ipcContext.Result(nil)
}
resultArgsBytes = nil
}
}
return
}
// ipcGoExecuteMethodMessage 执行 Go 监听函数
func (m *ipcBrowserProcess) ipcGoExecuteMethodMessage(browser *ICefBrowser, frame *ICefFrame, sourceProcess consts.CefProcessId, message *ICefProcessMessage) (result bool) {
result = true
@ -43,7 +78,7 @@ func (m *ipcBrowserProcess) ipcGoExecuteMethodMessage(browser *ICefBrowser, fram
args.GetData(argsBytes, 0)
args.Free() //立即释放掉
}
ipcContext := ipc.NewContext(browser.Identifier(), frame.Identifier(), argsBytes)
ipcContext := ipc.NewContext(browser.Identifier(), frame.Identifier(), true, argsBytes)
argsBytes = nil
//调用监听函数
if ctxCallback := eventCallback.ContextCallback(); ctxCallback != nil {

View File

@ -72,9 +72,9 @@ func (m *ipcRenderProcess) ipcJSOnEvent(name string, object *ICefV8Value, argume
return
}
var (
onName *ICefV8Value //事件名
onName *ICefV8Value // 事件名
onNameValue string // 事件名
onCallback *ICefV8Value //事件回调函数
onCallback *ICefV8Value // 事件回调函数
)
onName = arguments.Get(0)
//事件名 第一个参数必须是字符串
@ -105,9 +105,12 @@ func (m *ipcRenderProcess) ipcGoExecuteJSEvent(browser *ICefBrowser, frame *ICef
if callback := ipcRender.onHandler.getCallback(name); callback != nil {
messageId := argument.GetInt(0)
args := argument.GetBinary(2)
var argsBytes []byte
var count uint32
var argsV8ValueArray *TCefV8ValueArray
var (
argsBytes []byte
count uint32
argsV8ValueArray *TCefV8ValueArray
resultData []byte
)
if args.IsValid() {
size := args.GetSize()
argsBytes = make([]byte, size)
@ -122,12 +125,25 @@ func (m *ipcRenderProcess) ipcGoExecuteJSEvent(browser *ICefBrowser, frame *ICef
if argsV8ValueArray != nil {
argsV8ValueArray.Free()
}
if ret.IsUndefined() && ret.IsNull() {
resultData = ipcValueConvert.V8ValueToProcessMessageBytes(ret)
}
ret.Free()
callback.context.Exit()
}
argsBytes = nil
if messageId != 0 { // callback
replyMessage := ProcessMessageRef.new(internalProcessMessageIPCEmitReply)
replyMessage.ArgumentList().SetInt(0, messageId)
if resultData != nil {
replyMessage.ArgumentList().SetBool(1, true) //有返回值
binaryValue := BinaryValueRef.New(resultData)
replyMessage.ArgumentList().SetBinary(2, binaryValue) //result []byte
} else {
replyMessage.ArgumentList().SetBool(1, false) //无返回值
}
frame.SendProcessMessage(consts.PID_BROWSER, replyMessage)
replyMessage.Free()
}
result = true
}
@ -246,8 +262,10 @@ func (m *ipcRenderProcess) ipcJSExecuteGoEventMessageReply(browser *ICefBrowser,
if isReturn := message.ArgumentList().GetBool(1); isReturn {
//[]byte
binaryValue := message.ArgumentList().GetBinary(2)
var count uint32
var resultArgsBytes []byte
var (
count uint32
resultArgsBytes []byte
)
if binaryValue.IsValid() {
size := binaryValue.GetSize()
resultArgsBytes = make([]byte, size)
@ -276,7 +294,6 @@ func (m *ipcRenderProcess) ipcJSExecuteGoEventMessageReply(browser *ICefBrowser,
}
//remove
callback.free()
ipcRender.emitHandler.removeCallback(messageId)
}
return
}

View File

@ -252,13 +252,47 @@ func (m *v8ValueProcessMessageConvert) JSONObjectToV8Value(object json.JSONObjec
return result
}
// V8ValueToProcessMessageBytes ICefV8Value 转换 []byte 进程消息
// V8ValueToProcessMessageBytes ICefV8Value 转换 [[]byte] 进程消息
func (m *v8ValueProcessMessageConvert) V8ValueToProcessMessageBytes(v8value *ICefV8Value) []byte {
if v8value.IsArray() {
if result, err := m.V8valueArrayToSlice(v8value); err == nil {
if v, err := jsoniter.Marshal(result); err == nil {
return v
}
}
} else if v8value.IsObject() {
if result, err := m.V8valueObjectToMap(v8value); err == nil {
if v, err := jsoniter.Marshal(result); err == nil {
return v
}
}
} else {
result := make([]any, 1)
if v8value.IsString() {
result[0] = v8value.GetStringValue()
} else if v8value.IsInt() {
result[0] = int(v8value.GetIntValue())
} else if v8value.IsUInt() {
result[0] = uint(v8value.GetUIntValue())
} else if v8value.IsDouble() {
result[0] = v8value.GetDoubleValue()
} else if v8value.IsBool() {
result[0] = v8value.GetBoolValue()
} else if v8value.IsDate() {
result[0] = v8value.GetDateValue()
} else if v8value.IsNull() {
result[0] = "null"
} else if v8value.IsUndefined() {
result[0] = "undefined"
} else if v8value.IsArrayBuffer() {
result[0] = ""
} else {
result[0] = "" // function/byte/buffer
}
if v, err := jsoniter.Marshal(result); err == nil {
return v
}
}
return nil
}
@ -281,6 +315,8 @@ func (m *v8ValueProcessMessageConvert) V8valueArrayToSlice(v8value *ICefV8Value)
result[i] = args.GetDoubleValue()
} else if args.IsBool() {
result[i] = args.GetBoolValue()
} else if v8value.IsDate() {
result[i] = v8value.GetDateValue()
} else if args.IsNull() {
result[i] = "null"
} else if args.IsUndefined() {
@ -327,6 +363,8 @@ func (m *v8ValueProcessMessageConvert) V8valueObjectToMap(v8value *ICefV8Value)
result[key] = args.GetDoubleValue()
} else if args.IsBool() {
result[key] = args.GetBoolValue()
} else if v8value.IsDate() {
result[key] = v8value.GetDateValue()
} else if args.IsNull() {
result[key] = "null"
} else if args.IsUndefined() {

View File

@ -17,13 +17,14 @@ import (
const (
internalIPCKey = "ipc" // JavaScript -> ipc 事件驱动, 根对象名
internalEmit = "emit" // JavaScript -> ipc.emit 在 JavaScript 触发 GO 监听事件函数名
internalEmit = "emit" // JavaScript -> ipc.emit 在 JavaScript 触发 GO 监听事件函数名, 异步
internalEmitSync = "emitSync" // JavaScript -> ipc.emitSync 在 JavaScript 触发 GO 监听事件函数名, 同步
internalOn = "on" // JavaScript -> ipc.on 在 JavaScript 监听事件, 提供给 GO 调用
)
const (
internalProcessMessageIPCEmit = "emitHandler" // 进程消息 emitHandler
internalProcessMessageIPCEmitReply = "ipcEmitReply" // 进程消息 ipcEmitReply
internalProcessMessageIPCOn = "onHandler" // 进程消息 onHandler
internalProcessMessageIPCEmit = "emitHandler" // 进程消息 emit事件处理
internalProcessMessageIPCEmitReply = "emitReply" // 进程消息 emit事件回复消息
internalProcessMessageIPCOn = "onHandler" // 进程消息 on监听事件处理
)
var (
@ -79,7 +80,8 @@ func ipcInit() {
// isIPCInternalKey IPC 内部 key 不允许使用
func isIPCInternalKey(key string) bool {
return key == internalIPCKey || key == internalEmit || key == internalOn ||
key == internalProcessMessageIPCEmit || key == internalProcessMessageIPCOn || key == internalProcessMessageIPCEmitReply
key == internalProcessMessageIPCEmit || key == internalProcessMessageIPCOn || key == internalProcessMessageIPCEmitReply ||
key == internalEmitSync
}
// addCallback
@ -96,20 +98,16 @@ func (m *ipcEmitHandler) addCallback(callback *ipcCallback) int32 {
return m.callbackMessageId
}
// removeCallback
func (m *ipcEmitHandler) removeCallback(messageId int32) {
//m.callbackList.Remove((*list.Element)(unsafe.Pointer(ptr)))
m.callbackLock.Lock()
defer m.callbackLock.Unlock()
delete(m.callbackList, messageId)
}
// getCallback
func (m *ipcEmitHandler) getCallback(messageId int32) *ipcCallback {
//return (*list.Element)(unsafe.Pointer(ptr)).Value.(*ipcCallback)
m.callbackLock.Lock()
defer m.callbackLock.Unlock()
return m.callbackList[messageId]
if callback, ok := m.callbackList[messageId]; ok {
delete(m.callbackList, messageId)
return callback
}
return nil
}
func (m *ipcEmitHandler) clear() {

View File

@ -78,6 +78,8 @@ func main() {
r10[2] = r9
var tm = time.Now().Second()
var cha = 0
//监听事件js触发之后再触发js监听的事件
ipc.On("testGoEmit", func(context ipc.IContext) {
count++
args := context.ArgumentList().JSONArray()
@ -90,27 +92,26 @@ func main() {
cha = args.GetIntByIndex(0)
tm = time.Now().Second()
}
//触发JS监听的函数,并传入参数
//触发JS监听的事件,并传入参数
ipc.Emit("onTestName1", r0, r1+count, r2, r3, r4, r5, r6, r7, r8, r9, r10)
//ipc.EmitAndCallback("", func() {}, "aaaa")
})
ipc.On("testGoEmitAndCallback", func(context ipc.IContext) {
fmt.Println("testGoEmit", context.BrowserId(), context.FrameId())
ipc.On("testGoEmitAndCallback", func() {
fmt.Println("testGoEmitAndCallback")
//触发JS监听的函数并传入参数
ipc.EmitAndCallback("onTestName1", []any{r0, r1 + count, r2, r3, r4, r5, r6, r7, r8, r9, r10}, func() {
ipc.EmitAndCallback("onTestName2", []any{r0, r1 + count, r2, r3, r4, r5, r6, r7, r8, r9, r10}, func(r1 string) {
fmt.Println("onTestName2 r1: ", r1)
})
//ipc.EmitAndCallback("", func() {}, "aaaa")
})
ipc.OnArguments("testResultArgs", func(args1 int) (string, int, float64, bool, *MyError, []string, []*src.StructVarDemo, []src.StructVarDemo, map[string]string, map[string]interface{}, []map[string]interface{}) {
ipc.On("testResultArgs", func(args1 int) (string, int, float64, bool, *MyError, []string, []*src.StructVarDemo, []src.StructVarDemo, map[string]string, map[string]interface{}, []map[string]interface{}) {
fmt.Println("args1", args1)
return r0, r1 + count, r2, r3, r4, r5, r6, r7, r8, r9, r10
})
ipc.OnArguments("testInArgs", func(in1 string, in2 int, in3 float64, in4 bool, in5 []string, in6 []any, in7 map[string]any, in8 src.TestInArgs, in9 map[string]src.TestInArgs) (string, int, bool) {
ipc.On("testInArgs", func(in1 string, in2 int, in3 float64, in4 bool, in5 []string, in6 []any, in7 map[string]any, in8 src.TestInArgs, in9 map[string]src.TestInArgs) (string, int, bool) {
fmt.Println("in1: ", in1)
fmt.Println("in2: ", in2)
fmt.Println("in3: ", in3)

View File

@ -135,8 +135,10 @@
msg("R9", r9, JSON.stringify(r9));
msg("R10", r10, JSON.stringify(r10));
});
ipc.on('onTestName2', function (param1, param2, param3) {
ipc.on('onTestName2', function (r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10) {
clearMsg()
msg("onTestName2");
return ["返回值", 111111, 2222.22, true]
});
let tgesi = null
@ -167,6 +169,34 @@
ipc.emit("testGoEmit", [idx]);
}
let tgesic = null
function autotestGoEmitAndCallback() {
if (tgesic != null) {
clearInterval(tgesic)
tgesic = null
idx = 0;
return
}
tgesic = setInterval(testGoEmitAndCallback, 1)
if (tgesic != null) {
let time = document.getElementById("time").value - 0
if (time > 0) {
setTimeout(function () {
clearInterval(tgesic)
msg(idx)
tgesic = null
idx = 0;
}, time)
}
}
}
function testGoEmitAndCallback() {
ipc.emit("testGoEmitAndCallback");
}
function bindFunc() {
energy.funcName();
}
@ -196,6 +226,9 @@
<button onclick="testGoEmit()">testGoEmit</button>
<button onclick="autotestGoEmit()">自动testGoEmit</button>
<br>
<button onclick="testGoEmitAndCallback()">testGoEmitAndCallback</button>
<button onclick="autotestGoEmitAndCallback()">自动testGoEmitAndCallback</button>
<br>
<button onclick="bindFunc()">bindFunc</button>
<button onclick="bindField()">bindField</button>
</p>

View File

@ -41,13 +41,15 @@ type Context struct {
replay IReplay
}
func NewContext(browserId int32, frameId int64, data []byte) IContext {
func NewContext(browserId int32, frameId int64, isReplay bool, data []byte) IContext {
ctx := &Context{
browserId: browserId,
frameId: frameId,
replay: &Replay{},
argument: json.NewJSONArray(data),
}
if isReplay {
ctx.replay = new(Replay)
}
data = nil
return ctx
}

View File

@ -16,8 +16,6 @@ import (
"reflect"
)
var errorType = reflect.TypeOf((*error)(nil)).Elem()
// callback IPC 监听回调函数
type callback struct {
context *contextCallback //上下文参数回调
@ -26,7 +24,7 @@ type callback struct {
// contextCallback 带上下文的回调函数
type contextCallback struct {
callback emitContextCallback
callback EmitContextCallback
}
// argumentCallback 带参数的回调函数
@ -76,11 +74,17 @@ func (m *callback) ArgumentCallback() *argumentCallback {
// Invoke 调用函数
func (m *argumentCallback) Invoke(context IContext) {
argsList := context.ArgumentList()
argsSize := argsList.Size()
var (
argsList json.JSONArray
argsSize int
inArgsValues []reflect.Value
)
argsList = context.ArgumentList()
if argsList != nil {
argsSize = argsList.Size()
rt := m.callback.Type()
inArgsCount := rt.NumIn()
var inArgsValues = make([]reflect.Value, inArgsCount)
inArgsValues = make([]reflect.Value, inArgsCount)
for i := 0; i < inArgsCount; i++ {
inType := rt.In(i)
if i < argsSize {
@ -175,6 +179,7 @@ func (m *argumentCallback) Invoke(context IContext) {
inArgsValues[i] = reflect.New(inType).Elem()
}
}
}
// call
resultValues := m.callback.Call(inArgsValues)
if len(resultValues) > 0 {

View File

@ -12,6 +12,8 @@
package ipc
// ITarget 指定目标
//
// ipc.NewTarget() *Target
type ITarget interface {
GetBrowserId() int32
GetFrameId() int64

View File

@ -24,16 +24,13 @@ var (
browser *browserIPC
)
// emitContextCallback IPC 上下文件回调函数
type emitContextCallback func(context IContext)
// emitArgumentCallback 带有参数回调函数
type emitArgumentCallback any
// EmitContextCallback IPC 上下文件回调函数
type EmitContextCallback func(context IContext)
// browserIPC 主进程 IPC
type browserIPC struct {
onEvent map[string]*callback
emitCallback map[int32]*reflect.Value
emitCallback map[int32]*callback
emitCallbackMessageId int32
onLock sync.Mutex
emitLock sync.Mutex
@ -42,7 +39,21 @@ type browserIPC struct {
func init() {
if common.Args.IsMain() {
browser = &browserIPC{onEvent: make(map[string]*callback), emitCallback: make(map[int32]*reflect.Value)}
browser = &browserIPC{onEvent: make(map[string]*callback), emitCallback: make(map[int32]*callback)}
}
}
func createCallback(fn any) *callback {
switch fn.(type) {
case func(context IContext):
return &callback{context: &contextCallback{callback: fn.(func(context IContext))}}
default:
v := reflect.ValueOf(fn)
// f must be a function
if v.Kind() != reflect.Func {
return nil
}
return &callback{argument: &argumentCallback{callback: &v}}
}
}
@ -54,12 +65,9 @@ func SetProcessMessage(pm IProcessMessage) {
}
//On
// IPC GO 监听事件, 上下文参数
func On(name string, fn emitContextCallback) {
browser.addOnEvent(name, &callback{context: &contextCallback{callback: fn}})
}
//OnArguments
//
// 参数 回调函数fn: EmitContextCallback 或 func
//
// IPC GO 监听事件, 自定义参数,仅支持对应 JavaScript 对应 Go 的常用类型
//
// 入参 不限制个数
@ -85,15 +93,10 @@ func On(name string, fn emitContextCallback) {
//
// 出参
//
// 与同入参相同
func OnArguments(name string, fn emitArgumentCallback) {
if browser != nil {
v := reflect.ValueOf(fn)
// f must be a function
if v.Kind() != reflect.Func {
return
}
browser.addOnEvent(name, &callback{argument: &argumentCallback{callback: &v}})
// 与入参相同
func On(name string, fn any) {
if callbackFN := createCallback(fn); callbackFN != nil {
browser.addOnEvent(name, callbackFN)
}
}
@ -110,6 +113,12 @@ func RemoveOn(name string) {
//Emit
// IPC GO 中触发 JS 监听的事件
//
// 参数
// name: JS 监听的事件名
// []argument: 入参 基本类型: int(int8 ~ uint64), bool, float(float32、float64), string
// 复杂类型: slice, map, struct
// 复杂类型限制示例: slice: []interface{}, map: map[string]interface{}
func Emit(name string, argument ...any) {
if browser == nil || name == "" || browser.processMessage == nil {
return
@ -119,6 +128,13 @@ func Emit(name string, argument ...any) {
//EmitAndCallback
// IPC GO 中触发 JS 监听的事件
//
// 参数
// name: JS 监听的事件名
// []argument: 入参 基本类型: int(int8 ~ uint64), bool, float(float32、float64), string
// 复杂类型: slice, map, struct
// 复杂类型限制示例: slice: []interface{}, map: map[string]interface{}
// callback: 无返回值的回调函数, 接收返回值. 函数类型 EmitContextCallback 或 func(...) {}
func EmitAndCallback(name string, argument []any, callback any) {
if browser == nil || name == "" || browser.processMessage == nil {
return
@ -129,6 +145,13 @@ func EmitAndCallback(name string, argument []any, callback any) {
//EmitTarget
// IPC GO 中触发指定目标 JS 监听的事件
//
// 参数
// name: JS 监听的事件名
// target: 接收事件的目标
// []argument: 入参 基本类型: int(int8 ~ uint64), bool, float(float32、float64), string
// 复杂类型: slice, map, struct
// 复杂类型限制示例: slice: []interface{}, map: map[string]interface{}
func EmitTarget(name string, target ITarget, argument ...any) {
if browser == nil || name == "" || browser.processMessage == nil {
return
@ -138,6 +161,14 @@ func EmitTarget(name string, target ITarget, argument ...any) {
//EmitTargetAndCallback
// IPC GO 中触发指定目标 JS 监听的事件
//
// 参数
// name: JS 监听的事件名
// target: 接收事件的目标
// []argument: 入参 基本类型: int(int8 ~ uint64), bool, float(float32、float64), string
// 复杂类型: slice, map, struct
// 复杂类型限制示例: slice: []interface{}, map: map[string]interface{}
// callback: 无返回值的回调函数, 接收返回值. 函数类型 EmitContextCallback 或 func(...) {}
func EmitTargetAndCallback(name string, target ITarget, argument []any, callback any) {
if browser == nil || name == "" || browser.processMessage == nil {
return
@ -162,15 +193,15 @@ func CheckOnEvent(name string) *callback {
//CheckEmitCallback
// IPC 检查 GO Emit 回调函数是否存在,并返回回调函数
func CheckEmitCallback(id int32) *reflect.Value {
func CheckEmitCallback(id int32) *callback {
if browser == nil {
return nil
}
browser.emitLock.Lock()
defer browser.emitLock.Unlock()
if fn, ok := browser.emitCallback[id]; ok {
delete(browser.emitCallback, id) //移除这个回调函数
return fn //返回
delete(browser.emitCallback, id)
return fn
}
return nil
}
@ -206,11 +237,14 @@ func (m *browserIPC) addEmitCallback(fn any) int32 {
}
m.emitLock.Lock()
defer m.emitLock.Unlock()
if callbackFN := createCallback(fn); callbackFN != nil {
if m.emitCallbackMessageId == -1 {
m.emitCallbackMessageId = 1
} else {
m.emitCallbackMessageId++
}
m.emitCallback[m.emitCallbackMessageId] = &rv
m.emitCallback[m.emitCallbackMessageId] = callbackFN
return m.emitCallbackMessageId
}
return 0
}