カスタムスクリプト用のクロスブラウザーシェルの作成

こんにちは、ハラジテリ。 Habréにはユーザースクリプト(ユーザースクリプト)に関する多くの投稿がありましたが、それらの使用方法のみを示しました。 また、ユーザースクリプトの作業では、ブラウザー間の非互換性が多くあります(ブラウザーjsのどの領域でも)。 当然、さまざまなブラウザーにさまざまなアドオンをインストールできますが、エンドユーザー向けのスクリプトを作成する場合は、通常の動作を確保するために、コンポーネントのインストールに関する膨大なreadmeを添付する必要があります。 個人的には、私もあなたも、あなたにはあまり似合わないと思います。



この記事では、Mozilla Firefox(GreaseMonkeyがインストールされている)、Google Chrome、Operaの3つのブラウザーについて説明します。 この記事の目的は「プレハブ」です。これにより、リストされているすべてのブラウザーでユーザースクリプトが同じように機能します。 GM APIの実装は考慮されません。 すでに何百もあります。 読者は、ユーザースクリプトを記述するための一般的なルールを既に知っていることを前提としています(そうでない場合は、 最初に別の記事を読むことをお勧めします)。





トピックに直接。 ディレクティブから始めましょう。 いくつかの非互換性があります。まず、オペラではincludeのみサポートされ、chromeでは一致のみサポートされます。 Firefoxは両方をサポートしています。 したがって、両方のディレクティブを(突然)指定する必要があります。 次に、firefoxでunsafeWindowをサポートするには、@ unwrapディレクティブが必要です。 unsafeWindowを使用する前に、これが本当に必要かどうかをよく考える必要があることを明確にしません。 したがって、ワークピースの最初の部分は次のようになります。

// ==UserScript== // @name script_name // @author author's name // @version 1.0 // @description example // @unwrap // @run-at document-end // @include http://example.com/* // @match http://example.com/* // ==/UserScript==
      
      







さらに、Chromeでは、 matchディレクティブにフォールオフする機能があるため、次のような行を先頭に追加する価値があります。

 if (location.hostname !== "example.com") return;
      
      







それでは、スコープについて話しましょう。 Google Chromeでは、ユーザースクリプトは常に別のスコープで実行されますが、オペラでは、ページの中央で実行されるため、すべてのグローバル変数を破壊する恐れがあります。 したがって、セキュリティのために、追加のクロージャーを追加するとよいでしょう。

 // ==UserScript== // @name script_name // @author author's name // @version 1.0 // @description example // @unwrap // @run-at document-end // @include http://example.com/* // @match http://example.com/* // ==/UserScript== (function(){ if (location.hostname !== "example.com") return; })();
      
      







そして最後に、グローバルオブジェクトへのアクセスなどの重要なことです。 Mozilla Firefoxでは、unsafeWindow変数を介してアクセスされます。Operaでは、スクリプトはページ表示領域で直接実行されるため、グローバル変数はウィンドウを介してアクセスできます。GoogleChromeでは、グローバルオブジェクトにまったくアクセスできません(悲しみ)。 ただし、onclickがウィンドウを返すページにオブジェクトを追加することにより、unsafeWindowをエミュレートできます。 実際には、コメント付きのコード:



 //   unsafeWindow    -   ,    , //      window var unsafeWindow= this.unsafeWindow; //  ,    unsafeWindow,     , //    (function(){ // ..,   ,      , //  unsafeWindow  chrome,   , ,   . var test_scr= document.createElement("script"); //       var tid= ("t" + Math.random() + +(new Date())).replace(/\./g, ""); //       . test_scr.text= "window."+tid+"=true"; document.querySelector("body").appendChild(test_scr); //      unsafeWindow, //         if (typeof(unsafeWindow) == "undefined" || !unsafeWindow[tid]) { if (window[tid]) { // ..   window -    window, //    unsafeWindow= window; } else { //   -    var scr= document.createElement("script"); scr.text= "(" + (function() { var el= document.createElement('unsafeWindow'); el.style.display= 'none'; el.onclick=function(){return window}; document.body.appendChild(el); }).toString() + ")()"; //   -   script      document.querySelector("body").appendChild(scr); this.unsafeWindow= document.querySelector("unsafeWindow").onclick(); //   ,     // onclick  unsafeWindow ,      unsafeWindow= this.unsafeWindow; }; } })(); // 
      
      







したがって、最終的には、空白は次のようになります。

 // ==UserScript== // @name script_name // @author author's name // @version 1.0 // @description example // @unwrap // @run-at document-end // @include http://example.com/* // @match http://example.com/* // ==/UserScript== (function(){ if (location.hostname !== "example.com") return; var unsafeWindow= this.unsafeWindow; (function(){ var test_scr= document.createElement("script"); var tid= ("t" + Math.random() + +(new Date())).replace(/\./g, ""); test_scr.text= "window."+tid+"=true"; document.querySelector("body").appendChild(test_scr); if (typeof(unsafeWindow) == "undefined" || !unsafeWindow[tid]) { if (window[tid]) { unsafeWindow= window; } else { var scr= document.createElement("script"); scr.text= "(" + (function() { var el= document.createElement('unsafeWindow'); el.style.display= 'none'; el.onclick=function(){return window}; document.body.appendChild(el); }).toString() + ")()"; document.querySelector("body").appendChild(scr); this.unsafeWindow= document.querySelector("unsafeWindow").onclick(); unsafeWindow= window.unsafeWindow; }; } })(); //  ,    })();
      
      







それだけです。 この記事が誰かを助けることを願っています。



PSそうそう。 Firefoxでユーザースクリプトをデバッグするには、この種のtry ... catchコンストラクトでスクリプトコードをラップできます。

{

//スクリプトコード

} catch(e){console.error(e)}

人生をとても促進します。



UPD:この記事にすばらしい追加をしてくれてありがとう。 むしろ、この記事は彼が書いたものに加えて...



UPD2: includeディレクティブは、不要なサイトでchromeでスクリプトを動作させませんが、スクリプトをインストールするときに、 matchディレクティブを指定しない場合、スクリプトはすべてのページで動作すると言われます。 したがって、matchディレクティブを指定することをお勧めします。



All Articles