dom-visitor.go 5.2 KB
Newer Older
yanghye's avatar
yanghye 已提交
1 2 3 4 5
package main

import (
	"embed"
	"fmt"
yanghye's avatar
yanghye 已提交
6 7 8 9 10
	"github.com/energye/energy/v2/cef"
	"github.com/energye/energy/v2/cef/ipc"
	"github.com/energye/energy/v2/cef/ipc/callback"
	"github.com/energye/energy/v2/cef/ipc/types"
	"github.com/energye/energy/v2/cef/process"
yanghye's avatar
yanghye 已提交
11
	"github.com/energye/energy/v2/common"
yanghye's avatar
yanghye 已提交
12 13
	"github.com/energye/energy/v2/consts"
	"github.com/energye/energy/v2/pkgs/assetserve"
yanghye's avatar
yanghye 已提交
14 15 16 17 18 19 20 21 22 23 24 25 26 27
	//_ "net/http/pprof"
)

//go:embed resources
var resources embed.FS

func main() {
	//全局初始化 每个应用都必须调用的
	cef.GlobalInit(nil, &resources)
	//创建应用
	var app = cef.NewApplication()
	//指定一个URL地址,或本地html文件目录
	cef.BrowserWindow.Config.Url = "http://localhost:22022/dom-visitor.html"
	cef.BrowserWindow.Config.Title = "Energy - dom-visitor"
28
	if common.IsLinux() && app.IsUIGtk3() {
yanghye's avatar
yanghye 已提交
29 30 31 32
		cef.BrowserWindow.Config.IconFS = "resources/icon.png"
	} else {
		cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
	}
yanghye's avatar
yanghye 已提交
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75

	// DomVisitor 必须在渲染进程中执行
	// 示例
	//	1. JS 通过 ipc 消息发送到主进程
	//  2. 在主进程中发送渲染进程消息
	//  3. 渲染进程中使用 DomVisitor
	// CEF DomVisitor 不如JS提供的功能函数全面
	ipc.On("dom-visitor", func(channel callback.IChannel) {
		// 此时在主进程中,我们将消息通过 frame.SendProcessMessage 发送到渲染进程
		wi := cef.BrowserWindow.GetWindowInfo(channel.BrowserId())
		fmt.Println("wi", wi, wi.Browser().MainFrame().Identifier())
		// 发送渲染进程消息
		// data 不能为空, 且大于 0 个
		wi.Browser().MainFrame().SendProcessMessageForJSONBytes("dom-visitor-test", consts.PID_RENDER, []byte("test data"))
	})

	// 仅渲染(子)进程监听事件
	// 示例
	//	1. JS 通过 ipc 配置规则 发送消息到当前子进程
	//  2. 当前子进程接收到消息后创建 DomVisitor
	//  3. 渲染进程中使用 DomVisitor
	//  4. 在渲染进程的IPC消息事件中可以通过 V8ContextRef.Current() 获得 Browser 和 Frame 对象
	// CEF DomVisitor 不如JS提供的功能函数全面
	ipc.On("render-dom-visitor", func(channel callback.IChannel, args1 string) int64 {
		fmt.Println("render-dom-visitor", "channelId", channel.ChannelId(), "current-Id:", cef.V8ContextRef.Current().Frame().Identifier(), "args:", args1)
		// 创建 dom visitor
		visitor := cef.DomVisitorRef.New()
		// 监听事件
		// 这个事件在渲染进程中才会执行
		visitor.SetOnVisit(func(document *cef.ICefDomDocument) {
			fmt.Println("title:", document.GetTitle())
			body := document.GetBody()
			fmt.Println("body-InnerText:", body.GetElementInnerText())
			fmt.Println("GetNodeType:", body.GetNodeType())
			fmt.Println("button-domVisitor:", body.GetDocument().GetElementById("domVisitor").GetElementInnerText())
			fmt.Println("button-attrs:", body.GetDocument().GetElementById("domVisitor").GetElementAttributes())
			body.GetDocument().GetElementById("domVisitor").SetElementAttribute("id", "modify") // 把button按钮的id属性值更改了
		})
		fmt.Println("visitor:", visitor)
		// 只能在渲染进程中的IPC消息事件中使用 V8ContextRef.Current()
		cef.V8ContextRef.Current().Frame().VisitDom(visitor)
		fmt.Println("visitor-browserId:", cef.V8ContextRef.Current().Browser().Identifier())
		fmt.Println("visitor-frameId:", cef.V8ContextRef.Current().Frame().Identifier())
76
		fmt.Println("visitor-frameId:", process.FrameId())
yanghye's avatar
yanghye 已提交
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122

		return process.FrameId()
		// OtSub 仅子进程监听该事件
	}, types.OnOptions{OnType: types.OtSub})

	// 监听渲染进程消息-在这里获取dom元素
	app.SetOnProcessMessageReceived(func(browser *cef.ICefBrowser, frame *cef.ICefFrame, sourceProcess consts.CefProcessId, message *cef.ICefProcessMessage) bool {
		if message.Name() == "dom-visitor-test" {
			// 读取 data 数据 也可以不读取
			buf := message.ArgumentList().GetBinary(0) // 因为传递的是字节数组
			data := make([]byte, buf.GetSize())        // data 缓存区
			buf.GetData(data, 0)                       //读取数据
			buf.Free()                                 // 读取完释放掉

			// 创建 dom visitor
			visitor := cef.DomVisitorRef.New()
			// 监听事件
			// 这个事件在渲染进程中才会执行
			visitor.SetOnVisit(func(document *cef.ICefDomDocument) {
				fmt.Println("title:", document.GetTitle())
				body := document.GetBody()
				fmt.Println("body-InnerText:", body.GetElementInnerText())
				fmt.Println("GetNodeType:", body.GetNodeType())
				fmt.Println("button-domVisitor:", body.GetDocument().GetElementById("domVisitor").GetElementInnerText())
				fmt.Println("button-attrs:", body.GetDocument().GetElementById("domVisitor").GetElementAttributes())
				body.GetDocument().GetElementById("domVisitor").SetElementAttribute("id", "modify")
			})
			fmt.Println("visitor:", visitor)
			frame.VisitDom(visitor)
			return true // 接收消息已处理
		}
		return false // 接收不需要处理的消息 返回 false
	})
	//内置http服务链接安全配置
	cef.SetBrowserProcessStartAfterCallback(func(b bool) {
		fmt.Println("主进程启动 创建一个内置http服务")
		//通过内置http服务加载资源
		server := assetserve.NewAssetsHttpServer()
		server.PORT = 22022
		server.AssetsFSName = "resources" //必须设置目录名
		server.Assets = &resources
		go server.StartHttpServer()
	})
	//运行应用
	cef.Run(app)
}