关闭`@grant none`会破坏我的Greasemonkey脚本?

时间:2014-08-09 19:45:06

标签: jquery facebook greasemonkey sandbox

我在Facebook主页上运行此脚本。它会在底部的Dock中获取所有会话并获取__FB_TOKEN s。

// ==UserScript==
// @name MyScript
// @namespace MyNameSpance
// @include /https?://(www.)?facebook.com(/.*)?/
// @require http://code.jquery.com/jquery-2.1.0.min.js
// @version 0.0.0
// @grant none
// ==/UserScript==
(function () {
  // Don't run on frames or iframes
  if (window.top != window.self) {
    return ;
  }

  window.addEventListener('load', function () {

    var element = $('.fbNubGroup.clearfix.videoCallEnabled');
    console.log('SCRIPT ELEMENT: ', element); // is displayed on the console

    var children = element.children();
    console.log('SCRIPT CHILDREN: ', children); // is displayed on the console

    for (var i = 0; i < children.length; i++) {
      var child = $(children[i]);
      console.log('SCRIPT CHILD: ', child); // is displayed on the console

      /*
      child :
        Object [div.someClasses]
          + 0: div.someClasses
            + __FB_TOKEN: [ 267 ]
      */

      console.log('SCRIPT CHILD[0]: ', child[0]); // is displayed on the console
      console.log('SCRIPT CHILD[0].__FB_TOKEN:', child[0].__FB_TOKEN); // UNDEFINED

      var key = child[0].__FB_TOKEN[0];
      console.log('SCRIPT KEY: ', key); // not displayed
    }
  }, false);
}) ();


使用@grant none,它按预期工作,我得到:

grant_none


但是,如果我将@grant none更改为@grant GM_xmlhttpRequest,则该脚本将不再有效。它给出了:

grant GM_xmlhttpRequest

并在child[0].__FB_TOKEN行引发异常。


我不明白为什么,因为CHILD[0]没有改变:

child

为什么更改@grant none打破脚本?

1 个答案:

答案 0 :(得分:7)

当您从@grant none切换到@grant GM_xmlhttpRequest时,Greasemonkey switches the sandbox back on, as a side-effect (坦率地说,所有GM开发人员和脚本都应该始终使用沙箱运行 - 极少数情况下例外。这可以避免&#34;定时炸弹&#34;编码问题和头脑风暴这样的问题。)

JavaScript对象,数组,变量和函数无法跨越沙箱。但是unsafeWindow作为有限的解决方法提供给Greasemonkey范围。

这个问题也很重要:

  1. Greasemonkey (and Firefox) just shut down some of the previously possible solutions using unsafeWindow
  2. jQuery是一种特殊情况,并且非常难以将非DOM对象用于沙箱。
  3. 解决方案:

    1. 由于__FB_TOKEN是一个数组,因此您必须使用unsafeWindow将其传到沙盒中。
    2. 在这种情况下尝试使用jQuery会产生令人无法接受的高头痛与结果比率;所以使用普通的DOM方法。
    3. 将脚本全部放在一起成为:

      // ==UserScript==
      // @name        _MyScript
      // @namespace   MyNameSpace
      // @include     /https?://(www.)?facebook.com(/.*)?/
      // @require     http://code.jquery.com/jquery-2.1.0.min.js
      // @version     0.0.0
      // @grant       GM_xmlhttpRequest
      // ==/UserScript==
      (function () {
          // Don't run on frames or iframes
          if (window.top != window.self) {
              return;
          }
          window.addEventListener ('load', function () {
              /*--- This unsafeWindow is key. After that, don't use any jQuery
                  while trying to get at javascript objects like __FB_TOKEN.
              */
              var element = unsafeWindow.document.querySelector (
                  '.fbNubGroup.clearfix.videoCallEnabled'
              );
              /*-- Used console.info to make it easier to spot messages buried
                  in all the Facebook console crud.
              */
              console.info ('SCRIPT ELEMENT: ', element);
      
              var children = element.children;
              console.info ('SCRIPT CHILDREN: ', children);
      
              for (var i = 0; i < children.length; i++) {
                  var child = children[i];
                  console.info ('SCRIPT CHILD: ', child);
      
                  /*
                  child :
                    Object [div.someClasses]
                      + 0: div.someClasses
                        + __FB_TOKEN: [ 267 ]
                  */
                  console.info ('SCRIPT CHILD: ', child);
                  console.info ('SCRIPT CHILD.__FB_TOKEN:', child.__FB_TOKEN);
      
                  var key = child.__FB_TOKEN[0];
                  console.info ('SCRIPT KEY: ', key);
              }
          }, false);
      } ) ();