Chrome 扩展帖子消息和侦听器



我正在从我的扩展向网站DOM中注入一个脚本。脚本访问DOM对象&使用postMessage((返回。然后我在content.js&获取对象。有一个函数将这些脚本注入DOM&期望对象返回。此函数被调用5次&期望5个不同的对象。第一个调用成功执行&返回addListener中的object1。但在此之后,监听器等待执行所有4个脚本&将对象保存在postMessage中。一旦加载了整个扩展,那么最后会调用addEventListener&则返回所有剩余的4个对象。

为什么会有这种行为?如何从postMessage中获取对象在addListener中而不被持有?

function temp(){
var globalObject = `var globalObject = domObj; `;
var scriptHtml = [
globalObject,
`var obj = JSON.parse(JSON.stringify(globalObject));`,
`console.log("Obj in DOM",obj);`,
`window.postMessage(obj)`,
].join("");
s.innerHTML = scriptHtml;
document.body.appendChild(s);
var obj = {};
window.addEventListener(
"message",
function (event) {
// We only accept messages from ourselves
if (event.source != window) return;
if (event.data) {
obj = event.data;
// console.log("Obj in Content.js ", obj);
// port.postMessage(event.data);
}
},
false
);
return obj;
}

";content.js";脚本从";background.js";

background.js

chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
console.log(tabId, changeInfo, tab);
if (changeInfo.status == 'complete') {
Utils.executeScriptUsingTabId(tabId, 'content.js').catch(err => {
console.log(err);
});
}
});

manifest.json

{
"manifest_version": 2,
"name": "My Ext",
"description": "My Extension",
"version": "5.0",
"icons": {
"128": "images/icon.png"
},
"externally_connectable": {
"matches": ["*://*.example.com/*", "*://localhost/*"]
},
"permissions": [
"<all_urls>",
"webRequest",
"webRequestBlocking",
"tabs",
"http://*/*",
"https://*/*"
],
"background": {
"page": "background.html"
},
"browser_action": {
"default_title": "My Extension",
"default_icon": "images/icon.png",
"default_popup": "popup.html"
},
"web_accessible_resources": ["images/*.png", "helpers/*.js"]
}

content.js

console.time("start");
import getPageVar from "./contentScripts/getPageVar";
import getPageVarFunc from "./contentScripts/getPageVarFunc";
import getAdsDotTxt from "./contentScripts/adsDotTxtResponse";
import $ from "jquery";
import Utils from "./libs/utils.js";
let adsDotTxtResponse = false;
if (!adsDotTxtResponse) {
console.log("No data");
getAdsDotTxt();
adsDotTxtResponse = true;
}
chrome.runtime.onMessage.addListener(function (
{ command, data },
sender,
sendResponse
) {
try {
switch (command) {
case "getPageVar":
sendResponse({ success: true, data: getPageVar(data.pageVar) });
break;
case "getPageVarFunc":
sendResponse({ success: true, data: getPageVarFunc(data.pageVar) });
break;
case "setPrebidHandlers":
console.log("Case SetPrebidHandlers");
console.log(prebidEventHandlersSet);
if (!prebidEventHandlersSet) {
setPrebidHandlers();
prebidEventHandlersSet = true;
}
sendResponse({ success: true, data: "Script executed" });
break;
case "getAdsDotTxt":
console.log("send ads.txt response");
if (!adsDotTxtResponse) {
console.log("No data");
getAdsDotTxt();
adsDotTxtResponse = true;
sendResponse({ success: true, data: "Fetching ads.txt data" });
} else {
console.log("Sending Data");
sendResponse({
success: true,
data: getPageVarFunc(
'document.getElementById("_My_adsDotTxt").innerText'
),
});
}
break;
case "scrollAdToScreen":
const status = Utils.scrollElementToScreen($(`div[id='${data.id}']`));
sendResponse({ success: status, data: { status } });
break;
case "highlightAds":
Utils.borderifyAd(data.isMy);
sendResponse({ success: true, data: { status: true } });
break;
case "adUnitReporting":
Utils.getAdUnitReporting(data.isMy, data.toDate, data.fromDate);
sendResponse({ success: true, data: { status: true } });
break;
case "appendAndReloadUrl":
Utils.appendAndReloadURL(data.param);
sendResponse({ success: true, data: { status: true } });
break;
}
} catch (e) {}
return true;
});

有趣。看起来chrome.tabs.onUpdated中的status: 'complete'被报告了好几次,所以每次都会注入内容脚本并注册一个新的onMessage侦听器。

尝试通过发送一条特殊消息(如ping(来检查内容脚本是否已经在运行,onMessage应该返回true,例如:

background.js:

chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
if (changeInfo.status === 'complete') {
chrome.tabs.sendMessage(tabId, 'ping', {frameId: 0}, ok => {
if (chrome.runtime.lastError || !ok) {
Utils.executeScriptUsingTabId(tabId, 'content.js').catch(console.log);
}
});
}
});

content.js:

chrome.runtime.onMessage.addListener(function (
{ command, data },
sender,
sendResponse
) {
try {
switch (command) {
case "ping":
sendResponse(true);
break;
//////////////////////

最新更新