Home > Latest topics

Latest topics > Webページ内のスクリプトからchrome内に処理を渡す

宣伝1。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。 以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能! シス管系女子って何!? - 「シス管系女子」特設サイト

宣伝2。Firefox Hacks Rebooted発売中。本書の1/3を使って、再起動不要なアドオンの作り方のテクニックや非同期処理の効率のいい書き方などを解説しています。既刊のFirefox 3 Hacks拡張機能開発チュートリアルと併せてどうぞ。

Firefox Hacks Rebooted ―Mozillaテクノロジ徹底活用テクニック
浅井 智也 池田 譲治 小山田 昌史 五味渕 大賀 下田 洋志 寺田 真 松澤 太郎
オライリージャパン

Webページ内のスクリプトからchrome内に処理を渡す - May 16, 2007

分割ブラウザに、Webページ内のスクリプトから任意の方向に表示領域を分割するAPIを加えた。

今回、最終的に「スクリプトを実行しているページのドキュメントのルート要素に属性値を設定することで挙動を制御する」というあんまりスマートでない仕様に落ち着いたんだけど、これは結構苦肉の策というか、本来やりたかったものとは違う形のソリューションになってしまっている。

そもそもなんでこういう機能(?)を加えたかというと、Stylishという拡張機能の作者さんから「そういうAPIを作ったらどうかね」という意見を頂いたからだ。

Stylishはuserstyles.orgというユーザースタイルシートの投稿サイトと連係して動作するようになっていて、現在見ているページで使えるユーザースタイルシートを表示して、ボタン一発でそれをインストールできるようになっている。要は、そういうAPIがSplit Browserにもあった方がいいんじゃないのか、という話。

まず、内容領域のウィンドウに独自の関数なりメソッドなりを定義する という方法を思いついたけど、これは論外だ。セキュリティホールの温床になりかねないから、よっぽどどうしようもない時以外、この方法は採りたくない。

次に、Stylishがそうしているように独自のイベントを定義して、そのイベントが発行されたらSplit Browserでハンドリングする、という方法を思いついた。でもこれは実験してみたらうまく動かなかった。

var newEvent = document.createEvent('Events');
newEvent.initEvent('SubBrowserAddRequestFromInternal', true, true);
newEvent.targetPosition = 2;
newEvent.targetURI = 'http://www.google.com/';
document.dispatchEvent(newEvent);

こんな感じのスクリプトを書いたテストページを用意してみたんだけど、どういうワケか、こうして発行した独自のイベントは、Chromeウィンドウ内のイベントターゲットにリスナを設定する限り、バブリングフェーズでもキャプチャリングフェーズでも、Chromeウィンドウからはハンドリングすることができなかった。何故だ! clickとかのイベントは問題なくハンドリングできてたのに!!

Stylishの場合、ページ内に特定のidのボタンが存在している場合にのみ、そのページのdocumentをターゲットとしてChromeからイベントハンドラを登録してやる、という方法を採っていた。これなら問題なくイベントを捕捉できるっぽいんだけど、Split Browserでこれをすべてのページに対してやるというのは現実的ではない気がする。

次に、window.open()に渡すURIで制御できないか? と言うことを思いついた。Firefox 1.5以降ではnsIBrowserDOMWindowという仕組みによって、新規ウィンドウに開かれるはずの要求を代わりにタブで開くといった処理が可能になってるんだけど、そこに割り込んで、URIの末尾に ?-moz-split-browser-to=TOP のような引数が付いていればタブを開かずにブラウズ領域を分割する、といったことができるようになるはずだと考えたわけだ。

でもこれも実験してみるとうまく動かなかった。ページ内のスクリプトでwindow.open()を実行した時には、nsBrowserAccess.prototype.openURI()には開こうとしているURIが渡されないのだ。Firefox 2に至るまでのどこかの時点でそういう仕様に変更されたらしい。 window.open()の実装その実体nsIWindowWatcherの実装その実体nsIWindowProviderの、ウィンドウを開いていいかどうか確認する処理 と辿って、ハッキリとこの時nsIBrowserDOMWindowのopenURI()には空のURIを渡すと書いてある箇所にぶち当たってしまったので、これはもう、僕にはどうにもできない世界の話だ。

ただ、openURI()には引数として、そのURIを新規ウィンドウで開こうとしたスクリプトが実行されているウィンドウが渡される。なので、そのウィンドウのdocument.documentElementに属性が設定されているかどうかを見て、タブを開く代わりにブラウズ領域を分割するようにはできた。

……というのが、今回の仕様に落ち着くまでの経緯。なんだかとっても遠回りをした気がする。

分類:Mozilla > XUL, , , , , , 時刻:03:43 | Comments/Trackbacks (3) | Edit

Comments/Trackbacks

ユーザーが発生させたイベントの受け取り

一般の Web ページのような「信頼されていない」コード上で作成、発生させたイベントは「信頼されていないイベント (untrusted events)」と呼ばれ、そのままでは chrome 領域で受け取れません。chrome 領域でこれらのイベントを受け取るためには、addEventListener メソッドの第 4 引数 wantsUntrusted に true を指定する必要があります。
http://lxr.mozilla.org/seamonkey/source/dom/public/idl/events/nsIDOMNSEventTarget.idl

ただし、ユーザー側で追加した独自プロパティはそのままでは参照できないようなので、何か付加情報を受け取りたいというときは、UIEvent の detail プロパティを使うなどしないといけないかもしれません。

(なぜかコメントが反映されないなと思ってたら、外相の名前を入れてました orz...)

Commented by nanto_vi at 2007/05/19 (Sat) 03:31:40

分割メニュー

便利に使わせていただいてます。
0.4.2007051501での分割メニューですが、
「すべてのタブを横に並べる」と「〓を縦に並べる」のラベルが逆になっているようです。

内部的には「横/縦に区切る」動作のようなので、「並べる」場合はラベルが逆のほうが正しいと思います。
(動作結果がメニューのアイコンと違う)

Commented by mar at 2007/05/19 (Sat) 09:49:25

no title

>nanto_viさん
こんな独自拡張があったとは!!
というわけで早速使ってみました。
ただ、URI文字列を渡す事ができそうなイベントがMutationEventくらいしかなかったので、他のイベントを引数に取れるXULCommandEventを使うことにしました。
荒技も荒技だわ……

>marさん
何度も他の人から英語で指摘を受けていながらどこが悪いのかさっぱり分からなくて放置していたけれどもさすがに日本語で指摘がくるということは勘違いではなくマジなんだろう、と思ってよくよくコードを見直してみたら、水平方向かどうかの判断で逆の判定をしてしまっていました orz
ラベルもIDも引数も全部合ってるのに肝心のメソッドそのものが腐っていた、というオチでした……

Commented by Piro at 2007/05/21 (Mon) 01:11:49

TrackBack ping me at


の末尾に2014年1月19日時点の日本の首相のファミリーネーム(ローマ字で回答)を繋げて下さい。例えば「noda」なら、「2007-05-16_splitbrowser-api.trackbacknoda」です。これは機械的なトラックバックスパムを防止するための措置です。

Post a comment

writeback message: Ready to post a comment.

2014年1月19日時点の日本の首相のファミリーネーム(ひらがなで回答)

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のつぶやき

オススメ

Mozilla Firefox ブラウザ無料ダウンロード