GM_
函数在注入代码中不起作用,因为注入代码在目标页面的范围内运行。如果他们确实在那里工作,那么不道德的网站也可以使用这些GM_
功能 - 做无法形容的邪恶。
最可取的解决方案是:
不要注入代码。很多时候,它真的没有必要,而且它总是使事情复杂化。仅在您绝对肯定需要使用目标页面加载的某些 javascript 时才注入代码。
对于像 jQuery 这样的库,使用@require
指令 (Firefox) 或粘贴库代码或使用自定义manifest.json文件包含它 (Chrome) 将获得更好的性能。
通过不注入代码,您:
- 保持轻松使用
GM_
功能的能力
- 避免或减少对外部服务器交付库的依赖。
- 避免潜在的副作用和对页面 JS 的依赖。(您甚至可以使用NoScript之类的东西来完全禁用页面的 JS,而您的脚本仍在运行。)
- 防止恶意网站利用您的脚本来访问这些
GM_
功能。
使用Tampermonkey 扩展程序(Chrome)。这允许您通过提供更好的 Greasemonkey 仿真来避免脚本注入。您可以使用该@require
指令和unsafeWindow
比 Chrome 原生提供的更强大/更危险的版本。
将您的用户脚本代码拆分为注入部分(不能使用GM_
函数)和非注入部分。使用消息传递、轮询和/或特定 DOM 节点在作用域之间进行通信。
如果你真的必须使用注入代码,这里有一个示例脚本,展示了如何做到这一点:
// ==UserScript==
// @name _Fire GM_ function from injected code
// @include https://stackoverflow.com/*
// @grant GM_xmlhttpRequest
// ==/UserScript==
/* Warning: Using @match versus @include can kill the Cross-domain ability of
GM_xmlhttpRequest! Bug?
*/
function InjectDemoCode ($) {
$("body").prepend ('<button id="gmCommDemo">Open the console and then click me.</button>');
$("#gmCommDemo").click ( function () {
//--- This next value could be from the page's or the injected-code's JS.
var fetchURL = "http://www.google.com/";
//--- Tag the message, in case there's more than one type flying about...
var messageTxt = JSON.stringify (["fetchURL", fetchURL])
window.postMessage (messageTxt, "*");
console.log ("Posting message");
} );
}
withPages_jQuery (InjectDemoCode);
//--- This code listens for the right kind of message and calls GM_xmlhttpRequest.
window.addEventListener ("message", receiveMessage, false);
function receiveMessage (event) {
var messageJSON;
try {
messageJSON = JSON.parse (event.data);
}
catch (zError) {
// Do nothing
}
console.log ("messageJSON:", messageJSON);
if ( ! messageJSON) return; //-- Message is not for us.
if (messageJSON[0] == "fetchURL") {
var fetchURL = messageJSON[1];
GM_xmlhttpRequest ( {
method: 'GET',
url: fetchURL,
onload: function (responseDetails) {
// DO ALL RESPONSE PROCESSING HERE...
console.log (
"GM_xmlhttpRequest() response is:\n",
responseDetails.responseText.substring (0, 80) + '...'
);
}
} );
}
}
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);
};