web-dev-qa-db-ja.com

UserScripts&Greasemonkey:ウェブサイトのJavaScript関数を呼び出す

私はFirefox&Chrome=のUserScript拡張機能を作成していますが、ウェブサイトのJavaScriptでいくつかのコードを使用しようとしています。たとえば:

_function: myFunction(){
    return  Grooveshark.playNextSong();
}
_

問題は、このコードをテストすると、Groovesharkがnull参照になることです。

私はそれを行った他の人々がいることを知っています:

BetterGroovesharkを参照

しかし、なぜ私の単純な拡張機能がGroovesharkのJavaScript関数を呼び出せないのかはわかりません。

これを機能させるには、スクリプトをドキュメントに「追加」する必要がありますか?:document.document.body.appendChild(script);

Greasemonkeyは拡張機能のJavaScriptをすでに挿入していませんか?誰かがこれを明確にしてくれませんか?.

ありがとう。

33
sebastian

バックグラウンド

Greasemonkeyは拡張機能のJavaScriptを既に挿入していませんか?誰かがこれを明確にしてくれませんか?.

Greasemonkeyは sandbox でスクリプトを実行します。これは、ページ内のJavaScriptに直接アクセスしない制限された環境です。以前のバージョンのGreasemonkeyはスクリプトをページに直接挿入していましたが、これにより深刻なセキュリティの脆弱性が生じました。古いモデルでは、スクリプトはブラウザークロムの昇格された権限で実行されていました。これにより、リモートページが 巧妙なJavaScript を使用してGreasemonkeyの組み込み関数にアクセスできるようになりました。これは悪かった:

通常のxmlttprequestオブジェクトとは異なり、Greasemonkeyスクリプトには独自のGM_xmlhttprequestオブジェクトが含まれており、通常はxmlhttprequestに適用される同じOriginポリシーに関係なく、コンピューターのローカルファイルにアクセスしたり、任意のサイトに任意のリクエストを送信したりできます。 (ソース)

今日、Greasemonkeyスクリプトからwindowオブジェクトにアクセスすると、実際のwindowのプロパティを間接的に参照する ラッパーオブジェクト が得られます。このラッパーオブジェクトは安全に変更できますが、 重要な制限 があります。実際のウィンドウオブジェクトへのアクセスは、 unsafeWindowwindow.wrappedJSObjectの省略形)によって提供されます。 unsafeWindowを使用すると、Greasemonkeyの元々のセキュリティ問題がすべて再び開き、Chromeでは使用できません。可能な限り回避する必要があります。

良いニュース:Greasemonkeyの新しいセキュリティモデルを安全に使用するには、少なくとも2つの方法があります。

スクリプトインジェクション

Greasemonkeyスクリプトが安全にDOMにアクセスできるようになったので、ターゲットドキュメントの<script><head> タグを挿入するのは簡単です。次のような関数を作成します。

function exec(fn) {
    var script = document.createElement('script');
    script.setAttribute("type", "application/javascript");
    script.textContent = '(' + fn + ')();';
    document.body.appendChild(script); // run the script
    document.body.removeChild(script); // clean up
}

使い方は簡単です:

exec(function() {
    return Grooveshark.playNextSong();
});

ロケーションハック

スクリプトインジェクションは、特にページ内の変数の値を変更するか、単一の関数を実行するだけでよい場合など、場合によってはやり過ぎになることがあります。 Location Hack は、javascript: URLを利用して、ドキュメントのコンテンツのコードにアクセスします。これは、Greasemonkeyスクリプト内からブックマークレットを実行するのとよく似ています。

location.assign("javascript:Grooveshark.playNextSong();void(0)");

ボーナススクリプト

上記の例を示す完全なGreasemonkeyスクリプトは次のとおりです。このページで実行できます。

// ==UserScript==
// @name           Content Function Test
// @namespace      lwburk
// @include        http://stackoverflow.com/questions/5006460/userscripts-greasemonkey-calling-a-websites-javascript-functions
// ==/UserScript==

function exec(fn) {
    var script = document.createElement('script');
    script.setAttribute("type", "application/javascript");
    script.textContent = '(' + fn + ')();';
    document.body.appendChild(script); // run the script
    document.body.removeChild(script); // clean up
}

window.addEventListener("load", function() {
    // script injection
    exec(function() {
        // alerts true if you're registered with Stack Overflow
        alert('registered? ' + isRegistered);
    });
    // location hack
    location.assign("javascript:alert('registered? ' + isRegistered);void(0)");
}, false);
73
Wayne Burkett

GreaseMonkeyスクリプト(およびChromeのユーザースクリプト)で宣言された関数と変数は、明らかな理由により、Webページで宣言されたものとは別に保持されます。 GM Firefoxのスクリプトの場合、 unsafeWindow を使用してグローバル変数にアクセスできます。

安全性と互換性のための最良のアプローチは、スクリプト要素を使用してページに関数を挿入することです。ユーザースクリプトで次のスニペットを使用しています。

function addFunction(func, exec) {
  var script = document.createElement("script");
  script.textContent = "-" + func + (exec ? "()" : "");
  document.body.appendChild(script);
}

"-"ここでは、関数が式として解析されることを確認しているため、execを使用すると、関数を追加するとすぐに実行できます。次のように関数を呼び出します。

function myFunction () {
    return Grooveshark.playNextSong();
}

// Inject the function and execute it:
addFunction(myFunction, true);
11
Andy E