宣伝。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。 以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能!
分割ブラウザに、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
に属性が設定されているかどうかを見て、タブを開く代わりにブラウズ領域を分割するようにはできた。
……というのが、今回の仕様に落ち着くまでの経緯。なんだかとっても遠回りをした気がする。
一般の Web ページのような「信頼されていない」コード上で作成、発生させたイベントは「信頼されていないイベント (untrusted events)」と呼ばれ、そのままでは chrome 領域で受け取れません。chrome 領域でこれらのイベントを受け取るためには、addEventListener メソッドの第 4 引数 wantsUntrusted に true を指定する必要があります。
http://lxr.mozilla.org/seamonkey/source/dom/public/idl/events/nsIDOMNSEventTarget.idl
ただし、ユーザー側で追加した独自プロパティはそのままでは参照できないようなので、何か付加情報を受け取りたいというときは、UIEvent の detail プロパティを使うなどしないといけないかもしれません。
(なぜかコメントが反映されないなと思ってたら、外相の名前を入れてました orz...)
便利に使わせていただいてます。
0.4.2007051501での分割メニューですが、
「すべてのタブを横に並べる」と「〓を縦に並べる」のラベルが逆になっているようです。
内部的には「横/縦に区切る」動作のようなので、「並べる」場合はラベルが逆のほうが正しいと思います。
(動作結果がメニューのアイコンと違う)
>nanto_viさん
こんな独自拡張があったとは!!
というわけで早速使ってみました。
ただ、URI文字列を渡す事ができそうなイベントがMutationEventくらいしかなかったので、他のイベントを引数に取れるXULCommandEventを使うことにしました。
荒技も荒技だわ……
>marさん
何度も他の人から英語で指摘を受けていながらどこが悪いのかさっぱり分からなくて放置していたけれどもさすがに日本語で指摘がくるということは勘違いではなくマジなんだろう、と思ってよくよくコードを見直してみたら、水平方向かどうかの判断で逆の判定をしてしまっていました orz
ラベルもIDも引数も全部合ってるのに肝心のメソッドそのものが腐っていた、というオチでした……
の末尾に2020年11月30日時点の日本の首相のファミリーネーム(ローマ字で回答)を繋げて下さい。例えば「noda」なら、「2007-05-16_splitbrowser-api.trackbacknoda」です。これは機械的なトラックバックスパムを防止するための措置です。
writeback message: Ready to post a comment.