梳理事件流

This commit is contained in:
xuyanfeng 2021-04-28 13:59:16 +08:00
parent 7b3ee52a6d
commit c4fb53646f
9 changed files with 167 additions and 141 deletions

View File

@ -1,6 +1,4 @@
import * as PluginMsg from "./core/plugin-msg" import {PluginEvent, Page, Msg} from "@/core/types";
import {PluginEvent} from "@/devtools/type";
import {MsgInclude} from "./core/plugin-msg";
let Devtools: chrome.runtime.Port | null = null; let Devtools: chrome.runtime.Port | null = null;
let Content: chrome.runtime.Port | null = null; let Content: chrome.runtime.Port | null = null;
@ -8,12 +6,13 @@ console.log('on background')
chrome.runtime.onConnect.addListener((port: chrome.runtime.Port) => { chrome.runtime.onConnect.addListener((port: chrome.runtime.Port) => {
switch (port.name) { switch (port.name) {
case PluginMsg.Page.Devtools: { case Page.Devtools: {
Devtools = port; Devtools = port;
onPortConnect(port, onPortConnect(port,
(data: PluginEvent) => { (data: PluginEvent) => {
// 从devtools过来的消息统一派发到Content中 // 从devtools过来的消息统一派发到Content中
if (MsgInclude(data.msg)) { if (data.target === Page.Background) {
data.target = Page.Content;
Content && Content.postMessage(data) Content && Content.postMessage(data)
} }
}, },
@ -22,7 +21,7 @@ chrome.runtime.onConnect.addListener((port: chrome.runtime.Port) => {
}) })
break; break;
} }
case PluginMsg.Page.Content: { case Page.Content: {
Content = port; Content = port;
onPortConnect(port, onPortConnect(port,
() => { () => {
@ -41,6 +40,7 @@ function onPortConnect(port: chrome.runtime.Port, onMsg: Function, onDisconnect:
console.log(`%c[Connect] ${port.name}`, "color:blue;"); console.log(`%c[Connect] ${port.name}`, "color:blue;");
port.onMessage.addListener((data: any, sender: any) => { port.onMessage.addListener((data: any, sender: any) => {
console.log(`%c[Connect-Message] ${sender.name}\n${JSON.stringify(data)}`, "color:green;") console.log(`%c[Connect-Message] ${sender.name}\n${JSON.stringify(data)}`, "color:green;")
// 如果多个页面都监听 onMessage 事件,对于某一次事件只有第一次调用 sendResponse() 能成功发出回应,所有其他回应将被忽略。
// sender.postMessage(data); // sender.postMessage(data);
onMsg && onMsg(data); onMsg && onMsg(data);
}); });
@ -53,10 +53,11 @@ function onPortConnect(port: chrome.runtime.Port, onMsg: Function, onDisconnect:
// background.js 更像是一个主进程,负责整个插件的调度,生命周期和chrome保持一致 // background.js 更像是一个主进程,负责整个插件的调度,生命周期和chrome保持一致
// 监听来自content.js发来的事件将消息转发到devtools // 监听来自content.js发来的事件将消息转发到devtools
chrome.runtime.onMessage.addListener((request: any, sender: any, sendResponse: any) => { chrome.runtime.onMessage.addListener((request: PluginEvent, sender: any, sendResponse: any) => {
console.log(`%c[Message]url:${sender.url}]\n${JSON.stringify(request)}`, 'color:green') if (request.target === Page.Background) {
sendResponse && sendResponse(request); request.target = Page.Devtools;
if (MsgInclude(request.msg)) { console.log(`%c[Message]url:${sender.url}]\n${JSON.stringify(request)}`, 'color:green')
sendResponse && sendResponse(request);
Devtools && Devtools.postMessage(request); Devtools && Devtools.postMessage(request);
} }
} }
@ -65,9 +66,9 @@ chrome.runtime.onMessage.addListener((request: any, sender: any, sendResponse: a
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) { chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
if (changeInfo.status === "complete") { if (changeInfo.status === "complete") {
// 加载新的url // 加载新的url
if (Content) { // if (Content) {
Content.postMessage(new PluginEvent(PluginMsg.Msg.UrlChange, {url: tab.favIconUrl})); // Content.postMessage(new PluginEvent(Msg.UrlChange, {url: tab.favIconUrl}));
} // }
} }
}) })

View File

@ -1,29 +1,35 @@
// content.js 和原始界面共享DOM具有操作dom的能力 // content.js 和原始界面共享DOM具有操作dom的能力
// 但是不共享js,要想访问页面js,只能通过注入的方式 // 但是不共享js,要想访问页面js,只能通过注入的方式
import * as PluginMsg from './core/plugin-msg'
import {injectScript} from "@/core/util"; import {injectScript} from "@/core/util";
import {PluginEvent} from "@/devtools/type"; import {PluginEvent, Page, Msg} from "@/core/types";
injectScript("js/inject.js"); injectScript("js/inject.js");
// 和background.js保持长连接通讯 // 和background.js保持长连接通讯
let conn = chrome.runtime.connect({name: PluginMsg.Page.Content}) let conn = chrome.runtime.connect({name: Page.Content})
conn.onMessage.addListener(function (data) { conn.onMessage.addListener((data: PluginEvent, sender) => {
// 将background.js的消息返回到injection.js // 将background.js的消息返回到injection.js
console.log(`%c[Connect-Message] ${JSON.stringify(data)}`, "color:green;") console.log(`%c[Connect-Message] ${JSON.stringify(data)}`, "color:green;")
window.postMessage(data, "*"); if (data.target === Page.Content) {
data.target = Page.Inject;
window.postMessage(data, "*");
}
}) })
// 接受来自inject.js的消息数据,然后中转到background.js // 接受来自inject.js的消息数据,然后中转到background.js
// window.addEventListener('message', function (event) { window.addEventListener('message', function (event) {
// let data = event.data; let data: PluginEvent = event.data;
// console.log(`%c[Window-Message] ${JSON.stringify(data)}`, "color:green;"); console.log(`%c[Window-Message] ${JSON.stringify(data)}`, "color:green;");
// chrome.runtime.sendMessage(data); if (data.target === Page.Inject) {
// }, false); data.target = Page.Background;
chrome.runtime.sendMessage(data);
}
}, false);
let gameCanvas = document.querySelector("#GameCanvas"); let gameCanvas = document.querySelector("#GameCanvas");
if (!gameCanvas) { if (!gameCanvas) {
let sendData = new PluginEvent(PluginMsg.Msg.Support, { let sendData = new PluginEvent(Page.Background, Msg.Support, {
support: false, support: false,
msg: "未发现GameCanvas,不支持调试游戏!" msg: "未发现GameCanvas,不支持调试游戏!"
}) })

View File

@ -1,29 +0,0 @@
export const Page = {
Inject: "Inject",
Devtools: "Devtools",
Content: "Content",
Popup: "Popup",
Options: "Options",
}
export const Msg = {
NodeInfo: "node-info",// 具体的节点信息
TreeInfo: "tree-info",// 节点树信息
Support: "game-support",// 游戏支持信息
MemoryInfo: "memory-info",//
TabsInfo: "tabs_info", // 当前页面信息
UrlChange: "url_change", // 网址发生变化
SetProperty: "set-property", // 设置node属性
}
export function MsgInclude(msg: string) {
for (let key in Msg) {
if (Msg.hasOwnProperty(key)) {
//@ts-ignore
let m = Msg[key] as string;
if (m === msg) {
return true
}
}
}
return false;
}

56
source/src/core/types.ts Normal file
View File

@ -0,0 +1,56 @@
export enum Page {
Inject = "Inject",
Devtools = "Devtools",
Background = 'Background',
Content = "Content",
Popup = "Popup",
Options = "Options",
}
export enum Msg {
NodeInfo = "node-info",// 具体的节点信息
TreeInfo = "tree-info",// 节点树信息
Support = "game-support",// 游戏支持信息
MemoryInfo = "memory-info",//
TabsInfo = "tabs_info", // 当前页面信息
UrlChange = "url_change", // 网址发生变化
SetProperty = "set-property", // 设置node属性
}
export class PluginEvent {
msg: Msg | null = null;
data: any = null;
target: Page | null = null; // 事件要发送的目标
constructor(target: Page, msg: Msg, data?: any) {
if (PageInclude(target)) {
this.target = target;
this.msg = msg;
this.data = data || null;
} else {
console.warn(`无效的target: ${target}`)
}
}
}
function inEnum(enumValues: any, value: Page | Msg) {
for (let key in enumValues) {
if (enumValues.hasOwnProperty(key)) {
//@ts-ignore
let itemEnum = enumValues[key] as string;
if (itemEnum === value) {
return true
}
}
}
return false;
}
export function PageInclude(page: Page) {
return inEnum(Page, page);
}
export function MsgInclude(msg: Msg) {
return inEnum(Msg, msg)
}

View File

@ -1,12 +1,11 @@
import * as PluginMsg from "@/core/plugin-msg"; import {PluginEvent, Page} from "@/core/types";
import {PluginEvent} from "@/devtools/type";
class ConnectBackground { class ConnectBackground {
connect: chrome.runtime.Port | null = null; connect: chrome.runtime.Port | null = null;
constructor() { constructor() {
if (chrome && chrome.runtime) { if (chrome && chrome.runtime) {
this.connect = chrome.runtime.connect({name: PluginMsg.Page.Devtools}); this.connect = chrome.runtime.connect({name: Page.Devtools});
this.connect.onDisconnect.addListener(() => { this.connect.onDisconnect.addListener(() => {
console.log(`%c[Connect-Dis]`, 'color:red;') console.log(`%c[Connect-Dis]`, 'color:red;')
this.connect = null; this.connect = null;
@ -23,7 +22,7 @@ class ConnectBackground {
} }
} }
postMessage(data: PluginEvent) { postMessageToBackground(data: PluginEvent) {
if (this.connect) { if (this.connect) {
this.connect.postMessage(data) this.connect.postMessage(data)
} else { } else {

View File

@ -45,10 +45,10 @@
import Vue from "vue"; import Vue from "vue";
import {Component} from "vue-property-decorator"; import {Component} from "vue-property-decorator";
import properties from "./propertys.vue"; import properties from "./propertys.vue";
import {DataSupport, PluginEvent, NodeData} from "@/devtools/type"; import {DataSupport, NodeData} from "@/devtools/type";
import {PluginEvent, Page, Msg} from '@/core/types'
import {connectBackground} from "@/devtools/connectBackground"; import {connectBackground} from "@/devtools/connectBackground";
const PluginMsg = require("../core/plugin-msg");
@Component({ @Component({
components: { components: {
properties, properties,
@ -117,7 +117,7 @@ export default class Index extends Vue {
if (data.support) { if (data.support) {
// //
if (this.treeData.length === 0) { if (this.treeData.length === 0) {
this.onBtnClickUpdateTree(); // this.onBtnClickUpdateTree();
} }
} else { } else {
this._reset(); this._reset();
@ -131,39 +131,41 @@ export default class Index extends Vue {
_initChromeRuntimeConnect() { _initChromeRuntimeConnect() {
// background.js // background.js
connectBackground.onBackgroundMessage((data: any, sender: any) => { connectBackground.onBackgroundMessage((data: PluginEvent, sender: any) => {
if (!data) { if (!data) {
return; return;
} }
if (data.target === Page.Background) {
let eventData: any = data.data; let eventData: any = data.data;
console.log(data) console.log(data)
switch (data.msg) { switch (data.msg) {
case PluginMsg.Msg.UrlChange: { case Msg.UrlChange: {
break; break;
} }
case PluginMsg.Msg.TreeInfo: { case Msg.TreeInfo: {
this._onMsgListInfo(eventData as Array<NodeData>); this._onMsgListInfo(eventData as Array<NodeData>);
break; break;
} }
case PluginMsg.Msg.Support: { case Msg.Support: {
this._onMsgSupport(eventData as DataSupport) this._onMsgSupport(eventData as DataSupport)
break; break;
} }
case PluginMsg.Msg.NodeInfo: { case Msg.NodeInfo: {
this._onMsgNodeInfo(eventData); this._onMsgNodeInfo(eventData);
break; break;
} }
case PluginMsg.Msg.MemoryInfo: { case Msg.MemoryInfo: {
this._onMsgMemory(eventData) this._onMsgMemory(eventData)
break; break;
} }
case PluginMsg.Msg.TabsInfo: { case Msg.TabsInfo: {
debugger debugger
break break
}
} }
} }
}); });
} }
handleNodeClick(data: NodeData) { handleNodeClick(data: NodeData) {
@ -172,8 +174,7 @@ export default class Index extends Vue {
// console.log(data); // console.log(data);
let uuid = data.uuid; let uuid = data.uuid;
if (uuid !== undefined) { if (uuid !== undefined) {
PluginMsg.Msg.TabsInfo; this.runToContentScript(Msg.NodeInfo, uuid);
this.runToContentScript(PluginMsg.Msg.NodeInfo, uuid);
} }
} }
@ -188,14 +189,14 @@ export default class Index extends Vue {
} }
runToContentScript(msg: string, data?: any) { runToContentScript(msg: Msg, data?: any) {
if (!chrome || !chrome.devtools) { if (!chrome || !chrome.devtools) {
console.log("环境异常,无法执行函数"); console.log("环境异常,无法执行函数");
return; return;
} }
debugger debugger
let sendData = new PluginEvent(msg, data) let sendData = new PluginEvent(Page.Background, msg, data)
connectBackground.postMessage(sendData); connectBackground.postMessageToBackground(sendData);
} }
// DOM // DOM
@ -220,15 +221,15 @@ export default class Index extends Vue {
} }
onBtnClickUpdateTree() { onBtnClickUpdateTree() {
this.runToContentScript(PluginMsg.Msg.TreeInfo); this.runToContentScript(Msg.TreeInfo);
} }
onBtnClickUpdatePage() { onBtnClickUpdatePage() {
this.runToContentScript(PluginMsg.Msg.Support); this.runToContentScript(Msg.Support);
} }
onMemoryTest() { onMemoryTest() {
this.runToContentScript(PluginMsg.Msg.MemoryInfo); this.runToContentScript(Msg.MemoryInfo);
} }
onNodeExpand(data: NodeData) { onNodeExpand(data: NodeData) {

View File

@ -1,5 +1,4 @@
// eval 注入脚本的代码,变量尽量使用var,后来发现在import之后,let会自动变为var // eval 注入脚本的代码,变量尽量使用var,后来发现在import之后,let会自动变为var
import * as PluginMsg from '../core/plugin-msg'
import { import {
ArrayData, ArrayData,
BoolData, BoolData,
@ -13,7 +12,7 @@ import {
Vec3Data Vec3Data
} from "./data"; } from "./data";
import {PluginEvent} from './type' import {PluginEvent, Page, Msg} from '@/core/types'
class CCInspector { class CCInspector {
inspectorGameMemoryStorage: Record<string, any> = {} inspectorGameMemoryStorage: Record<string, any> = {}
@ -27,57 +26,64 @@ class CCInspector {
// } // }
}, 1000); }, 1000);
// 注册cc_after_render事件 // 注册cc_after_render事件
window.addEventListener("message", (event: any) => { window.addEventListener("message", (event) => {
// 接受来自background的事件,有可能也会受到其他插件的 // 接受来自content的事件,有可能也会受到其他插件的
if (!event || !event.data) { if (!event || !event.data) {
return return
} }
let pluginEvent: PluginEvent = event.data; let pluginEvent: PluginEvent = event.data;
switch (pluginEvent.msg) { if (pluginEvent.target === Page.Inject) {
case PluginMsg.Msg.UrlChange: switch (pluginEvent.msg) {
case PluginMsg.Msg.Support: { case Msg.UrlChange:
let isCocosGame = this._isCocosGame(); case Msg.Support: {
this.sendMsgToContent(PluginMsg.Msg.Support, {support: isCocosGame}); let isCocosGame = this._isCocosGame();
break; this.sendMsgToContent(Msg.Support, {support: isCocosGame});
} break;
case PluginMsg.Msg.TreeInfo: { }
case Msg.TreeInfo: {
debugger debugger
break; break;
} }
case PluginMsg.Msg.NodeInfo: { case Msg.NodeInfo: {
debugger debugger
break; break;
} }
case PluginMsg.Msg.SetProperty: { case Msg.SetProperty: {
debugger; debugger;
break; break;
}
} }
} }
}); });
} }
sendMsgToContent(msg: Msg, data: any) {
// 发送给content.js处理也会导致发送给了自身死循环
window.postMessage(new PluginEvent(Page.Inject, msg, data), "*");
}
devPageCallEntry(str: string) { devPageCallEntry(str: string) {
let para: PluginEvent = JSON.parse(str); let para: PluginEvent = JSON.parse(str);
debugger debugger
if (this._isCocosGame()) { if (this._isCocosGame()) {
switch (para.msg) { switch (para.msg) {
case PluginMsg.Msg.TreeInfo: case Msg.TreeInfo:
this.updateTreeInfo(); this.updateTreeInfo();
break; break;
case PluginMsg.Msg.Support: case Msg.Support:
break; break;
case PluginMsg.Msg.MemoryInfo: case Msg.MemoryInfo:
break; break;
case PluginMsg.Msg.SetProperty: case Msg.SetProperty:
break; break;
case PluginMsg.Msg.NodeInfo: case Msg.NodeInfo:
this.getNodeInfo(para.data as string); this.getNodeInfo(para.data as string);
break; break;
} }
} else { } else {
this.sendMsgToContent(PluginMsg.Msg.Support, {support: false}); this.sendMsgToContent(Msg.Support, {support: false});
} }
} }
@ -98,9 +104,9 @@ class CCInspector {
let node = sceneChildren[i]; let node = sceneChildren[i];
this.getNodeChildren(node, sendData.children); this.getNodeChildren(node, sendData.children);
} }
this.sendMsgToContent(PluginMsg.Msg.TreeInfo, sendData); this.sendMsgToContent(Msg.TreeInfo, sendData);
} else { } else {
this.sendMsgToContent(PluginMsg.Msg.Support, {support: false, msg: "未发现游戏场景,不支持调试游戏!"}); this.sendMsgToContent(Msg.Support, {support: false, msg: "未发现游戏场景,不支持调试游戏!"});
} }
} }
} }
@ -276,7 +282,7 @@ class CCInspector {
let compGroup = this._getGroupData(itemComp); let compGroup = this._getGroupData(itemComp);
groupData.push(compGroup); groupData.push(compGroup);
} }
this.sendMsgToContent(PluginMsg.Msg.NodeInfo, groupData); this.sendMsgToContent(Msg.NodeInfo, groupData);
} else { } else {
// 未获取到节点数据 // 未获取到节点数据
console.log("未获取到节点数据"); console.log("未获取到节点数据");
@ -297,13 +303,9 @@ class CCInspector {
} }
} }
sendMsgToContent(msg: string, data: any) {
// 发送给content.js处理
window.postMessage(new PluginEvent(msg, data), "*");
}
onMemoryInfo() { onMemoryInfo() {
this.sendMsgToContent(PluginMsg.Msg.MemoryInfo, { this.sendMsgToContent(Msg.MemoryInfo, {
performance: { performance: {
// @ts-ignore // @ts-ignore
jsHeapSizeLimit: window.performance.memory.jsHeapSizeLimit, jsHeapSizeLimit: window.performance.memory.jsHeapSizeLimit,

View File

@ -1,6 +1,4 @@
import * as PluginMsg from '../core/plugin-msg'
import Manifest from '../manifest.json' import Manifest from '../manifest.json'
import {PluginEvent} from "@/devtools/type";
import {connectBackground} from "@/devtools/connectBackground"; import {connectBackground} from "@/devtools/connectBackground";
export function init() { export function init() {

View File

@ -10,12 +10,4 @@ export class DataSupport {
} }
export class PluginEvent {
msg: string = '';
data: any = null;
constructor(msg: string, data?: any) {
this.msg = msg;
this.data = data || null;
}
}