たまに18歳未満の人や心臓の弱い人にはお勧めできない情報が含まれることもあるかもしれない、甘くなくて酸っぱくてしょっぱいチラシの裏。RSSによる簡単な更新情報を利用したりすると、ハッピーになるかも知れませんしそうでないかも知れません。
の動向はもえじら組ブログで。
宣伝。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。
以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能!
ツリー型タブの最近の改善でやったことをまた地味に解説するよ。誰得な記事。
ツリー型タブには、「ブックマークからタブを複数開いた時に1つのツリーになってた方がいいけど、でもツリーにするには親になるタブが必要で、だからといって同列のブックマークの中で1つだけが親になるのってなんか違和感あるよね」という場面のための「グループ化専用のダミーのタブ」を開く機能がある。というか、about:treestyletab-group
というURIを読み込んだタブはそういう用途のタブとして扱うようになる。そのときタブの内容が空っぽだと味気ないので、そのタブ配下のタブのツリーをタブの内容として表示するようになっている。
それとはまた別の話で、ツリーになっているタブの上でしばらく待つとそのタブ1つだけじゃなくて配下タブの名前も一緒にツリー表示して、さらにもう少し待つとそれらがリンクに切り替わってクリックしたらそのタブに切り替えられる、という機能もある。
見た目で分かるかもだけど、これらのツリーを生成する部分は共通のpseudoTreeBuilder(疑似ツリー)というモジュールになってる。
この疑似ツリーは、ちょっと前までのバージョンでは、タブの数が多くなるとそのままツリーが下に伸びていって、ウィンドウやツールチップの高さに収まらなくなった分はスクロールして見るという仕様になってた。 元々、おまけの機能だからそれほど作り込む必要性も感じてなかったんだけど、未処理のissueがたくさん溜まってたのを断捨離してたらその中に「このツリーをマルチカラム表示して欲しい」という要望があった事に気がついた。
このエントリを書くにあたって改めて調べ直してたら、別のもっと古いissueでは否定的なことを自分で言ってたみたいなんだけど、実際自分で使ってて「長いタイトルが折り返されるという事もなく巨大なツールチップが画面を覆い尽くして、そのくせちびちびスクロールしないと全項目は確認できない」という状況に意外とイライラしていたため、この機会に「じゃあやってみっか」と手を着けてみた。
で、最終的にはどうにかそれらしくマルチカラム表示できるようなった。
基本的にはCSSのマルチカラム機能を使ってるんだけど、ツールチップの方で僕の意図したとおりの結果を得るためにはちょっと工夫が必要だった。
「ツールチップの方で」と限定したのは、後で分かったんだけど、タブの中に表示する方はそこまで苦労しなくても勝手にいい感じにGeckoがレンダリングしてくれるから。 なので先にそっちの方から書いていきます。
先に要件を整理しよう。
まずコンテナとして、コンテンツ領域いっぱいに広がるボックスを置いておく。
コンテナには、内容が溢れたらスクロールできるようにoverflow:auto
も指定しておく。
#tree {
overflow: auto;
box-flex: 1;
-moz-box-flex: 1;
}
で、この中に置くツリーをマルチカラムにしたいわけなんだけど。
CSSのマルチカラム表示を有効にするだけなら、マルチカラムにしたい内容を含む上位の要素に列の数か幅を指定してやればいい。
2列なら、こう。この場合、列の幅はコンテナの半分になる(自動的に決定される)。
#tree > .treestyletab-pseudo-tree-root {
-moz-column-count: 2;
/* -moz-columns: 2 auto; と同等 */
}
列幅固定なら、こう。この場合、コンテナの中に1列しか収まらない時はマルチカラムにならないという、いわゆるレスポンシブデザイン的な挙動になる。
#tree > .treestyletab-pseudo-tree-root {
-moz-column-width: 20em;
/* -moz-columns: auto 20em; と同等 */
}
列数固定だとウィンドウの幅が広いときに余白ばかり広がってしまってあまり嬉しくないので、ツリー型タブではとりあえず主観で20em
と指定してみた。
自分の使ってる環境では、これでだいたい2~3列になる。
マルチカラム表示したいツリーを構成しているXUL要素の中で、内容が複数列に泣き別れてもいい物(=「1つのタブ」に対応する「アイコンとラベル文字列のペア」以外のすべてのボックス)は明示的にdisplay:block
にしないといけない。
display:-moz-box
のままだと、要素の作るボックスは途中でぶった切られる事が無いので、マルチカラム表示にはならない。
/* required to apply CSS multi columns */
#tree > .treestyletab-pseudo-tree-root,
#tree > .treestyletab-pseudo-tree-root vbox {
display: block;
}
当初はこれに気付いてなくて、わざわざXHTMLとXULを混ぜて実装してた。
でも、後になってからdisplay
の値を変えればXUL要素でも問題ない事が分かったので、今は全部XULに戻してある。
しかし、これだけだと項目の数が多い時に「縦に長いツリーがマルチカラムで表示される」「画面に収まらなかった部分は下にスクロールしないと見えない」ということになる。
こういうのは一覧性が悪くて死ねる。 だって、左の列を上から順に下まで見た後、次の項目を見るにはまた一番上までスクロールし直さなきゃいけないんですよ? あり得ないでしょ……
つまり、各列がコンテンツ領域の高さより高くなられると困る。 項目の数が多いときは、「縦に長ーいリストを2列で表示する」んじゃなくて、「コンテンツ領域の高さに収まる短いリストを3列、4列と列を増やして表示させる」方がいい。 ということ。
じゃあってんでさっきの要素に最大の高さを100%
と指定してみても、これは効果がなかった。相変わらず、親のボックスの大きさを超えてスクロール可能なまま。
#tree > .treestyletab-pseudo-tree-root {
-moz-columns: auto 20em;
height: 100%;
}
なので、resize
イベントでコンテナの高さを調べて、その都度ピクセル値で適切な高さを指定するようにしてみたら、ようやく縦のスクロールバーが消えて横方向にスクロールできるようになった。
...
this.window.addEventListener('resize', this, false);
...
handleEvent : function GT_handleEvent(aEvent)
{
switch (aEvent.type)
{
...
case 'resize':
return this.onResize();
...
}
},
...
onResize : function GT_onResize()
{
...
var container = this.document.getElementById('tree');
var tree = container.firstChild;
PseudoTreeBuilder.columnizeTree(tree); // ここでcontainerの高さをtreeのheightにピクセル値で指定し直す。
},
CSSのマルチカラムでは「列の数」の指定は絶対ではなくて、コンテナの幅と高さから溢れた分の内容は自動的に列の数を増やして表示するようになってる。
コンテナがoverflow:auto
になっていれば、溢れた分は横スクロールすれば見える。
全体の高さを指定していても、項目の数が「全部1列で表示するには多いが、2列を埋めるには足りない」程度の時には、領域の下の方に妙に余白が出てしまう。
これは-moz-column-fill:balance
という初期値のせい。この指定の時には、各列の内容の高さがなるべく揃うようにレイアウトされるため、結果として下の方に余白が産まれることになる。
まぁそれはそんなに悪くはないんだけど、今までコンテンツ領域の高さいっぱいまで並んでた物が急にその半分とかくらいの高さになるのは気持ち悪い。 違和感が無いのは、やはり、領域の高さに収まらなくなった分からちょっとずつ次のカラムに流し込まれていくという感じだろう。
そのための指定が-moz-column-fill:auto
で、これを指定しておくと、1列目は下まで項目が埋まって、入りきらなかった分だけが2列目に溢れるようになる。
実は、この-moz-column-fill:auto
を使うのにも、ボックス全体の高さを明示的に制限しておく必要がある。
というのも、-moz-column-fill:auto
の時は「高さが指定の高さに収まらなかったときに、その分を次のカラムに流す」という事になるので、高さが未指定だと「内容が溢れることもないからいつまで経ってもマルチカラムにはならず、縦にどんどんリストが伸びていく」という結果になってしまう。
……というわけなので、やっぱり全体の高さはスクリプトで動的にピクセル値で指定してやらないといけないのでした。
こちらも要件を整理する。
ここで曲者なのが3つ目の要件。 コンテンツ領域の中であれば「与えられた領域の中を最大限使って、残りは余白扱いにすればいい」ということになるんだけど、ツールチップだとそうもいかない。 というか、必要最小限のサイズで出てくれないと困る。 「内容を表示するのに必要な最小の大きさをどうやって決めるのか?」 これがツールチップの場合の難しい所だ。
先に結論を言ってしまうと、「とりあえず許されてる最大の大きさで試しにレンダリングしてみて、その後、実際に必要な大きさで改めて表示し直す」というのが答えになる。
とはいうものの、ツールチップを1回表示した後そこから小さく縮めるというのは見た目が宜しくない(一瞬だけとはいえ目に見える状態で大きなツールチップが出るというのはイラつきますよね)。
じゃあどうすれば?という事になるんだけど、逆転の発想というかなんというか、ツリー型タブでは「そもそも最初からベストのサイズで表示する事は諦める」という解決策をとっている。 どういう事かというと、いきなり違うサイズのツールチップを出すとギャップで見当識を失うので、まずは元の普通のツールチップと同じ大きさ・位置で1回表示して、そこからアニメーションでツールチップを必要な大きさまで拡大する、という事をしてる。
ツリー型タブの高機能なツールチップはだいたい元のツールチップよりは大きくなるので、この「1回小さめのサイズで表示した」状態で必要なサイズを確定させて、後からゆっくり拡大すればいい。
元より小さなツールチップで何故「最大の大きさで試しにレンダリングしてみる」ができるのかというと、XULのarrowscrollbox要素を使ってるから。 これは元々は、ツールチップが画面いっぱいに広がっていてもまだ内容が収まりきらない時のための対策として使っていた。 arrowscrollboxは中にどんなに大きな物を置いてもそれ自体やその親(ツールチップ)の大きさが広がらないので、安心して「めいっぱい大きく表示して、最小限必要なサイズをその結果から割り出す」ということができる。
「幅も高さもいい感じにする」というのは難しいので、ツリー型タブの場合はまず「画面の全体を覆い尽くさない程度」ということで画面の高さの70%(例えば画面が縦1024ピクセルなら、その7割の717ピクセル)を最大の高さとして、その中でマルチカラム表示の指定を反映させている。
arrowscrollbox > .treestyletab-pseudo-tree-root {
-moz-columns: auto 20em;
-moz-column-fill: auto;
height: 717px; /* ←実際にはその都度計算する */
max-height: 717px; /* ←実際にはその都度計算する */
}
こうすると、高さについては指定の高さまでに収まって、幅は必要な分だけ自動的に列が増えていくという形で、ツリー全体を収めるのに必要な領域を確定する事ができる。
高さは既に分かっているので、残るは幅なんだけど、これはツリー自体のboxObject.width
やclientWidth
からは分からない。
というのも、この時点でのマルチカラム表示されたツリーは「列の幅は指定されているが列の数は指定されていないので、要素自身の幅を超えて列が表示されている(可能性がある)」という状態で、要素自体の幅を調べても意味がないのです。
overflow:auto
になってる要素の幅を計測しても中身の幅は分からない、というのと同じね。
こういう時の「本来の内容の幅」は、RangeのgetBoundingClientRect()
で調べられる。
これは、DOMのRangeが含んでいる範囲の全要素が収まる矩形の位置や大きさを計測してくれるという便利なAPI。
これを使ってツリーの要素の「内容を」選択してそのサイズを測れば、ツリー全体を収めるのに本当に必要な最小のサイズが分かる。
var range = tree.ownerDocument.createRange();
range.selectNodeContents(tree);
var rect = range.getBoundingClientRect();
range.detach();
あとは、ツールチップ全体を広げるだけ。 「ツリー全体を収めるのに必要な幅」と「画面の幅さの80%(例えば画面が横1280ピクセルなら、その8割の1024ピクセル)」のどちらか小さい方をツールチップの新しい幅にしてやる。 ツリーはツールチップの中のarrowscrollbox要素の中に置かれているので、ツールチップがツリーよりも小さければ、はみ出た部分はスクロールして見る事ができる。
以上、マルチカラムなポップアップをいい感じに表示するためのノウハウの話でした。
実は、ここに書いた内容はmasterのHEADでの話で、解説を書くにあたって調べ直した結果の洗練された内容になってる。 今リリースしてるバージョンでは、そこまで洗練されてない状態の(でもだいたい同じような結果を得られている)コードになってるので、どこが無駄だったのかを洗い出して「こいつ技術力低いなあ!」と笑いものにしてくれていいです。
それにしても、昔なつかしNetscape Communicator 4では、フォルダの中にブックマークが大量にあるときはこんな風に段組表示してくれて一覧性が高くてものすごく便利だったんだけど、Geckoエンジンベースで作り直されたNetscape 6以降や、その流れの先にあるFirefoxには、その機能はついぞ引き継がれなかった。 業を煮やして複数のポップアップを並べることで擬似的に再現できないか?という実験をしてみたこともあったんだけど、不安定でダメだった。
今だったら、このやり方で行けるんじゃないか?という気がする。 というか、SUMOの質問に寄せられてる回答でStylish用のスタイルシートが公開されてて、2つの例のうち1つはCSSマルチカラムでやるようになってたので、間違いなくできる。
ただ、例に挙がってるStylish用のスタイルシートはカラム数が固定されていて、1列でいい時にまで常に2列3列になってしまうという問題がある。 ネスケ4の頃のそれのような使い勝手を実現するには、ここで解説したような細かい調整をやらないといけないんだと思う。 僕自身はやる元気がないので、誰か代わりにやってくれないかなあ……と、実現する見込みの低そうな事をネットの片隅でこっそり呟いてみる次第です。
ツリー型タブではタブバーに表示するスクロールバーについて、普通のスクロールバーよりも細く表示するようにしてるんだけど、その実装方法に少し改善があったので誰得だけど解説しておく。
ちょっと前までのバージョンでは、単純にCSSのmax-width
で以下のように実現していた。
tabs.tabbrowser-tabs
.tabbrowser-arrowscrollbox
> scrollbox
> scrollbar[orient="vertical"],
tabs.tabbrowser-tabs
.tabbrowser-arrowscrollbox
> scrollbox
> scrollbar[orient="vertical"] * {
max-width: 10px;
min-width: 10px; /* この指定がないと逆に最小サイズが大きくなってしまう */
}
tabs.tabbrowser-tabs
.tabbrowser-arrowscrollbox
> scrollbox
> scrollbar[orient="vertical"] {
font-size: 10px;
}
この方法の難点は、一部のプラットフォームで……というかWindowsでスクロールバーの端のボタンの表示がずれるということ。
スクリーンショットを見ると、「▼」がちょっと右にずれてるのが分かる。
何故こうなるかというと、Windowsのスクロールバーの端のボタンのアイコンは最小サイズが大きめに定義されているようで、それよりも小さなサイズを指定してもWindows側の最小サイズが優先されてしまうせい。
この問題は、実用上は問題がないので長らく放置してたんだけど、最近ツリー型タブのissue trackerで閉じられてないままの古いissueを断捨離してる時にもっとこうしたらいいよという提案があったことに今頃気がついて、その方針を最近のバージョンで採用してみた。
これはどうやってるのかというと、スクロールバーの幅を小さくする代わりに、「スクロールバーの左右にマイナスのマージンを設定して他の要素の下に潜り込ませる」ことで、擬似的に細く見せている。
何ピクセル潜り込ませるかは環境によって変わってくるので、document.getComputedStyle()
なども使ってその都度計算するという面倒なことをしている。
これで、「▼」がずれるということがなくなった。
しかし、今度は副作用としてタブバーの背景色を変えている時に表示が変になるという問題が起こってしまった。
例えばClassic Theme Restorerをインストールして且つ「Mixed」スキンを選択した状態だと、水色の背景の一部がグレーになってしまってた。
これは、先の「マイナスのマージンを設定して他の要素の下に潜り込ませる」という手法において、スクロールバーが潜り込む先となる(スクロールバーの上に載って一部を覆い隠す)ボックスの背景色の指定が必要となってしまって、決め打ちで指定した色がユーザのカスタマイズ後の色と違うせいで見えてしまっているということ。
タブバーの背景色を変える方法はuserChrome.cssやらテーマやらClassic Theme Restorerやら色々とあるので、すべての場合にマッチする万能の対策は事実上無い。
ということで頭抱えてしまって、なんとかスクロールバーの潜り込んだ部分(はみ出た部分)を綺麗に消す方法はないかと、思いついた方法を色々試してみた。
max-width
でちゃんと細くできてたんだし)と思って試してみたら、ボタン部分だけがスクロールバーからはみ出すという結果になってしまった。
overflow-x:hidden
だな!と思って、スクロールバー全体にこれを指定してはみ出したボタンだけをどうにかしようと思ったけど、実際やってみたらスクロールバー全体の動作がぶっ壊れてしまうので駄目だった。
万策尽きてDOMインスペクタの画面とにらめっこしてた所、clip
という名前が見えた。そういえばCSSにはそういう機能もあるんだった。試したこと無かったから、じゃあそれで行けるんじゃないか?
ということで実際試してみたんだけど、これもスクロールバーのボタンには効いてくれなかった。
でも、MDNのプロパティ解説を見るとdeprecatedと書いてあって、誘導先を見たらclip-pathを使えと書いてある。
clip-path
というとFirefoxのタブの見た目などを丸くするのに実際使われてるプロパティだったはずなので、こっちなら大丈夫だろうと思って再挑戦したら、ようやくうまくいった。
Classic Theme Restorerとの併用時にも何ら問題がないことが見て取れる。
実装は以下のようになってる。
tabs.tabbrowser-tabs
.tabbrowser-arrowscrollbox
> scrollbox
> scrollbar[orient="vertical"] {
font-size: 10px;
max-width: 10px;
min-width: 10px;
clip-path: url(#treestyletab-box-clip-path);
}
tabs.tabbrowser-tabs
.tabbrowser-arrowscrollbox
> scrollbox
> scrollbar[orient="vertical"] * {
font-size: 10px;
max-width: 100%;
min-width: 10px;
}
tabs.tabbrowser-tabs
.tabbrowser-arrowscrollbox
> scrollbox
> scrollbar[orient="vertical"] scrollbarbutton {
font-size: 10px;
margin-left: -3px;
margin-right: -2px;
}
参照してるSVGのクリッピングパスは以下の通り。
<svg:svg height="0">
<svg:clipPath id="treestyletab-box-clip-path"
clipPathUnits="objectBoundingBox">
<svg:path d="m0,0 V1 H1 V-1 H-1 z"/>
</svg:clipPath>
</svg:svg>
このクリッピングパスはどういう形かというと、仮想的なキャンバス全体を覆い尽くす矩形になってる。m
から始まる相対指定で(0,0)
から(1,1)
までを覆う矩形を作っている(左上から始めて、下、右、上、左と反時計回りに進んでパスを閉じてる。最初は逆方向の時計回りに回ってしまってうまくいかなかった)ので、クリッピングパスの適用対象になるボックスがどんなサイズであってもそれと同じ大きさになる。
スクロールバーに対してこのクリッピングパスを反映すると、この矩形からはみ出る部分、つまりネガティブマージンではみ出してるボタンが切り取られて表示されるようになる、というわけ。
今回の実装自体のノウハウをそのまま流用できる場面はそうそうなさそうだけど、なんかの機会にまた使うかもしれないので、解説してみた。
要点をまとめると、「要素のスクロールの可否といった動作に影響を与えないで、見た目の表示サイズだけを小さくしたい時は、clip-path
を使うとよい」といったところでしょうか。
以上、ちっこい三角ひとつのためだけに四苦八苦させられた話なのでした。
De-coupling Reviews from Signing Unlisted Add-ons | Mozilla Add-ons Blogの私的な翻訳です。
長いので3行で説明 – 今週中(2015年12月4日)までに、私達は非公開のアドオンに対する署名を完全に自動化し、人力レビューを発生させないようにすることを考えています。
ここ数日、アドオンの署名手続きの最初のステップについての議論がありました。「バリデータ(検証器)」として知られる一連のコードによる、アドオン登録時の機械的レビューの改善についてです。バリデータは登録されるアドオンについて様々な理由から人力のレビューを喚起し、署名手続きを中断させます。これはアドオンのリリースを遅らせることに繋がります。なぜなら、署名を要求するという要件がFirefox 43以降のバージョンでは強制されるからです。
過去には、バリデータの有用性について議論が持ち上がったこともありました。悪意ある開発者であればバリデータによる検証を回避するコードを書くことができるからです。私達は、バリデータのできることには限界があることを承知しています。現実には、あくまで既知の危険なコードに付いてしか検出できず、それでは対応できない未知の危険なコードはたくさんあります。しかし、バリデータはレビューの過程の1要素に過ぎず、私達は開発者がアドオンをより提供しやすく、それを使う人達がより安全になるようにしたいと願っています。私達はバリデータについて、完全なマルウェア検出機構として動作することを意図しておらず、むしろ、Firefoxユーザにより適切な形でアドオンを届けられるように開発者を手助けすることを意図しています。
このことを考慮して、私達は非公開のアドオンに対する関門としてのバリデーションを取り除こうとしています。私達は開発者が非公開のアドオンを提供しやすいようにしたいと考えており、従ってレビューは署名手続きとは独立して行っていくことになります。今週末(2015年12月4日)、私達は非公開のアドオンに対する署名を完全に自動化し、人力レビューを発生させないようにすることを考えています。この日付は不確定な物で、これを可能にするために必要な技術的・手続き的・ポリシー的な変更を我々がどれだけ早くできるかに依ります。今月の初めに導入されたアドオンの署名APIは、署名手続きの完全な自動化が可能となり、この件についての解決策の一部となるでしょう。
私達は、アドオン開発者の方々には引き続き、MDNで概説されているFirefoxアドオンのポリシーへの同意を求め、署名のための登録に先立ってそれらのポリシーに自身のアドオンが違反していないかを確認することをお願いしていきます。開発者の方々はアドオンのレビュアー向けガイド(アドオンがレビューを通過しなかったりブロックリストに入れられてしまったりする主な理由を概説しています)の内容も把握するようにして下さい。
私は先週を通じて得られたそれらの情報と洞察をもたらしてくれたすべての人に感謝しています。私達はアドオン開発者やユーザの方々にとってFirefox上での体験を可能な限り痛みを伴わない物にしていきたいと思っています。また、「生き辛い」やり方であるように思われる場合があったとしても、そのような生き辛さは、私達の目標には絶対に含まれません。どうか、私や他のチームメンバーに直接、気軽に意見を言い続けて下さい。
私はそれらを可能にするための次のステップのより具体的な概要を投稿するつもりで、その進捗はbug 1229197で見ることができます。前もって、あなたの我慢強さに感謝します。
kev(訳注:Kev Needham、Mozilla Corporationの雇用スタッフ。)
ということなのですが、これはあくまで非公開(unlisted)のアドオンに限定した話のようで、公開(listed)のアドオンについてはこの限りではない模様です。実際、先日新バージョンを公開しようとした公開のアドオンでは人力レビューを経なければ署名は得られませんでした。
このエントリ中では触れられていませんが、1229197 – Allow unlisted add-ons to be signed without passing the validatorでは「非公開アドオンなのであればサイドローディングの可否に依らず署名手続きにレビューが不要なようにする」という話になっているようで、実際に行われた変更でも確かにそのようになっています。
なお、このエントリでは、「アドオンが人力レビューを通過できないのでいつまで経っても署名を得ることができず、テストも配布もできない」という状況が発生していた事について、「人力レビューの通過を署名の必須要件に含めなくした」という事が述べられていますが、その後の人力レビュー自体については言及されていません。 なので、Mozillaのポリシー的に許容され得ない危険なアドオン(例えば、リンク先のローカルファイルのショートカットを自動で開くような物)については、仮にバリデータ(Linterに名前が変わったようですが)での機械的チェックを通過して署名を得られたとしても、その後のエディターによる判断で「これはマルウェア的だからやっぱりブロックリストに入れよう」とされてしまう可能性は依然としてある、と思っておいた方が良さそう……というのが今のところの自分の認識です。
ちなみに、第一報からだいぶ時間が過ぎた今頃になって何で訳してるの? と思われそうですが、それまでは「マルウェアなどの危ないアドオンを排除したいから署名義務化します、危険なアドオンはレビューで弾くから安全です」と説明されていたのが、ここに来ての「機械的チェックで問題無ければ原則署名します、危険なアドオンでもレビュー無しで署名します」への方針転換だったので、そりゃちゃぶ台返しすぎないか?!と驚いて話を鵜呑みにできずにいたからです。
しかし実際に読んでみた限りでは、確かに非公開のアドオンについては署名を完全に自動で得られるようになったものの、その後の人力レビューで弾かれる可能性は否定されていませんでした。「先に全部閉め出しておいて安全な物だけ通す」から「先に全部通しておいて危険な物だけ潰す」への方針転換だったという事になるので、タイミングはずれはするものの危険な物はやはり許容されず、一般ユーザとしては安心して使えて、開発者は依然としてレビューを通過できないことの恐怖に怯えなくてはならないという、大枠の所は変わらないようでした。やれやれ。
具体的にアドオンを作る・使う側の人間はどう対処すれば良いのか、というのを自分の理解でまとめてみる。判断のソースは原文のコメント欄での質問と回答で示されている情報です。
現在AMOでのアドオンの公開に際してはPreliminary ReviewとFull Reviewの2段階のレビューがあり、Preliminary Reviewを通過できればサイト上に掲載され、その上でさらにFull Reviewを通過できれば検索結果にヒットしたり一覧に表示されたりするようになる、という感じなんだけど、Preliminary Reviewではセキュリティ上の重大な脅威が無いならとりあえずは通過できる事が多い。しかし、Firefoxのセキュリティ機構をバイパスするためのアドオン、例えばThunderbirdでメールに添付されたWindowsショートカットを直接実行できるようにするアドオンのような物は、どれだけ多くのユーザが切望していても、例え顧客企業で必要とされていても、レビューを通過できない。今回の件の記事のコメント欄でも、署名チェック機構をバイパスするようなアドオンは審査を通過できない(=XPIに署名して貰えない=インストールは許可されない)という事が明言されている。
「公表できない物」っていうのは、例えばクリティカルな情報を含んでいるとか、組織内利用専用とか、そういうこと。なぜ公表できるかどうかが焦点になるのかというと、AMOのサイト上で一般向けに公開されないとしても、インターネット上のサービスにパスワードもかけずにファイルをアップロードし、どこの誰かも分からないボランティアのスタッフに自由にソースコードを見られる、という事を許容できるかどうかという話になるから。
企業などの組織内で使うためのアドオンについては「第3の選択肢」を用意するという事になっているようだけれども、具体的な詳細が公表されていないので、現状では最悪のケースも想定しておいた方がいいんじゃないかって気がする。例えば「特別なパートナーシップ契約を結んで、非公開でレビューを受けられるようにする」みたいな話だったとして、Mozillaにとって特別なパートナーシップ契約を結ぶだけのメリットを感じられない規模の組織は、詰んでしまうことになるので。
正道はやはり、クリティカルな情報を含まなくていい形で公開できるアドオンとして開発しておき、クリティカルな情報はMCDなり何なりで後から反映できるようにしておく、という事だとは思うんですけどね。
率直な感想としては、「ウチの製品をユーザがどう使えるかはウチが決めますよ、使い手のあなたたちに使い方を決める権利はありませんよ」「ウチの製品の上で使いたいならそれなりの質の物じゃないと許しませんよ」って言ってるような印象で、tivoizationと似た感じのニオイを感じられてまったくウンザリする話だ、って感じではあります(現状でも、Firefox OS向けのアプリは既にそうだったと記憶してる)。ある程度普及して、「Mozillaという組織の名前を冠した信頼と実績のFirefoxというブランド」が一定の価値を持ち、自分がやろうとしている事のリスクもよくわからないままに致命的な操作をしてしまいかねない層のユーザの数が無視できないレベルに達しており、そしてそれを狙った悪質な攻撃が増加している、という前提に基づくと、やむを得ない判断だと理解はできるんですが。だから怨むべきは、Mozillaではなく、面白半分だったり悪意だったりで人に迷惑かけてる黒アドオン作者の方。
まあ、Firefoxの名前とブランドロゴを外したビルドを使う分には関知しないという抜け道は残してくれているようなので、そこがMozillaの良心だと思ってます。
Firefoxのマルチプロセス設計への移行がいよいよ目前に迫っている。
Firefoxにおけるマルチプロセス化のための仕組みそのものはElectrolysis、略してe10sと呼ばれており、Firefox 4の頃から既に入っていて、Firefox Hacks Rebootedでも詳しく解説してたんだけど、ブラウザのUIを動かすプロセスとコンテンツ領域のプロセスを分けるというのはFirefoxではかなりの大ごとだった。一時は「こんなん無理!」っつって計画が凍結されてたほどだったと記憶してる。
e10s移行が困難だった理由は、多分、Firefoxというアプリケーションそのものの設計にあったのだと思う。FirefoxというWebブラウザは、「GeckoというHTML・XMLレンダリングエンジンの上で動作するJavaScript製のローカルWebアプリケーション」といった感じの設計になっている。なのでコンテンツ領域内の操作のためのコードとUI部分の操作のためのコードが非常に似通っていて、シームレスに連携しやすかった、否、「連携しやすすぎた」と言える。あまりにシームレスに連携できたせいで、ブラウザのUIに関わるコードとコンテンツ領域内の操作に関わるコードが渾然一体の密結合になってしまい、それが「UI部分とコンテンツ領域内との間はテキストメッセージだけを非同期に通信しあう」というe10sベースの設計への移行を阻んでいた、という事なのではないか……と僕は思っている。
どういう理由があったのかは知らないけど、最近のバージョンのFirefoxではe10sベースの設計への本格的な以降のための準備が着々と進められている。上記のような密結合だった部分が「UI領域専用」「コンテンツ領域専用」「両方で共通」といった感じに分離されてきているし、同期処理前提だった部分が非同期処理前提に改められている。 セッション保存の仕組み(ページ内のテキストボックスへの入力内容を保存する所とか)、リンクのクリック操作のハンドリング、その他多数の部分が大幅に書き直されている。アドオンから見た時のAPI的な互換性は可能な限り残すようにしてあるようで、その努力の様子が非常に興味深い。
で、アドオン側での対応をどう進めるかなんだけど、実際にいくつかのアドオンをe10s対応に改修してみて、アドオンの性質によって典型的なパターンがあるようだという事が分かった。
browser
のcontentWindow
やcontentDocument
に一切触れず、コンテンツ領域内からBubblingしてくるイベントも捕捉しないタイプのアドオンは、何も考えなくてもそのままe10sで動く。var linkURIs = Array.map(gBrowser.contentDocument.links, function(aLink) { return aLink.href; });
と書けたけれども、こういう事ができなくなる。
UI領域とコンテンツ領域の境界をまたぐ時に非同期処理を挟まないといけないので、処理を「UI領域からコンテンツ領域へ、リンクを収集する指示のメッセージを送る」「コンテンツ領域で指示のメッセージを受け取って、リンクを収集し、UI領域へ結果を報告するメッセージを送る」「UI領域で報告のメッセージを受け取って、次の処理を行う」という3つの段階に分けなくてはならない。
マルチプルタブハンドラの場合、「選択したタブの情報をクリップボードにコピーする」という機能のために、タブ(で開いているページ)の情報からクリップボードにコピーするための文字列を得る処理をコンテンツ領域側に移動した上で、UI領域からコンテンツ領域へ・コンテンツ領域からUI領域への橋渡しを行うためのコードを追加し、前後の処理をPromiseで繋ぐようにした。上記の5パターンの最初の方の物ほど実装が容易で、後の方の物ほど実装が面倒になる(その上、メッセージの往復を待たないといけないのでオーバーヘッドも大きくなる)。 特に深い意味もなく後の方のパターンで実装していた機能は、どうにかして前の方のパターンで実装できないか検討した方がいい(Firefox本体の設計変更も、おそらくそういう風に進められたのではないかと思う)。 実際に、情報化タブではWebページのサムネイル画像を取得する処理について、元々はUI領域で「サムネイルが必要だ」となったタイミングでその都度同期処理していたのだけれども、まずサムネイル取得の処理はコンテンツ領域に移し、処理が走るタイミングについて、コンテンツ領域側で発生したイベントをトリガーとしてサムネイル画像をUI領域側にpushで送りつけるように改めた。 これは上のリストで言うと、5番目のパターンから4番目のパターンに設計変更した、ということになる。
それでもどうしても5番目のパターンで実装しないといけないケースというのはあって、前後の処理とどうやって繋ぐか(同期処理だった物をどう非同期化するか)というのが問題になる。 自分の場合は、こういう時はPromiseを使うのがいいと思ってる(以前ならJSDeferredを使ってたんだけど、Mozilla Add-onsのレビューが通らないため、最近になってPromise.jsmのES6 Promise互換APIを使うようになった)。 ツリー型タブでも、コンテンツ領域内にプラグイン(Flashなど)で描画されている領域があるかどうかを調べるための処理で、このパターンが残っている。 Promiseを使うコードはUI領域側のブリッジにまとめてあり、こんな感じになってる。
sendAsyncCommand : function CB_sendAsyncCommand(aCommandType, aCommandParams)
{
var manager = this.mTab.linkedBrowser.messageManager;
manager.sendAsyncMessage(this.MESSAGE_TYPE, {
command : aCommandType,
params : aCommandParams || {}
});
},
checkPluginAreaExistence : function CB_checkPluginAreaExistence()
{
return new Promise((function(aResolve, aReject) {
var id = Date.now() + '-' + Math.floor(Math.random() * 65000);
this.sendAsyncCommand(this.COMMAND_REQUEST_PLUGIN_AREA_EXISTENCE, {
id : id
});
return this.checkPluginAreaExistenceResolvers[id] = aResolve;
}).bind(this));
},
handleMessage : function CB_handleMessage(aMessage)
{
// dump(JSON.stringify(aMessage.json)+'\n');
switch (aMessage.json.command)
{
...
case this.COMMAND_REPORT_PLUGIN_AREA_EXISTENCE:
var id = aMessage.json.id;
if (id in this.checkPluginAreaExistenceResolvers) {
let resolver = this.checkPluginAreaExistenceResolvers[id];
delete this.checkPluginAreaExistenceResolvers[id];
resolver(aMessage.json.existence);
}
return;
}
},
checkPluginAreaExistence
メソッドは、その実行を示すユニークなidを伴ってコンテンツ領域に指示のメッセージを送ると同時に、新たに生成したPromiseのリゾルバ関数を、idと対応付けて保持する。メソッドの戻り値はPromiseとする。という風にする事で、checkPluginAreaExistence
メソッドをthenableなメソッドとして他の処理の中に無理なく組み込める(次のコールバックには、コンテンツ領域側での処理で得られた結果が渡る)ようになってる。
UI領域→コンテンツ領域→UI領域 と境界を2回以上またぐ処理を実装する時は、多少の差異はあれどだいたいこんな感じになるんじゃないだろうか。
必要かどうかで言うと、このパターンでPromiseは必須ではなくて、Promiseのリゾルバ関数を保持・実行する代わりに、単にcheckPluginAreaExistence
メソッドでコールバック関数を受け取って、それを保持・実行するようにしてもいいんだけど。
非同期の処理同士を何度も書き連ねる時のコールバック地獄は見たくない(今はそういう連携をする必要がないとしても、今後いつ必要になるとも限らない)ので、僕は自分で書く非同期処理は、インターフェースとしては基本的にPromiseを使う方向で統一するように考えてる。
Mozilla Corporationの人から、「なんでツリー型タブはFull Reviewを受けてないんだい? about:addonsからの検索にヒットしないから、ユーザがインストールするのに面倒だよ。You申請しちゃいなよ!(意訳)」的なメールを頂いた。ありがたいことだ。
Mozillaのアドオンポータルサイトである所のMozilla Add-onsでは、アドオンを登録するにあたってPreliminary Review(事前審査)とFull Review(完全審査)という2段階の審査がある。登録したアドオンはまずPreliminary Reviewでセキュリティ面などの大雑把な審査を必ず受けて、通過できなければそのアドオンはAMOへの掲載すらかなわない。ここで問題なしとなれば晴れて「実験的アドオン」としてサイトに掲載されるようになるけど、Firefoxのアドオンマネージャからの検索にはヒットせず、おすすめアドオンとしてもノミネートされないので、これではまだ単に「載っただけ」。そこで一定の支持を得たら、次の段階としてFull Reviewを申請して品質面その他を審査してもらえる。Full Reviewを無事通過すれば、Firefoxのアドオンマネージャからの検索にヒットするようになったり、おすすめとして紹介して貰えたりするようになる。定番アドオンと言われるような物は、代替はこのFull Reviewを通過した状態になってる。
前から見てる人は把握してるかもしれないけど、僕が作ってるアドオンのうちいくつかは、Preliminary Reviewのみ通過していて実験的アドオンのままになっている。新しく作って登録した物は当然なんだけど、それだけでなく、過去にはFull Reviewを通っていた物が、ある時を境に審査にパスしなくなってそれっきりになっている物もある。ツリー型タブもその1つだ。
何故かというと、簡単に言えば、最初のFull Reviewの頃には審査が甘かったから通過できていたのが、その後の審査基準見直しで通らなくなったということ。ただ、僕としてはこの時の裁定にはあまり納得がいってなくて、evalが危険でそれ以外の方法が安全だと思ってる人へ( 英訳)というエントリでタラタラ不満をぶちまけたりもしてた。
そういう経緯があったから、大人げないオッサンとしては「いやーFull Reviewしたいのは山々なんですけどねーeval()
使ってるから駄目っておたくんとこの人達が言うもんですからねー」と嫌味全開で返したくもなったんだけど、そこは我慢して、審査基準に合わないと言われたからFull Reviewしてないんですよ、審査基準が変わったなら再申請するのはやぶさかでないけどそうでないなら多分通過しないと思いますよ、でもまあ確かにeval()
使ってるとレビューしにくいだろうししょうがないっすね、と、そんな感じで返信するに留め……られるほどにはやっぱり大人になりきれておらず、嫌みったらしく上記のエントリ(英語の方)のURIを貼り付けてメール送信してしまいました。ああ、なんとも底の浅い人間である事よ……
でもまあ、その時のレビュワーの人とは無関係であるにせよ、公式サイドの人から「Full Reviewに値する」という評価を貰えた事には「やってやったぜ」という胸のすく思いで、4年越しで溜飲を下げたのでした。
Scrollbar Like Scrollerを更新した。
1.0/1.1での大きな変更点として、仮想的な「つまみ」を導入して、それ以外の場所では反応しないようにした。使い勝手が悪くなったと見る向きもあるかもしれないけど、前の挙動に戻すつもりはないです。
というのも、僕が自分で実際に使ってた感想として、何も無いところでスワイプやパンスクロールしようとして急に画面が飛んでしてしまう(スクロールバー風操作の開始と判断して、指があった位置から計算したスクロール位置まで強制的にスクロールしてしまう)という誤爆が何度かあってイラッときてしまったのです。
スクロール位置を示すインジケーター自体はFirefoxも提供してるんだけど、これは注意深く見ないと気がつかないようなさりげなさで表示されているので、UIとしてこれを目印にするのは辛い。と思ったというのもあって、ぶっとい「つまみ」に相当する物を自前で表示するようにした。これをなるべく正確な位置に表示したくてああだこうだと座標をいじくり回した結果、指のある位置からのスクロール位置の算出が前よりグッと正確になったので、そういう意味でも成果はあったと思う。
もう1つの変更として、画面の上端や左端もスクロールバーとして動作するようにした。右手でスマホを持って親指でスクロールしてる時は右にスクロールバーが出てていいんだけど、左手で持って親指でスクロールしてると、右端に出るつまみまで指が届かなかったので。最後にパンスクロールした時のタッチ位置が画面の1/3より左だったら左につまみが出るようになってるけど、つまみが出てない時でも、つまみがあるであろう位置を指で操作すればスクロール操作は開始できます。
Nexus 7を買って以降、Firefox for Androidをエンドユーザとして使うようになってそれなりに経つんだけど、布団の中でWebブラウズする時間がだんだん長くなってきて(病気で……とかじゃなくて、単にPCの前に座って作業するのが億劫になってきたという事です)、触る時間・頻度が増えてくると、色々細かい所で「イラッ」と来るようになってきた。
アドオンを作れば解決できるんだろうなあと思ってはいたんだけど、既に何十とリポジトリを作っていてメンテナンスしきれてない僕がまた新しく抱え込むのは世界に不幸を増やす事になるのではないか……と思って、「他の誰かがやってくれないかなあ」と淡い期待を抱きながら待ってたんだけど、僕の不満が解消されるような物が出てくる気配が一向になかったので、カッとなった勢いで2つほど作ってAMOに登録してみた。ああ、またつまらぬ物を作ってしまった……
Scrollbar Like Scroller(スクロールバー風スクロール)は、いくつかのAndroidアプリ(具体的にはJota Text Editorとか)で実装されていた「基本的にはパンスクロールだけど、必要に応じてスクロールバーも使える」的な挙動を実現する物。はい、どこからどう見てもパクリです。
ビューポートの大きさの解像度とタッチイベントの座標の解像度が違うという点でドツボに填って難儀したけど、タッチイベントの座標を現在のズーム率とかけ算した値がどうやらビューポートのサイズと同じ解像度になるようだったので、どうにかそれらしい動きを実現できた。
縦にクソ長い2chまとめだとかTogetterまとめだとかを見た後で最初の方までスクロールするのにパンスクロールのためのスワイプ操作で画面をひたすらこするのにウンザリしていて、このままじゃ画面か指が削れて無くなっちまうよ!!!という悩みはこれで解消されると思う。
Open Local File(ローカルファイルを開く)は、名前の通りで、なぜかAndroid版Firefoxに標準で付いてない「ローカルファイルを選択して開く」機能を加えるだけの物。一旦ダウンロードして保存したXPIファイルをファイルブラウザからFirefoxを指定して開こうと思ったら、関連付けでJota Text Editor固定になってしまっててどう頑張っても開けず、関連付けを設定し直すのもイヤだったので、作った。
nsIFilePickerでやってるんだけど、modeGetFolderが未実装だったり最後に開いたディレクトリを記録・反映できなかったりと、PC版と同じように作るのはやはり難しいのだなあ。という事を改めて思い知らされた感じです。
あと選択範囲のリンクをまとめて保存する機能なんかも欲しかったんだけどゼロから作るのはさすがに辛かったので、これはSave Link Menusを改造して作った。
デスクトップ版FirefoxとAndroid版FirefoxではAPIが違う部分が多いので(低レベルのAPIは共通でもUIに近い部分は全然違う)、まだまだおぼつかない感じだし、ちょっと凝ったことをやろうとするとドキュメントが無いというかつてのMozilla Application Suite時代のアドオン開発を想起させられる手探りっぷりだけど、必要になったらさっと作れるくらいにはなれるといいなあ。
This is the English translation of my another entry.
I decided to reject a pull request for TST, adding new secret preference to disable animation effects around drag and drop of tabs, because it contradicts the principle of the TST project. This entry describes why I rejected the pull request.
Because it is introduced by Firefox itself. After the animation effect is activated on Firefox, I updated TST to follow it. However, it was unwelcome update for some people and I got many requests like "it is hard to operate tabs with drag-and-drop", "I want an option to disable animation effects during tabs are dragged." Actually, I can see two issues on the issue tracker:
The patch of the pull request adds a secret preference to do it. It is enough small and clear. If I added the option, I wrote just same patch.
But I disagree to merge the pull request, because I think that the approach of the patch is similar to a story: "Firefox's Gecko engine is too buggy and less compatibility to WebKit, so why don't you delete all codes of Gecko and introduce WebKit with Firefox-like UI?" In other words, it is very easy to add new option which is requested by people, however, I'm extremely reluctant to do it beacuse it is opposed to my polify on Tree Style Tab project.
Basically, this project depends on Mozilla Firefox project --which is very large and uncontrollable by me-- and it is unavoidable to be tossed up and down by the storm of changes in Firefox. Actually, on my another project, I had to rewrite the addon for new versions of Firefox again and again. I learned through the bitter experience that I should have some strict policies on my addon projects:
Don't re-implement a feature included in Firefox itself. For example, Tab Mix Plus has its own session management mechanism, because TMP project is started before the session management feature is introduced by Firefox itself. If the TMP project was started after that, they project team didn't implement such a custom session manager. There is no merit to implement a custom feature which conflicts to Firefox's.
To reduce maintenance cost, and to keep better compatibility with other addons which are developed based on Firefox's APIs, I think I should update and re-construct my addons for new APIs introduced by Firefox. It is better than I struggle to keep old custom implementations against Firefox's changes.
However, sometimes I decide to keep my custom implementations, when it is hard to rewrite codes for Firefox's new API for me.
For example, TST uses a library "JSDeferred" to process asynchronous operations easily. On the other side, lately Firefox uses Promise and Task for the same purpose. I know I should rewrite TST based on them instead of JSDeferred, but I still don't do it because: 1) TST is strongly designed based on JSDeferred. 2) Promise/Task are not available on the current ESR (Firefox 17). (In other words, I'll merge pull requests to do such a reconstruction, if there is no disadvantage about compatibility with other addons.)
When the API of Firefox's library is too untrustworthy for me, I decide to use my custom library based on very low stable APIs.
For example, Firefox has a system named "preference" which can save/restore users' configurations. Because it is not developer-friendly (ex. there are three deferent types --boolean, integer, and string--, and hard to observe changed configurations dynamically), Firefox provides some libraries like FUEL. But, such libraries are untrustworthy and risky for me because Firefox team sometimes changes those APIs despite they promised those APIs are developer-friendly --obviously they should be stable and safe--. I don't want to spend time to update my codes for such unstable APIs, so I actually use my custom library modules/lib/prefs.js which is based only on very stable low APIs. It is one of reasons why I don't update my codes for Promise/Task yet.
Anyway, I think that FUEL APIs are untrustworthy because Firefox team created FUEL just for third party add-on developers, not themselves. Because Promise/Task are used everywhere in Firefox, Firefox team will keep them stable for themselves.
Don't include features not related to the main concept. The basic concept is: what I want to use, one feature per one addon, and, as minimum as possible.
In my old blog entry (note: written in Japanese), I told that: features which I never use or unrelated to the main concept may satisfy users in the short term, but it will shorten life of the project in the long term. Basically I develop and publish my addons on GitHub because I need it and I want to keep it available for me. So I don't want to introduce changes which can disrupt the concept.
Provide higihly compatible, natural look-and-feel for Firefox's built-in features and other addons. For example, Firefox has a feature "auto hide toolbox" for the fullscreen mode started by F11 key. And, TST also provides "auto hide tab bar" feature. Yes, it is not related to "tree" feature. But if TST doesn't have the feature, you'll see unexpected vertical tab bar in the fullscreen mode. You press F11, you expect that the web page becomes fullscreened, then the vertical tab bar should not appear on the scene.
This is the main reason why I took much time to update TST to support drag-and-drop animation effects. Before the animation effect is introduced to Firefox, I respected behaviors of drag-and-drop around layers and objects on Adobe Illustrator. This behavior is still available when you drag a link to the tab bar.
Based on the above policies, I disagree to merge this pull request to TST's master, because:
Because there is no option to enable/disable animation effects, I think that Firefox team basically designs Firefox to do drag-and-drop operations with animations. Then, I should keep TST along the design of Firefox itself.
Actually disabling animation effects by userChrome.css or other ways sometimes break Firefox itself. For example, the internal operation to finalize closed tabs uses "TransitionEnd" DOM event to trigger itself, but it didn't workcorrectly because the event was never fired if the animation efect was disabled by userChrome.css. (I don't kwnow the bug is already fixed or not.)
I don't think my addon should be specially hospitable for people who live without animation effects, because Firefox itself disfavors them.
This is just my personal, current opinion. Of course I don't think this is the final truth of the topic. If you have information which can solve my worrying, or if you explain compelling reasons that I should do it, then I possibly merge such a change.
Otherwise, I'm sorry but I never merge such pull requests to my master repository. Then please fork this project, extend, maintain, and release it for people who have same distress - it is my stance on this project. To keep my codes forkable -- this is one of reasons why I distribute all codes of TST under OSS licenses.
English version of this entry is available.
ツリー型タブに頂いたプルリクエストについて、ポリシー上の理由から取り込めないなあと思ったのだけれども、これまで、参照しやすい形でまとまった文章としてポリシーを表明していなかった気がするで、何故この変更を取り込まないか(タブをドラッグ&ドロップするときのアニメーション効果をOFFにできるようにしないのか)の判断理由を頑張って文章にしてみました。アーカイブとして、少し手直し&追記してこちらにも転記しておきます。
Firefox本体の挙動としてタブのドラッグ&ドロップ操作にアニメーション効果が適用されるようになって以後、ツリー型タブにも、その挙動に合わせるための変更を随時行ってきました。
しかしながら、この変更は万人にとって望ましい結果をもたらしたとは言えず、「タブをドラッグ&ドロップで操作しにくい」「タブのドラッグ&ドロップ操作時のアニメーション効果を無効にできるようにして欲しい」といった意見・要望が何度か寄せられています。今すぐにパッと挙げられるだけでも、Issue Tracker上には以下の2つのIssueがありました。
メールを通じて寄せられた意見も合わせると、無視できない数の人がこの件に関心を持っているようだ、という印象を僕は持っています。
冒頭に挙げたプルリクエストは、ドラッグ&ドロップ時のアニメーションを無効化する設定をツリー型タブに加える、という物でした。変更箇所は最小限で、内容もおかしなことをしている部分はなく、コードとしてはそのまま取り込んで全く違和感のないパッチです。
ですが、自分の認識としては、このパッチで示されている方向での対応というのは言わば、「FirefoxのGeckoエンジンはバグだらけだしWebkitと互換性が低いから、Geckoを全部消して、WebkitにFirefox風のUIを付けた物を次のバージョンのFirefoxにしますよ」というような物なのではないか、と考えています。……という例えは極端なのでもう少し普通の言葉で言い直すと、「確かに皆が望む通りに対処することは簡単なのだけれども、プロジェクトの運営ポリシー的に、この点で皆が望む通りの対処の仕方をする事には非常に慎重である」ということになります。
大前提として、このプロジェクト(ツリー型タブというアドオンの開発プロジェクト)は、Mozilla Firefoxという自分には制御のできない別のプロジェクトに依存している・振り回される事を避けられないプロジェクトである、という事をまず押さえておく必要があります。
ツリー型タブ以外も含めた自作のFirefoxアドオン全体で、Firefoxの仕様変更に追従するために大きな変更が必要だったことが過去に何度かあり、その時の苦い経験から、現在のところ、自分はこれらのアドオン開発のプロジェクトにおいて以下のような方針を立てるようにしています。
以上を踏まえてこのプルリクエストで触れている問題を考えると、自分は以下の理由から、この変更を行わない方が良いという考えを持っています。
以上の事は、あくまで現時点での自分の考えがそうであるというだけで、絶対普遍の真理であるとは考えていません。ここに挙げた数々の懸念点を払拭できる材料があったり、あるいは、そのような懸念があってもなおこのようにするべきであるという強い動機があって、僕が同意できるのであれば、変更を取り込むことにはやぶさかでないです。
でも、そうでない限りは、この種の変更については「フォーク版を作ってそっちで自由に開発していって下さい。そして、その機能を必要とする人自身の手でメンテナンスしていって下さい。」というのがこのプロジェクトの方針ということになります。僕がこれらのアドオン群にオープンソースライセンスを適用しているのには、そのような自由を保障しておきたかったからという理由もあります。
冷たいようですが、どこで線を引くのか・何を基準に線を引くのかを熟慮した結果、このような線引きに落ち着いたということで、同様の不満を抱いている方々にはどうかご理解を頂ければ幸いです。