请参阅使用相同的JavaScript在网页和iframe中运行的技术described in this answer:
例如,假设您在domain_A.com上有此页面:
<html>
<body>
<iframe src="http://domain_B.com/SomePage.htm"></iframe>
</body>
</html>
如果你设置这样的@match指令:
// @match http://domain_A.com/*
// @match http://domain_B.com/*
然后你的脚本将运行两次 - 一次在主页上,一次在iframe上,就好像它是一个独立的页面。
让脚本的两个实例相互通信有哪些选择?
这将需要同步实例。例如,让iframe脚本实例仅在网页脚本实例完成后执行其任务,反之亦然。
答案 0 :(得分:4)
这两个脚本实例可以使用postMessage()
相互通信。关于:
这将需要同步实例,因此例如让iframe只在网页完成后执行其任务,反之亦然。
这就是this other answer中显示的内容
但是 Chrome has bugs in how it presents frames/iframes to extensions
因此,要解决这些错误,您必须注入调用postMessage()
的代码。
以下脚本显示了如何操作。它:
安装此脚本(感谢CertainPerformance更新了多年来目标网站的更改):
// ==UserScript==
// @name _Cross iframe, cross-domain, interscript communication
// @include http://fiddle.jshell.net/2nmfk5qs/*
// @include http://puppylinux.com/
// @grant none
// ==/UserScript==
/* eslint-disable no-multi-spaces */
if (window.top === window.self) return;
console.log ("Script start...");
if (window.location.href.includes('fiddle')) {
console.log ("Userscript is in the MAIN page.");
//--- Setup to process messages from the GM instance running on the iFrame:
window.addEventListener ("message", receiveMessageFromFrame, false);
console.log ("Waiting for Message 1, from iframe...");
}
else {
console.log ("Userscript is in the FRAMED page.");
//--- Double-check that this iframe is on the expected domain:
if (/puppylinux\.com/i.test (location.host) ) {
window.addEventListener ("message", receiveMessageFromContainer, false);
//--- Send the first message to the containing page.
sendMessageFromAnIframe (
"***Message 1, from iframe***", "http://fiddle.jshell.net"
);
console.log ("Waiting for Message 2, from containing page...");
}
}
function receiveMessageFromFrame (event) {
if (event.origin != "http://puppylinux.com") return;
console.log ('The container page received the message, "' + event.data + '".');
//--- Send message 2, back to the iframe.
sendMessageToAnIframe (
"#testIframe",
"***Message 2, from the container page***",
"http://puppylinux.com"
);
}
function receiveMessageFromContainer (event) {
if (event.origin != "http://fiddle.jshell.net") return;
console.log ('The iframe received the message, "' + event.data + '".');
}
/*--- Because of bugs in how Chrome presents frames to extensions, we must inject
the messaging code. See bug 20773 and others.
frames, top, self.parent, contentWindow, etc. are all improperly undefined
when we need them. See Firefox and other browsers for the correct behavior.
*/
function sendMessageFromAnIframe (message, targetDomain) {
var scriptNode = document.createElement ('script');
scriptNode.textContent = 'parent.postMessage ("' + message
+ '", "' + targetDomain + '");'
;
document.body.appendChild (scriptNode);
}
function sendMessageToAnIframe (cssSelector, message, targetDomain) {
function findIframeAndMessageIt (cssSelector, message, targetDomain) {
var targetIframe = document.querySelector (cssSelector)
if (targetIframe) {
targetIframe.contentWindow.postMessage (message, targetDomain);
}
}
var scriptNode = document.createElement ('script');
scriptNode.textContent = findIframeAndMessageIt.toString ()
+ 'findIframeAndMessageIt ("' + cssSelector
+ '", "' + message
+ '", "' + targetDomain + '");'
;
document.body.appendChild (scriptNode);
}
console.log ("Script end");
然后访问this test page at jsFiddle。
您将在javascript控制台中看到这一点:
Script start... Userscript is in the MAIN page. Waiting for Message 1, from iframe... Script end Script start... Userscript is in the FRAMED page. Waiting for Message 2, from containing page... Script end The container page received the message, "***Message 1, from iframe***". The iframe received the message, "***Message 2, from the container page***".