[REF] devtools: Better messages forwarding

This commit improves how messages are relayed from the page to the
devtools by using a specific port for each instance of the owl devtools
panel and refreshing it through the heartbeat message. This allows
to prevent sending messages to every devtools instances and sorting
the messages inside.
This commit is contained in:
Julien Carion (juca)
2023-04-14 16:19:24 +02:00
committed by Géry Debongnie
parent c049022798
commit 606d14a399
4 changed files with 102 additions and 105 deletions
+29 -11
View File
@@ -5,7 +5,7 @@ let owlStatus = 0;
const browserInstance = IS_FIREFOX ? browser : chrome;
// Used to keep track of the tabs where the owl devtools have been opened
const activePanels = new Set();
const activePanels = new Map();
// Load the devtools global hook this way when running on manifest v3 chrome
if (!IS_FIREFOX) {
@@ -75,8 +75,23 @@ browserInstance.runtime.onMessage.addListener(async (message, sender, sendRespon
return true;
} else if (message.type === "owlStatus") {
setOwlStatus(message.data);
// Dummy message to test if the extension context is still valid
// Refresh panel connection timeout
} else if (message.type === "keepAlive") {
const panel = activePanels.get(message.id);
if (panel) {
clearTimeout(panel.expirationTimeout);
panel.expirationTimeout = setTimeout(() => {
activePanels.delete(message.id);
panel.port.disconnect();
}, 750);
} else {
const port = browserInstance.runtime.connect({ name: "OwlDevtoolsPort_" + message.id });
const expirationTimeout = setTimeout(() => {
activePanels.delete(message.id);
port.disconnect();
}, 750);
activePanels.set(message.id, { port: port, expirationTimeout: expirationTimeout });
}
return;
// Open the devtools documentation in a new tab
} else if (message.type === "openDoc") {
@@ -87,10 +102,15 @@ browserInstance.runtime.onMessage.addListener(async (message, sender, sendRespon
}
);
return;
// Relay the received message to the devtools app
// Register a new port for the devtools panel
} else if (message.type === "newDevtoolsPanel") {
const tab = await getActiveTabURL();
activePanels.add(tab);
const id = message.id;
const port = browserInstance.runtime.connect({ name: "OwlDevtoolsPort_" + id });
const expirationTimeout = setTimeout(() => {
activePanels.delete(id);
port.disconnect();
}, 750);
activePanels.set(message.id, { port: port, expirationTimeout: expirationTimeout });
// This is solely for firefox which doesnt allow access to the chrome.tabs api inside devtools
} else if (message.type === "getActiveTabURL") {
getActiveTabURL().then((tab) => {
@@ -98,15 +118,13 @@ browserInstance.runtime.onMessage.addListener(async (message, sender, sendRespon
});
return true;
} else {
const tab = await getActiveTabURL();
if (!activePanels.has(tab)) {
return;
}
const port = browserInstance.runtime.connect({ name: "OwlDevtoolsPort" });
port.postMessage(
const destinationPanel = activePanels.get(sender.tab.id);
if (destinationPanel) {
destinationPanel.port.postMessage(
message.data
? { type: message.type, data: message.data, origin: message.origin }
: { type: message.type, origin: message.origin }
);
}
}
});
@@ -27,7 +27,6 @@ function createPanelsIfOwl() {
"../../assets/icon128.png",
IS_FIREFOX ? "devtools_panel.html" : "devtools_app/devtools_panel.html"
);
browserInstance.runtime.sendMessage({ type: "newDevtoolsPanel" });
}
);
}
+7 -21
View File
@@ -652,33 +652,28 @@ async function init() {
}
loadSettings();
}
browserInstance.runtime.sendMessage({ type: "newDevtoolsPanel", id: store.devtoolsId });
// Heartbeat message to test whether the extension context is still valid or not
setInterval(() => {
if (store.extensionContextStatus) {
try {
browserInstance.runtime.sendMessage({ type: "keepAlive" });
browserInstance.runtime.sendMessage({ type: "keepAlive", id: store.devtoolsId });
} catch (e) {
store.extensionContextStatus = false;
}
}
}, 1000);
}, 500);
}
let flushRendersTimeout = false;
// Connect to the port to communicate to the background script
browserInstance.runtime.onConnect.addListener((port) => {
if (!port.name === "OwlDevtoolsPort") {
return;
}
if (port.name === "OwlDevtoolsPort_" + store.devtoolsId) {
port.onMessage.addListener(async (msg) => {
// Reload the tree after checking if the scripts are loaded when this message is received
if (msg.type === "Reload") {
const tab = await getTabURL();
// Since this message is sent to all devtools windows, only take it into account when this is the active tab
if (tab !== store.devtoolsId) {
return;
}
store.owlStatus = await evalInWindow("window.__OWL__DEVTOOLS_GLOBAL_HOOK__ !== undefined;");
if (store.owlStatus) {
evalInWindow("__OWL__DEVTOOLS_GLOBAL_HOOK__.devtoolsId = " + store.devtoolsId + ";");
@@ -687,11 +682,6 @@ browserInstance.runtime.onConnect.addListener((port) => {
}
// Received when a frame has been delayed when loading the scripts due to owl being lazy loaded
if (msg.type === "FrameReady") {
const tab = await getTabURL();
// Same as for the reload message
if (tab !== store.devtoolsId) {
return;
}
store.updateIFrameList();
store.owlStatus = true;
store.resetData();
@@ -700,11 +690,6 @@ browserInstance.runtime.onConnect.addListener((port) => {
if (msg.type === "RefreshApps") {
store.loadComponentsTree(true);
}
// Filter out the messages that are not destined to this devtools tab. The messages above may be sent before
// the devtoolsId is set
if (msg.origin.id !== store.devtoolsId) {
return;
}
// When message of type Flush is received, overwrite the component tree with the new one from page
// A flush message is sent everytime a component is rendered on the page
if (msg.type === "Flush") {
@@ -749,6 +734,7 @@ browserInstance.runtime.onConnect.addListener((port) => {
}
}
});
}
});
// Load all settings from the chrome sync storage
@@ -17,8 +17,6 @@
this.addedElements = [];
// To keep track of the succession order of the render events
this.eventId = 0;
// Will be reset as soon as a new devtools owl tab is opened. Allows to avoid sending messages to the wrong devtools tab later on
this.devtoolsId = 0;
// Set to keep track of the frame on which this script is loaded
this.frame = "top";
// Allows to launch a message each time an iframe html element is added to the page
@@ -38,7 +36,6 @@
source: "owl-devtools",
type: "NewIFrame",
data: addedNode.contentDocument.location.href,
origin: { id: self.devtoolsId },
});
}
}
@@ -263,7 +260,7 @@
source: "owl-devtools",
type: "Flush",
data: path,
origin: { id: self.devtoolsId, frame: self.frame },
origin: { frame: self.frame },
});
}
});
@@ -372,7 +369,6 @@
source: "owl-devtools",
type: "Event",
data: self.eventsBatch,
origin: { id: self.devtoolsId },
});
self.eventsBatch = [];
}
@@ -628,7 +624,6 @@
source: "owl-devtools",
type: "SelectElement",
data: path,
origin: { id: this.devtoolsId },
});
}
};
@@ -656,7 +651,6 @@
window.top.postMessage({
source: "owl-devtools",
type: "StopSelector",
origin: { id: this.devtoolsId },
});
};
@@ -1767,6 +1761,6 @@
false
);
checkOwlStatus();
// Indicates whether the scripts loaded successfully or not (useful when loaded with eval in iframes only)
// Indicates whether the scripts loaded successfully or not (only useful when loaded with eval in iframes)
return window.__OWL__DEVTOOLS_GLOBAL_HOOK__ !== undefined;
})();