GM_
挿入されたコードはターゲット ページのスコープ内で実行されるため、関数は挿入されたコードでは機能しません。それらがそこで機能した場合、悪意のある Web サイトもそのGM_
機能を使用して、言いようのない悪を行う可能性があります。
解決策、最も望ましい最初:
コードを挿入しないでください。多くの場合、それは実際には必要ではなく、常に事態を複雑にします。ターゲット ページによってロードされた JavaScript の一部を絶対に、確実に使用する必要がある場合にのみ、コードを挿入します。
jQuery などのライブラリの場合、@require
ディレクティブを使用するか (Firefox)、ライブラリ コードを貼り付けるか、カスタムmanifest.jsonファイルを使用してそれを含める (Chrome) ことで、パフォーマンスが向上します。
コードを挿入しないことで、次のことが可能になります。
GM_
機能を使いやすく保つ
- ライブラリを配信するための外部サーバーへの依存を回避または軽減します。
- ページの JS との潜在的な副作用や依存関係を回避します。( NoScriptのようなものを使用して、スクリプトがまだ実行されている間にページの JS を完全に無効にすることもできます。)
- 悪意のある Web サイトがスクリプトを悪用して機能にアクセスするのを防ぎます
GM_
。
Tampermonkey 拡張機能(Chrome)を使用します。これにより、より優れた Greasemonkey エミュレーションを提供することで、スクリプト インジェクションを回避できます。ディレクティブと、 Chrome がネイティブに提供するものよりも@require
強力で危険なバージョンを使用できます。unsafeWindow
ユーザースクリプトコードを、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);
};