将消息的请求和响应分离,便于维护

This commit is contained in:
xu_yanfeng
2024-12-27 19:20:22 +08:00
parent f7937a5c8b
commit 3e9d259b2c
16 changed files with 214 additions and 142 deletions

View File

@@ -1,5 +1,5 @@
import { ChromeConst } from "cc-plugin/src/chrome/const";
import { Msg, Page, PluginEvent } from "../../core/types";
import { Msg, Page, PluginEvent, RequestSupportData } from "../../core/types";
import { Terminal } from "../terminal";
import { PortMan } from "./portMan";
import { portMgr } from "./portMgr";
@@ -15,12 +15,7 @@ function onTabConnect(tab: chrome.tabs.Tab, port: chrome.runtime.Port) {
debugger;
return;
}
let portMan = portMgr.findPort(tab.id);
if (portMan) {
// 一个port发起多次发起链接以最后一次的为数据通讯基准
// portMgr.removePort(portMan);
}
portMan = portMgr.addPort(tab, port);
const portMan = portMgr.addPort(tab, port);
portMan.init();
}
chrome.runtime.onConnect.addListener((port: chrome.runtime.Port) => {
@@ -60,7 +55,7 @@ chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
if (id && id > -1) {
let portMan = portMgr.findPort(id);
if (portMan) {
let data = new PluginEvent(Page.Background, Page.Content, Msg.Support);
const data = new PluginEvent(Page.Background, Page.Content, Msg.RequestSupport, {} as RequestSupportData);
portMgr.sendContentMsg(data);
}
}

View File

@@ -1,11 +1,28 @@
import { PluginEvent } from "../../core/types";
import { FrameDetails } from "../../views/devtools/data";
import { PortMan } from "./portMan";
import { portMgr } from "./portMgr";
export class PortContent extends PortMan {
protected frameID: number = 0;
constructor(tab: chrome.tabs.Tab, port: chrome.runtime.Port) {
super(tab, port);
this.frameID = port.sender.frameId || 0;
}
getFrameDetais(): FrameDetails {
return {
url: this.url,
frameID: this.frameID,
};
}
init(): void {
// content连上来要同时devtools更新
portMgr._updateFrames();
// 使用新连上来的content
const { frameId } = this.port.sender;
if (frameId !== undefined) {
portMgr.useFrame(frameId);
}
// 新的content连上来需要更新devtools
portMgr.updateFrames();
this.onDisconnect = (disPort: chrome.runtime.Port) => {
/**
* const index = this.content.findIndex((el) =>
@@ -16,7 +33,7 @@ export class PortContent extends PortMan {
*/
// content失去链接需要更新Devtools
portMgr.removePort(this);
portMgr._updateFrames();
portMgr.updateFrames();
};
this.onMessage = (data: PluginEvent) => {
// content的数据一般都是要同步到devtools

View File

@@ -1,32 +1,36 @@
import { Msg, Page, PluginEvent } from "../../core/types";
import { Msg, Page, PluginEvent, RequestTreeInfoData, RequestUseFrameData } from "../../core/types";
import { PortMan } from "./portMan";
import { portMgr } from "./portMgr";
export class PortDevtools extends PortMan {
init(): void {
// 当devtools链接后主动同步frames数据
portMgr._updateFrames();
portMgr.updateFrames();
this.onDisconnect = () => {
portMgr.removePort(this);
};
this.onMessage = (data: PluginEvent) => {
if (data.msg === Msg.UseFrame) {
portMgr.useFrame(data.data);
if (data.msg === Msg.RequestUseFrame) {
portMgr.useFrame((data.data as RequestUseFrameData).id);
} else {
// 从devtools过来的消息统一派发到Content中
if (data.check(Page.Devtools, Page.Background)) {
if (data.msg === Msg.TreeInfo) {
if (portMgr.isCurrentFrme(data.data)) {
if (data.msg === Msg.RequstTreeInfo) {
const d = data.data as RequestTreeInfoData;
if (!portMgr.isCurrentFrme(d.frameID)) {
console.log(`frameID[${data.data}]不一致`);
debugger;
}
}
data.reset(Page.Background, Page.Content);
const port = portMgr.getCurrentUseContent();
const port = portMgr.getCurrentUsePort();
if (!port) {
console.warn(`not find andy port`);
return;
}
port.postMessage(data);
port.send(data);
} else {
debugger;
}
}
};

View File

@@ -12,7 +12,7 @@ export abstract class PortMan {
public id: number | null = null;
public title: string = "";
public url: string = "";
public port: chrome.runtime.Port | null = null;
protected port: chrome.runtime.Port | null = null;
public tab: chrome.tabs.Tab | null = null;
public onDisconnect: (port: chrome.runtime.Port) => void | null = null;
public onMessage: (data: PluginEvent) => void | null = null;
@@ -24,14 +24,12 @@ export abstract class PortMan {
this.tab = tab;
this.name = port.name;
this.id = tab.id;
this.url = tab.url;
this.url = port.sender.url;
this.title = tab.title;
this.terminal = new Terminal(`Port-${this.name}`);
port.onMessage.addListener((data: any, port: chrome.runtime.Port) => {
const event = PluginEvent.create(data);
console.log(...this.terminal.chunkMessage(event.toChunk()));
// 如果多个页面都监听 onMessage 事件,对于某一次事件只有第一次调用 sendResponse() 能成功发出回应,所有其他回应将被忽略。
// port.postMessage(data);
if (event.valid && this.onMessage) {
this.onMessage(event);
} else {
@@ -47,10 +45,27 @@ export abstract class PortMan {
}
abstract init(): void;
isConnectPort() {
isContent() {
return this.name === Page.Content;
}
isDevtoolsPort() {
isDevtools() {
return this.name === Page.Devtools;
}
isUseing(id: number) {
if (!this.port) {
return false;
}
if (!this.port.sender) {
return false;
}
if (this.port.sender.frameId === undefined) {
return false;
}
return this.port.sender.frameId === id;
}
send(data: PluginEvent) {
if (this.port) {
this.port.postMessage(data);
}
}
}

View File

@@ -1,5 +1,5 @@
import { FrameDetails } from "views/devtools/data";
import { Msg, Page, PluginEvent } from "../../core/types";
import { Msg, Page, PluginEvent, RequestSupportData, ResponseUpdateFramesData } from "../../core/types";
import { FrameDetails } from "../../views/devtools/data";
import { Terminal } from "../terminal";
import { PortContent } from "./portContent";
import { PortDevtools } from "./portDevtools";
@@ -22,18 +22,19 @@ export class PortMgr {
public findPort(id: number): PortMan | null {
return this.portArray.find((el) => el.id === id) || null;
}
public _updateFrames() {
/**
* 通知devtools更新
*/
public updateFrames() {
// 将content类型的port收集起来同步到devtools
const data: FrameDetails[] = [];
this.portArray.forEach((item) => {
if (item.isConnectPort()) {
data.push({
url: item.port.sender?.url || "",
frameID: item.port.sender?.frameId || 0,
});
if (item.isContent()) {
const frame = (item as PortContent).getFrameDetais();
data.push(frame);
}
});
const event = new PluginEvent(Page.Background, Page.Devtools, Msg.UpdateFrames, data);
const event = new PluginEvent(Page.Background, Page.Devtools, Msg.ResponseUpdateFrames, data as ResponseUpdateFramesData);
this.sendDevtoolMsg(event);
}
@@ -89,38 +90,34 @@ export class PortMgr {
}
sendContentMsg(data: PluginEvent) {
this.getCurrentUseContent()?.postMessage(data);
this.getCurrentUsePort()?.send(data);
}
sendDevtoolMsg(data: PluginEvent) {
const portManArray = this.portArray.filter((el) => el.isDevtoolsPort());
const portManArray = this.portArray.filter((el) => el.isDevtools());
if (portManArray.length) {
portManArray.forEach((portMan) => {
portMan.port.postMessage(data);
portMan.send(data);
});
} else {
console.log("not find devtools port");
}
}
getCurrentUseContent(): chrome.runtime.Port | null {
getCurrentUsePort(): PortMan | null {
const portMan = this.portArray.find((portMan: PortMan) => {
const el = portMan.port;
const b1 = el.sender?.frameId !== undefined;
const b2 = el.sender.frameId === this.currentUseContentFrameID;
return b1 && b2;
return portMan.isContent() && portMan.isUseing(this.currentUseContentFrameID);
});
if (portMan) {
return portMan.port;
} else {
return null;
}
return portMan || null;
}
useFrame(id: number) {
this.currentUseContentFrameID = id;
// 更新这个frame的tree
const sendData = new PluginEvent(Page.Background, Page.Content, Msg.Support);
this.getCurrentUseContent()?.postMessage(sendData);
const sendData = new PluginEvent(Page.Background, Page.Content, Msg.RequestSupport, {} as RequestSupportData);
this.getCurrentUsePort()?.send(sendData);
}
isCurrentFrme(id: number) {
if (typeof id !== "number") {
throw new Error("id must be number");
}
return this.currentUseContentFrameID === id;
}
}

View File

@@ -1,7 +1,7 @@
// content.js 和原始界面共享DOM具有操作dom的能力
// 但是不共享js,要想访问页面js,只能通过注入的方式
import { ChromeConst } from "cc-plugin/src/chrome/const";
import { Msg, Page, PluginEvent } from "../../core/types";
import { Msg, Page, PluginEvent, ResponseSupportData } from "../../core/types";
import { DocumentEvent } from "../const";
import { Terminal } from "../terminal";
@@ -63,10 +63,10 @@ connect.onMessage.addListener((data: PluginEvent, sender: chrome.runtime.Port) =
function checkGame() {
let gameCanvas = document.querySelector("#GameCanvas");
const sendData = new PluginEvent(Page.Content, Page.Devtools, Msg.Support, {
const sendData = new PluginEvent(Page.Content, Page.Devtools, Msg.ResponseSupport, {
support: !!gameCanvas,
msg: "未发现GameCanvas,不支持调试游戏!",
});
} as ResponseSupportData);
if (connect) {
connect.postMessage(sendData);
} else {
@@ -76,4 +76,4 @@ function checkGame() {
}
injectScript(ChromeConst.script.inject);
checkGame();
// checkGame();

View File

@@ -1,6 +1,6 @@
// eval 注入脚本的代码,变量尽量使用var,后来发现在import之后,let会自动变为var
import { uniq } from "lodash";
import { Msg, PluginEvent } from "../../core/types";
import { Msg, PluginEvent, RequestNodeInfoData, RequestLogData, RequestObjectData, RequestSetPropertyData, ResponseNodeInfoData, ResponseObjectData, ResponseSetPropertyData, ResponseSupportData, ResponseTreeInfoData } from "../../core/types";
import { ArrayData, BoolData, ColorData, DataType, EngineData, Group, ImageData, Info, InvalidData, NodeInfoData, NumberData, ObjectData, ObjectItemRequestData, Property, StringData, TreeData, Vec2Data, Vec3Data } from "../../views/devtools/data";
import { InjectEvent } from "./event";
import { getValue, trySetValueWithConfig } from "./setValue";
@@ -25,22 +25,22 @@ export class Inspector extends InjectEvent {
}
onMessage(pluginEvent: PluginEvent): void {
switch (pluginEvent.msg) {
case Msg.Support: {
let isCocosGame = this._isCocosGame();
case Msg.RequestSupport: {
const isCocosGame = this._isCocosGame();
this.notifySupportGame(isCocosGame);
break;
}
case Msg.TreeInfo: {
case Msg.RequstTreeInfo: {
this.updateTreeInfo();
break;
}
case Msg.NodeInfo: {
let nodeUUID = pluginEvent.data;
this.getNodeInfo(nodeUUID);
case Msg.RequestNodeInfo: {
const data = pluginEvent.data as RequestNodeInfoData;
this.getNodeInfo(data.uuid);
break;
}
case Msg.SetProperty: {
const data: Info = pluginEvent.data;
case Msg.RequestSetProperty: {
const data: RequestSetPropertyData = pluginEvent.data;
let value = data.data;
if (data.type === DataType.Color) {
// @ts-ignore
@@ -48,22 +48,22 @@ export class Inspector extends InjectEvent {
}
if (this.setValue(data.path, value)) {
this.sendMsgToContent(Msg.UpdateProperty, data);
this.sendMsgToContent(Msg.ResponseSetProperty, data as ResponseSetPropertyData);
} else {
console.warn(`设置失败:${data.path}`);
}
break;
}
case Msg.LogData: {
const data: string[] = pluginEvent.data;
case Msg.RequestLogData: {
const data: RequestLogData = pluginEvent.data;
const value = getValue(this.inspectorGameMemoryStorage, data);
// 直接写console.log会被tree shaking
const logFunction = console.log;
logFunction(value);
break;
}
case Msg.GetObjectItemData: {
const data: ObjectData = pluginEvent.data;
case Msg.RequestObjectItemData: {
const data: RequestObjectData = pluginEvent.data;
let val = getValue(this.inspectorGameMemoryStorage, data.path);
if (val) {
let itemData: Property[] = this._buildObjectItemData({
@@ -76,7 +76,7 @@ export class Inspector extends InjectEvent {
id: data.id,
data: itemData,
};
this.sendMsgToContent(Msg.GetObjectItemData, result);
this.sendMsgToContent(Msg.ResponseObjectItemData, result as ResponseObjectData);
}
break;
}
@@ -88,7 +88,7 @@ export class Inspector extends InjectEvent {
}
notifySupportGame(b: boolean) {
this.sendMsgToContent(Msg.Support, b);
this.sendMsgToContent(Msg.ResponseSupport, { support: b, msg: "" } as ResponseSupportData);
}
updateTreeInfo() {
@@ -99,7 +99,7 @@ export class Inspector extends InjectEvent {
if (scene) {
let treeData = new TreeData();
this.getNodeChildren(scene, treeData);
this.sendMsgToContent(Msg.TreeInfo, treeData);
this.sendMsgToContent(Msg.ResponseTreeInfo, treeData as ResponseTreeInfoData);
} else {
console.warn("can't execute api : cc.director.getScene");
this.notifySupportGame(false);
@@ -588,7 +588,7 @@ export class Inspector extends InjectEvent {
groupData.push(compGroup);
}
const data: NodeInfoData = new NodeInfoData(uuid, groupData);
this.sendMsgToContent(Msg.NodeInfo, data);
this.sendMsgToContent(Msg.ResponseNodeInfo, data as ResponseNodeInfoData);
} else {
// 未获取到节点数据
console.log("未获取到节点数据");