【问题标题】:How can I mimic Greasemonkey/Firefox's unsafeWindow functionality in Chrome?如何在 Chrome 中模仿 Greasemonkey/Firefox 的 unsafeWindow 功能?
【发布时间】:2010-12-09 23:29:07
【问题描述】:

我现在只是在 chrome 中摆弄用户脚本,所以请忍受我潜在的无知/白痴。

在我正在为其编写脚本的页面中,有一个<script> 元素声明了一个变量x。 这是否意味着,在我的用户脚本中,我只能从全局命名空间访问x

例如,如果我的用户脚本中的唯一行是alert(x);,那么它是否应该按预期工作(假设x 是一个字符串)?我了解 chrome 不支持 unsafewindow,但由于某种原因,我发现无法弄清楚如何模仿该功能。有没有可能?

【问题讨论】:

    标签: javascript google-chrome greasemonkey


    【解决方案1】:

    这将为您提供对窗口对象的引用(作为 p):

    var p = unsafeWindow;
    
    if(window.navigator.vendor.match(/Google/)) {
        var div = document.createElement("div");
        div.setAttribute("onclick", "return window;");
        p = div.onclick();
    };
    

    【讨论】:

    • 没有必要进行“供应商嗅探”,您可以这样做:gist.github.com/1143845
    • 这在最新版本的 Chrome 中似乎不再起作用了。
    【解决方案2】:

    更新:
    onclick 漏洞利用在最新的 Chrome 版本中不再有效。

    要在 Chrome 中获得 unsafeWindow 功能,最好的办法是安装和使用 Tampermonkey -- 无论如何,您都应该这样做。 Tampermonkey 完全支持 Greasemonkey API,并且脚本管理更简单。

    Greasemonkey 脚本和 Tampermonkey 脚本几乎总是完全兼容,这对于普通的 Chrome 用户脚本来说并非如此。

    放弃 Tampermonkey,唯一仍然有效的替代方法是使用某种形式的 script injection



    以下内容现已过时:

    Chrome now defines unsafeWindow for userscripts / content-scripts,但是Chrome的unsafeWindow仍然不允许访问目标页面创建的JS对象。

    以下是如何提供适当不安全的unsafeWindow -- 以使用Feature Detection (good) versus Browser Sniffing (Bad) 的跨浏览器方式:

    /*--- Create a proper unsafeWindow object on browsers where it doesn't exist
        (Chrome, mainly).
        Chrome now defines unsafeWindow, but does not give it the same access to
        a page's javascript that a properly unsafe, unsafeWindow has.
        This code remedies that.
    */
    var bGreasemonkeyServiceDefined     = false;
    
    try {
        if (typeof Components.interfaces.gmIGreasemonkeyService === "object") {
            bGreasemonkeyServiceDefined = true;
        }
    }
    catch (err) {
        //Ignore.
    }
    
    if ( typeof unsafeWindow === "undefined"  ||  ! bGreasemonkeyServiceDefined) {
        unsafeWindow    = ( function () {
            var dummyElem   = document.createElement('p');
            dummyElem.setAttribute ('onclick', 'return window;');
            return dummyElem.onclick ();
        } ) ();
    }
    

    【讨论】:

    • 这还能用吗?我在 chrome 中尝试了它以覆盖 XHR 发送,但它似乎没有做任何事情。我刚刚添加:var oldSend = unsafeWindow.XMLHttpRequest.prototype.send; unsafeWindow.XMLHttpRequest.prototype.send = function(){ console.log("notified of XHR update"); oldSend.apply(this, arguments); } 但在请求期间我没有得到任何输出。如果我将它注入页面,这段代码确实会产生输出。
    • @Mix,是的,我刚刚验证它仍然适用于 Chrome 版本 18 和版本 19 (19.0.1084.56 m)。为您的问题打开一个新问题。
    • @user280109,是的,Chrome 修复了该漏洞。无论如何,您都应该安装和使用 Tampermonkey。否则你将不得不使用script injection
    • ViolentMonkey 也是 chrome 中的一个选项,并且是开源的,所以我宁愿推荐它而不是 TamperMonkey。不过,非常感谢答案的深度!我想了很久。
    【解决方案3】:

    contentWindow 在 Chrome 3 中可用,但 removed in Chrome 4。 Chrome 4 唯一可能的解决方案:

    location.href="javascript:(function(){ alert('Hello'); })()"
    

    【讨论】:

      【解决方案4】:

      如果您想与页面 JavaScript 交互,则必须将脚本插入页面。 (当然,除非您想使用此页面上建议的任何 hack。)我已经为我自己的脚本编写了一个函数来执行此操作,我将在此处发布它以防有人想使用它。

      /*
          @description    This function will insert the given code as a <script> or <style> block into a page.
          @param The code to insert; supported types are: JavaScript Function, String (JavaScript), String (CSS).
          @param2 Optional: The type of code that is inserted. If omitted, "js" is assumed. Possible values are 'js' or 'css'.
          @return The HTML element that was inserted, or FALSE on failure
      */
      function insert(z,t){
          var j,f,x,c,i,n,d
          d=document
          c=d.createElement
          i=d.head.appendChild
          a=d.createTextNode
          if(typeof z==='function') j=!0,f=!0;
          if((t=='js'||!t)&&!f){j=!0,f=!1}
          if(t=='css'&&!j){x=c('style');x.setAttribute('type','text/css')}
          if(j){x=c('script');x.setAttribute('type','text/javascript')}
          if(f) n=a('('+z+')()');else n=a(z)
          x.appendChild(n)
      
          if(x){return i(x)}else{return !1}
      }
      

      举几个例子来说明:

      //Inserting a JavaScript function
      var func=function(){
          stopAds();
          startFileDownload();
      }
      
      insert(func);
      
      
      //Inserting JavaScript as a string
      var strJS="prompt(\"Copy:\",someVariableAtThePage);";
      
      insert(strJS);
      //Or with an OPTIONAL 2nd parameter:
      insert(strJS,'js');
      
      
      //Inserting CSS
      var strCSS=".ad{display:none !important}    #downloadButton{display:block}";
      
      insert(strCSS,'css');//Specifying 2nd parameter as "css" is required.
      

      【讨论】:

        【解决方案5】:

        好的,这里有一个想法,您可以使用地址栏注入脚本...

        javascript:var ElEm = document.createElement("script");ElEm.src='[path_to_script]';document.body.appendChild(ElEm);
        

        然后你可以用你的javascript在窗口中运行你想要的任何东西

        【讨论】:

        • 哦,如果该变量是页面的全局变量,您应该能够使用您的 javascript 读取它
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-01
        • 1970-01-01
        • 2010-10-09
        • 1970-01-01
        • 2012-11-10
        相关资源
        最近更新 更多