9

Web ページに挿入されるユーザー スクリプトを作成しています。スクリプトは Web サーバーからいくつかのデータを読み取り、リッスンしているアプリケーションにメッセージを送信してデータに反応させたいと考えています。

今のところ、私がやっていることは、リスニング アプリケーションに文字列コマンドを送信して、それを読み取れるかどうかを確認することだけです。コードが挿入される前は機能していましたが、その後、「未定義の参照エラー」が発生します。

これは、今回の「Greasemonkey アクセス違反」と関係があると思われます。ただし、機能する解決策を見つけることができませんでした。私はChromeで開発しています。

これは、私が作業できないコードのセクションです。

GM_xmlhttpRequest({
   method: "POST", 
   url: "http://localhost:7777", 
   data: "testing123",
   headers:  {
         "Content-Type": "application/x-www-form-urlencoded"
             },
   onload: function(response) 
   {
      if (response.responseText.indexOf("TEST") > -1) 
      {
         console.log("Response confirmed..."); 
      }
   }
}); 

私はスクリプト作成にかなり慣れていないので、明らかな何かが欠けている可能性があります。挿入されたコードでこれを機能させるにはどうすればよいですか?

4

2 に答える 2

22

GM_挿入されたコードはターゲット ページのスコープ内で実行されるため、関数は挿入されたコードでは機能しません。それらそこで機能した場合、悪意のある Web サイトもそのGM_機能を使用して、言いようのない悪を行う可能性があります。

解決策、最も望ましい最初:

  1. コードを挿入しないでください。多くの場合、それは実際には必要ではなく、常に事態を複雑にします。ターゲット ページによってロードされた JavaScript の一部を絶対に、確実に使用する必要がある場合にのみ、コードを挿入します。

    jQuery などのライブラリの場合、@requireディレクティブを使用するか (Firefox)、ライブラリ コードを貼り付けるか、カスタムmanifest.jsonファイルを使用してそれを含める (Chrome) ことで、パフォーマンスが向上します。

    コードを挿入しないことで、次のことが可能になります。

    1. GM_機能を使いやすく保つ
    2. ライブラリを配信するための外部サーバーへの依存を回避または軽減します。
    3. ページの JS との潜在的な副作用や依存関係を回避します。( NoScriptのようなものを使用して、スクリプトがまだ実行されている間にページの JS を完全に無効にすることもできます。)
    4. 悪意のある Web サイトがスクリプトを悪用して機能にアクセスするのを防ぎますGM_

  2. Tampermonkey 拡張機能(Chrome)を使用します。これにより、より優れた Greasemonkey エミュレーションを提供することで、スクリプト インジェクションを回避できます。ディレクティブと、 Chrome がネイティブに提供するものよりも@require強力で危険なバージョンを使用できます。unsafeWindow

  3. ユーザースクリプトコードを、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);
};
于 2012-07-07T22:37:41.807 に答える