読者です 読者をやめる 読者になる 読者になる

心魅 - cocoromi -

半角スペース時々全角

グリモンuserscriptをChromeに移植するときに使う、GM APIのラッパっぽいものとプロジェクトテンプレートを書いた

2010/10/17 公開先をGithubにしています。
http://d.hatena.ne.jp/umezo/20100411/1270988391


Chrome速くて良いのですが、いかんせん、グリモンとか便利な物が無い。
そこでグリモンのスクリプトをextensionとしてChromeに持って行きたいのですが、GM_*なAPIが無い……
さらに、extensionの制限上の理由から、完全に移植することは出来ません。


ただし、何点かの妥協と既存のuser scriptのちょっとした修正で移植可能です。


移植用に可能な限りGM_*をラップ出来るようなものを作りました。
http://umezo.tsuyabu.in/chrome/gmWrapper.zip

使い方

zipファイルを展開すると以下のようなファイルが格納されています。
manifest.jsonを移植するグリモンに合わせて編集してください。
youGMScript.user.jsはサンプルです。移植したいuserscriptに置き換え、合わせてマニフェストも修正してください。

background.html
background.js
gmWrapper.js
manifest.json
yourGMScript.user.js

マニフェストの変更箇所

マニフェストの中身

  1 {
  2     "name": "change name for your GM script",
  3     "version": "1.0",
  4     "description": "change description for your GM script",
  5     "permissions" : [
  6         "http://*/*" ,
  7         "https://*/*"
  8     ] ,
  9     "background_page": "background.html",
 10
 11     "content_scripts": [{
 12         "matches": [
 13             "http://*/*" ,
 14             "https://*/*"
 15         ],
 16         "js": [ "gmWrapper.js" , "yourGMScript.user.js" ]
 17     }]
 18 }

background_pageとcontent_scripts.js[0]のgmWrapper.js以外をuserscriptに合わせて修正してください。

userscriptの修正

GM APIを使っている場合はどうしても吸収しきれなかったので、同梱のyourGMScript.user.jsを参考に修正を加えてください。

yourGMScript.user.js中身

  1 // ==UserScript==
  6 // ==/UserScript==
 10
 11 if( typeof isChromeExtension == "undefined" ){ //chrome wrapperが読み込まれていない場合 = グリモンに読み込まれている
 12     init();
 13 }else{ //こっちの場合はラッパーと一緒に読み込まれているのでonReadyGMイベントを受け取ってから初期化
 14     function onReadyGM(){
 15         init();
 16     }
 17 }
 18 //userscriptの初期化処理
 19 function init(){
 20     GM_setValue( "key1" , "value1" );
 21     GM_log( GM_getValue( "key1" ) );
 22
 23     GM_log( GM_getValue( "key2" , "default2" ) );
 24     GM_setValue( "key2" , "value2_stored" ) ;
 25
 26     GM_setValue( "key1" , "value1_new" );
 27     GM_log( GM_getValue( "key1" ) );
 28
 30     GM_xmlhttpRequest({
 31         method : "get" ,
 32         url: "http://www.google.com/" ,
 33         onload : function (req) {
 34             GM_log( req );
 35         }
 41     });
 42 }

ラップ出来なかったAPI

GM_registerMenuCommandはひとまず諦めました。
もし無理矢理移植するとすればpage_actionを利用する形になると思います。

まとめ

とっとと、グリモンそのものが移植出来るぐらいAPIが充実するといいですね。


以下付録

GM_getValue,GM_setValueの移植方法

データの保存場所はもちろんlocalStorageを使います。
そのため、background_pageにlocalStorageへアクセスするAPIをもたせます。
だたし、データの取得のたびにbackground_pageに問い合わせすると、非同期にしなくてはいけないので、
初期化処理のときにlocalStorageを丸ごと受け取ってキャッシュします。


懸念としてはlocalStorageにものすごく巨大な物を保存するような場合ですかね・・・。
そんなスクリプトあるんでしょうか・・・。


ラッパー部のコード

          〜前略〜
 33     //background_pageからlocalStorageを受け取ってキャッシュ
 34     //onReadyGMハンドラを実行
 35     function onInitializedGM( response ){
 36         localStorage = response ;
 37         isInitialized = true ;
 38         onReadyGM();
 39     }
          〜中略〜
 49     GM_setValue = function ( key , value ){
 50         if( !isInitialized ){
 51             console.log( "Error" , "GM_setValue was called before finished initializing" );
 52             return ;
 53         }
 54
 55         //キャッシュに書き込み
 56         localStorage[ key ] = value ;
 57
 58         //background_pageに書き込みメッセージ送信
 59         port.postMessage( { action : "setValue" , args : [ key , value ] } );
 60     };
 61
 62
 63     GM_getValue = function ( key , def ){
 64         if( !isInitialized ){
 65             console.log( "Error" , "GM_getValue was called before finished initializing" );
 66             return ;
 67         }
 68
 69         //値がセットされていなければAPI経由で保存
 70         if( localStorage[ key ] == undefined && def != undefined ){
 71             GM_setValue( key , def );
 72         }
 73
 74         //キャッシュから読み込んで返す
 75         return localStorage[ key ] ;
 76     };

GM_xmlhttpRequest

以前書いたエントリーのアイデアをそのまま使っています。
http://d.hatena.ne.jp/umezo/20091114/1258193365

GM_log

consoe.log

GM_registerMenuCommand

ひとまず保留