グリモン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
ひとまず保留