设置 @grant 值时无法使用所需的库

Can't use required library when an @grant value is set

有几个与此相关的问题,但使用 unsafeWindow 的一般 'solution' 对我不起作用。

我正在尝试使用 Stack Exchange Javascript SDK

这个有效:

// ==UserScript==
// @name        testing
// @include     http://whosebug.com/*
// @require     https://api.stackexchange.com/js/2.0/all.js
// @version     1
// @grant       none
// ==/UserScript==

console.log(SE);
SE.init({
  clientId: 1234,
  key: 'my key',
  channelUrl: location.protocol + '//whosebug.com/blank',
  complete: function (d) {
    console.log(d);
    console.log('SE init');
  }
});

这不是:

// ==UserScript==
// @name        testing
// @include     http://whosebug.com/*
// @require     https://api.stackexchange.com/js/2.0/all.js
// @version     1
// @grant       GM_setValue
// ==/UserScript==

console.log(SE);
SE.init({
  clientId: 1234,
  key: 'my key',
  channelUrl: location.protocol + '//whosebug.com/blank',
  complete: function (d) {
    console.log(d);
    console.log('SE init');
  }
});

然而,两个版本都记录 Object { authenticate: n(), init: r() } console.log(SE),我无法理解,因为这意味着脚本可以访问 SE 对象。

"doesn't work",我的意思是它什么都不做;在第一个 console.log(SE).

之后没有任何内容记录到控制台

我不明白如何让这个库工作。有人有什么想法吗?这与设置授权值时在 Firefox 上启用的沙箱有关。

顺便说一句,这确实适用于 Chrome,但我的理解是这两个沙箱有很大不同。有什么方法可以绕过这个阻止 SE.init() 函数变为 运行 的 Firefox 沙箱吗?我试过 unsafeWindow.SE... 但这不起作用——我不认为它应该有所作为,因为脚本总是可以访问 SE 对象;只是在调用它时遇到了问题!

快速破解 是将您的整个代码(包括简单的-API 脚本)注入网页并使用消息传递(dispatchEvent + addEventListerner for 'message' window 对象上的事件)访问 GM_ 不可用于注入脚本的函数。

它不如 GM 沙盒安全:如果您安装了扩展程序或用户脚本,API 密钥可以通过 DOM 变异观察器/侦听器或 onbeforescriptexecute 事件侦听器拦截专门用来窃取密钥的。

// ==UserScript==
// @name        testing
// @include     http://whosebug.com/*
// @include     https://whosebug.com/*
// @resource    SE_JS_API https://api.stackexchange.com/js/2.0/all.js
// @version     1
// @grant       GM_setValue
// @grant       GM_getResourceText
// ==/UserScript==

document.head.appendChild(document.createElement('script')).text =
  GM_getResourceText('SE_JS_API') + ';(' + function() {
    SE.init({
      clientId: 1234,
      key: 'my key',
      channelUrl: location.protocol + '//whosebug.com/blank',
      complete: function (d) {
        console.log(d);
        console.log('SE init');
      }
    });
  } + ')(); this.remove();'

API 脚本被声明为资源,因此它只在安装脚本时下载一次,并与脚本一起存储在用户的硬盘上。

或者,注入 API 并通过 unsafeWindowexportFunction 调用它以进行回调:

document.head.appendChild(document.createElement('script')).text =
  GM_getResourceText('SE_JS_API');

unsafeWindow.SE.init({
  clientId: 1234,
  key: 'my key',
  channelUrl: location.protocol + '//whosebug.com/blank',
  complete: exportFunction(function (d) {
    console.log(d);
    console.log('SE init');
  }, unsafeWindow),
});

正确的解决方案 是通过GM_xmlhttpRequest 手动访问actual API,直到有人发布了更好的库。在 Tampermonkey 中,您还需要为 API url:
添加权限 // @connect api.stackexchange.com.