如何从用户脚本访问iframe的javascript?

时间:2012-07-24 20:11:40

标签: javascript google-chrome iframe greasemonkey tampermonkey

我正在尝试使用Chrome用户脚本或Tampermonkey脚本修改具有此结构的网页:

<body>
content up here

<iframe id="main" src="foo.dat"></iframe>
</body>

iframe是同源的。

我需要访问iframe#main中的函数。我想到我可以使用unsafeWindow来获取它,但我一直没有得到任何内容或undefined返回。

我尝试了很多东西:

  • 尝试在iframe中创建新的脚本元素,但即使使用$('frame#main').contents().append(script)$('frame#main').contents()[0].createElement('script')

  • ,它也会附加到父级
  • window.frames["#main"].contentWindow返回undefined。

我已经尝试了许多其他我不记得的事情,但是我已经用尽了所有的想法,觉得我输的垃圾比任何重要的东西都要多。 我无法弄清楚如何使用iFrame的unsafeWindow

1 个答案:

答案 0 :(得分:10)

  1. unsafeWindow与Chrome,Tampermonkey或Firefox上的框架/ iframe不相称。
  2. 尝试使用jQuery访问全局(到框架)JS,就像那样,不起作用。
  3. 用户脚本将在符合@include@exclude和/或@match要求的iframe上投放。
  4. 因此,您需要考虑多个脚本运行,然后您有两种基本方法,具体取决于您要完成的任务。你可以:

    (A)将脚本定制到特定的框架,如this answer

    或(B)注入你的JS并使用特殊的frames对象来获取你想要的特定功能。

    以下脚本演示了两者。将其安装在Tampermonkey 1 (或Firefox Greasemonkey)中,然后访问this test page at jsBin

    // ==UserScript==
    // @name        _Calling iframe functions
    // @namespace   _pc
    // @include     http://jsbin.com/ugoruz/*
    // @include     http://jsbin.com/okequw/*
    // ==/UserScript==
    
    console.log ("Script start...");
    
    /*--- This next function call will work in Firefox or Tampermonkey ONLY,
        not pure Chrome userscript.
    */
    console.log ("calling functionOfInterest ()...");
    unsafeWindow.functionOfInterest ();
    
    
    if (window.top === window.self) {
        //--- Code to run when page is the main site...
        console.log ("Userscript is in the MAIN page.");
    
        //--- The frames object does not play nice with unsafeWindow.
        /*--- These next three work in Firefox, but not Tampermonkey, nor pure Chrome.
        console.log ("1", frames[1].variableOfInterest);                // undefined
        console.log ("2", unsafeWindow.frames[1].variableOfInterest);   // undefined
        console.log ("3", frames[1].unsafeWindow);                      // undefined
        */
        /*--- This next would cause a silent crash, all browsers...
        console.log ("4", unsafeWindow.frames[1].unsafeWindow.variableOfInterest);
        */
    
        //--- To get at iFramed JS, we must inject our JS.
        withPages_jQuery (demoAccessToFramedJS);
    }
    else {
        //--- Code to run when page is in an iframe...
        console.log ("Userscript is in the FRAMED page.");
        console.log ("The frame's ID is:", window.self.frameElement.id);
    }
    
    
    function demoAccessToFramedJS ($) {
        $("body").prepend (
              '<button id="gmMain">Run JS on main window</button>'
            + '<button id="gmFrame">Run JS on iframe</button>'
        );
    
        $("#gmMain, #gmFrame").click ( function () {
            if (this.id === "gmMain") {
                functionOfInterest ();
            }
            else {
                frames[1].functionOfInterest ();
            }
            console.log (this.id + "was clicked.");
        } );
    }
    
    function withPages_jQuery (NAMED_FunctionToRun) {
        //--- Use named functions for clarity and debugging...
        var funcText        = NAMED_FunctionToRun.toString ();
        var funcName        = funcText.replace (/^function\s+(\w+)\s*\((.|\n|\r)+$/, "$1");
        var script          = document.createElement ("script");
        script.textContent  = funcText + "\n\n";
        script.textContent += 'jQuery(document).ready(function() {'+funcName+'(jQuery);});';
        document.body.appendChild (script);
    };
    
    console.log ("Script end");
    



    您将看到该脚本从主页面和iframe运行一个函数。控制台输出(Tampermonkey)将是:

    Tampermonkey started
    Script start...
    calling functionOfInterest ()...
    Userscript is in the MAIN page.
    Script end
    Tampermonkey started
    Script start...
    calling functionOfInterest ()...
    Userscript is in the FRAMED page.
    The frame's ID is: iframe2
    Script end
    

    1 如果您删除unsafeWindow行,它也可以作为直接的Chrome用户脚本。