Hatena::ブログ(Diary)

ロックスターになりたい

 | 

2008-06-24

Greasemonkeyスクリプトとウインドウ間で安全に通信する

追記2008.6.24

イベントによる通信について、nanto_viさんがGreasemonkey スクリプトとイベントで通信: Days on the Moonでより有用でフォーマルな情報を提供されています。



まじめに書こうと思ったら予想より使えなかった。

むかしsnj14がはてなブックマークが勝手にj/kにキー割り当てて、サービスはデータを出すだけにしてUIはユーザが好きにできるようにするべきだっていうのを書いてた気がするけど見つけられませんでした。

自分は、そうはいってもfirefox+Greasemonkey+LDRizeのようなUIの統一を図るスクリプトが極めてマイナーな現状でサービスがいらんことすんなっていうのも、ついていけない正しい話だなーと思ってるので、まずはLDRizeがあったら独自のバインディングをやめる、という妥協策が必要だと思う。そうすればはてなブックマークでj/kを押すけどLDRizeは使ってないひとたちを救済しつつsnj14の理想の世界をまた一歩実現に近づけることができる。



Firebug1.2のconsoleの実装と同じように、てきとうなDOMイベントを作って、それを使って通信すればGreasemonkeyとふつうのウインドウ間でunsafeWindowsを使わずに安全に通信することができてLDRizeがあるかどうかも分かる。

Greasemonkey側で

    document.addEventListener( 'LDRizePing', function (ev) {
       var ev = document.createEvent("Events");
                ev.initEvent("LDRizePong", true, true);
                document.dispatchEvent(ev);
    }, false);

ふつうのwindow側で

window.onload = function () {
    document.addEventListener( 'LDRizePong', function (ev) {
        alert( "LDRize exists!" );
    }, false );
    var ev = document.createEvent("Events");
        ev.initEvent("LDRizePing", true, true);
        document.dispatchEvent(ev);
}

ってやったらLDRizeが存在すればpongがかえってくる。

なんかDOM:element.dispatchEvent - MDCにはイベントハンドラでpreventDefaultしたらfalseになるよって書いてあるけどDOMeventだからなのか、常にtrueが返ってきました。

cancelableでinitEventしないと(第3引数をtrueにしないと)preventDefaultしてもfalseになりません(nanto_viさんありがとうございます)。1bitですむ通信ならこれで可能。


リスナがいてもいなくても常にいないときもtrueでした。

あとgreasemonkeyがDOMContentReadyまで実行されないのでふつうのウインドウはそれよりあとまで待たないといけない。onloadはやだからDOMContentReadyでsetTimeoutして実行とかが一番いいけどひどい実装だ。



GM <-> chrome ではprefをwatchするといいとか、そういうのと似たようなアプローチ。JUIのときにinucaraさんがAutoPagerizeにまかせるか自分でやるか迷ったけど自分で実装する方にした、というはなしをされてたので思い出してこうしたら存在するかが分かるっていうのを書こうと思いつつ書いてなかったけど、いまごろなんか思い出した。


AutoPagerizePingとかLDRizePingとか増えるたびに増やしてたら相手にしてられないので、もっとおおざっぱにjsでUIを作るようなのをdisableにするかどうかくらいの粒度にするべきか。


まずはGMのスクリプトの側が存在するかどうかをチェックできる手段を用意してあげるべきだと思う。

gifnksmgifnksm 2008/06/24 12:37 2つめのソースの
>document.addEventListener( ’LDRizePing’, function (ev) {
この部分は
>document.addEventListener( ’LDRizePong’, function (ev) {
の間違いじゃないですか?
Pingイベントを投げたらPongイベントが帰ってくるのでそれをキャッチしているんですよね。

nanto_vinanto_vi 2008/06/24 14:06 > 常にtrueが返ってきました。
FirefoxとSafariではイベントがキャンセル可能でかつpreventDefaultメソッドが呼び出されたとき、つまりそのpreventDefaultメソッドの呼び出しが意味を持つ場合のみfalseを返すようです。Operaは(少なくとも9.0くらいのときは)単純にpreventDefaultメソッドが呼び出されたらfalseを返してたような気がします。

ku0522ku0522 2008/06/24 18:21 >gifnksmさん
ご指摘のとおりping -> pongの間違いでした。ありがとうございます。

>nanto_viさん
cancelableでinitEventしたらpreventDefaultしたときにfalseが帰ってくるようになりました。MDCのドキュメントが少し不正確なのですね。

nanto_vinanto_vi 2008/06/25 03:12 createEventの引数として渡すイベントタイプですが、プレーンなイベントオブジェクトがほしいとき、DOM 2 Eventsでは”HTMLEvents”、DOM 3 Eventsでは”Event”を指定することになっています。FirefoxもSafariも”Events”を受け入れてくれるようですが一応。

はてなユーザーのみコメントできます。はてなへログインもしくは新規登録をおこなってください。

トラックバック - http://d.hatena.ne.jp/ku0522/20080624/1214317218
 |