一个userscript的两个实例如何在帧之间通信? [英] How can two instances of a userscript communicate between frames?

查看:302
本文介绍了一个userscript的两个实例如何在帧之间通信?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请参阅使用相同的JavaScript在网页和iframe中运行的技术,如

Refer to the technique of having the same JavaScript to run in both a web page and an iframe, as described in this answer:


对于在此回答中描述的尝试访问框架?answerertab = active#tab-top>例如,假设您在domain_A.com上有此网页:

For example, suppose you have this page at domain_A.com:



<html>
<body>
    <iframe src="http://domain_B.com/SomePage.htm"></iframe>
</body>
</html>




如果你像这样设置@match指令:

If you set your @match directives like this:



// @match http://domain_A.com/*
// @match http://domain_B.com/*




- 一次在主页上,一次在iframe上,就像是一个独立的页面。

Then your script will run twice -- once on the main page and once on the iframe as though it were a standalone page.



使脚本的两个实例彼此通信的选项是什么?


What are the options to have the two instances of the script to communicate with each other?

这将需要同步实例。例如,使iframe脚本实例仅在网页脚本实例完成后执行其任务,反之亦然。

This would be needed to sync the instances. For example, have the iframe script-instance execute its task only after the webpage script-instance completed, and vice versa.

推荐答案

这两个脚本实例可以使用 postMessage() 。关于:

The two script instances can communicate with each other using postMessage(). Regarding:


这将需要同步实例,例如,让iframe只在网页之后执行其任务完成,反之亦然。

This would be needed to sync the instances, so for example to have the iframe one to execute its task only after the webpage one completed, and vice versa.

这正是这个,惊人的辉煌,回答。 ;)

Chrome在将框架/ iframe扩展到扩展程序时遇到了bug (而Chrome用户脚本是带有自动生成的清单的扩展程序)。

因此,要解决这些错误,您必须注入调用 postMessage()的代码。

That's exactly what is shown in this, stunningly brilliant, answer. ;)
But Chrome has bugs in how it presents frames/iframes to extensions (And Chrome userscripts are extensions with an auto-generated manifest).
So, to work around these bugs, you must inject the code that calls postMessage().


  • 在iframe和包含页面中运行。

  • 处理跨网域iframe。

  • 它演示了具有以下逻辑的脚本控制:
  • Runs in both an iframe and the containing page.
  • Handles cross domain iframes.
  • It demonstrates inter-script control having the following logic:

  1. 容器页面设置为侦听来自iframe的消息。 / li>
  2. iframe设置为侦听来自容器页面的邮件。

  3. iframe将第一条邮件发送到容器页面。

  4. 当容器页面收到该邮件时,会向iframe发送另一个邮件。


安装此脚本:

// ==UserScript==
// @name        _Cross iframe, cross-domain, interscript communication
// @include     http://fiddle.jshell.net/9aQv5/*
// @include     http://www.puppylinux.com/
// ==/UserScript==

console.log ("Script start...");

if (window.top === window.self) {
    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://www.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://www.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  = 'top.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");



然后访问此测试页在jsFiddle


Then visit this test page at jsFiddle.

在javascript控制台中:

You will see this in the javascript console:


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***".

这篇关于一个userscript的两个实例如何在帧之间通信?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆