Home > Latest topics

Latest topics 近況報告

たまに18歳未満の人や心臓の弱い人にはお勧めできない情報が含まれることもあるかもしれない、甘くなくて酸っぱくてしょっぱいチラシの裏。RSSによる簡単な更新情報を利用したりすると、ハッピーになるかも知れませんしそうでないかも知れません。

萌えるふぉくす子さんだば子本制作プロジェクトの動向はもえじら組ブログで。

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

Page 6/245: « 2 3 4 5 6 7 8 9 10 »

「タブを閉じる」ボタンの働きの選択肢として「親のタブを閉じずに子孫のタブだけを閉じる」が欲しい(A new option to close only child tabs by "Close Tab" button) - May 14, 2010

Q

My small suggestion is to be able to configure the close button for a parent tab to just close its children. After it is child-less, the second click would close the tab itself. My feeling is that this would make for more fluid experience when you open up a flurry of child tabs to follow up on details and want to continue with the main "story" or "task" on the original parent tab. As it is now you have to right click and select close children, which I find a bit clunky.

私の希望は、親のタブの「タブを閉じる」ボタンをクリックした時の挙動として、子孫のタブだけを閉じるというオプションが欲しいというものです。そのタブに子供がいなくなった後、2度目のクリックはそのタブ自身を閉じるでしょう。これがどういうときに役立つかというと、何か作業をしている時に、詳細な情報を見るために子タブをいくつか開いた後で、それらを一気に閉じて元の作業に戻るという風な場合です。現状でこのような使い方をするには、タブを右クリックして「このタブの子タブをすべて閉じる」を選択しなくてはならないので、面倒です。

A

Sorry, I have no plan to implement the feature to Tree Style Tab. There are two reasons: 1) overriding of the behavior of "close tab" button is hard to implement. And, 2) I think it is not an instinctive behavior.

1) Now there are some options for "close tab" of parent tabs, but all options are designed to work just after the parent tab was correctly closed. Because, TST listens "TabClose" event which is fired after the tab is completely closed by Firefox itself. We cannot cancel the closing of the parent tab from "TabClose" event.

2) If "close tab" button closes the tab and its collapsed children, I think it is instinctive, because it is same to the default behavior of the "close tab" button, except there are collapsed (hidden) children. And if the button closes only the parent tab (keeping children open) it is also same to the Firefox default. "When the close button is clicked, only children are closed and the tab itself is still there" -- the scenario is odd a little for me.

However, you can implement the feature with other scriptable addons (FireGestures, userChrome.js, etc.) with following codes:

var parentTab = gBrowser.selectedTab;
if (TreeStyleTab.hasChildTabs(parentTab)
  // The second argument "true" means "close only children".
  TreeStyleTabService.removeTabSubtree(parentTab, true);
else
  gBrowser.removeTab(parentTab);

すみませんが、その機能をツリー型タブ本体に取り込むつもりはありません。それには2つの理由があります。1) 「タブを閉じる」ボタンの挙動を乗っ取るのは実装が大変ですし、2) その挙動は直感的とは私には思えません。

1) 現在、親のタブの「タブを閉じる」ボタンをクリックした場合の挙動にはいくつかの選択肢を設けてありますが、そのいずれも、親のタブ自体が閉じられた後に働くことを前提にしています。これはツリー型タブが、タブが完全に閉じられた後でFirefox自身によって発行される「TabClose」イベントを監視することによってこの機能を実現しているためです。「TabClose」イベントからは、タブを閉じる操作自体をキャンセルする事はできません。

2) 「タブを閉じる」ボタンによってそのタブ自身とすべての折り畳まれた子タブが閉じられる場合、そこに折り畳まれた(見えない)子タブがあるという点を除けばFirefoxの標準的な挙動と同じなので、これは私には直感的な挙動に感じられます。また、もしそのタブだけが閉じられて子タブが残るのであれば、これはFirefoxの標準的な挙動と全く同じです。しかしながら、「タブを閉じるボタンをクリックしたら、子タブだけが閉じられて、そのタブは已然として開かれたままとなる」――この挙動は、私には違和感があります。

とはいえ、あなたはこの機能を、スクリプトでカスタマイズする機能を持った他のアドオン(FireGestures、userChrome.jsなど)と組み合わせる事で実現できます。上記のコードを参照して下さい。

ロケーションバーからAlt-Enterでタブを開けない?(ALT-Enter in the location bar doesn't open new tab?) - May 14, 2010

Q

In plain Firefox, ALT-Enter in the address bar opens a new tab. This doesn't happen with Tree Style Tab activated.

素のFirefoxでは、ロケーションバーでAlt-Enterと入力すると新しいタブが開かれます。ツリー型タブが有効な状態だと、この機能が働きません。

A

I think it is a designed behavior of TST. TST includes a feature to open new tabs from the location bar without the ALT key, and the effect of the ALT key is inverted by the feature (Enter => new tab, ALT-Enter => current tab).

To get back Firefox's default behavior (Enter => current tab, ALT-Enter => new tab), go to TST's configuration dialog => "New Tabs" => "Location Bar".

If you don't want any loading into the current tab from the location bar (Enter => new tab, ALT-Enter => new tab), then, go to about:config and turn "extensions.treestyletab.urlbar.invertDefaultBehavior" to "false".

この挙動はツリー型タブの仕様であると思われます。ツリー型タブはロケーションバーでAltキーを押さずに新しいタブを開くための機能を含んでおり、この影響によって、Altキーの働きは反転される事になります。(Enter→新しいタブ、Alt-Enter→現在のタブ)

Firefoxの既定の挙動(Enter→現在のタブ、Alt-Enter→新しいタブ)に戻すには、ツリー型タブの設定ダイアログで「新しいタブ」→「ロケーションバー」を参照して下さい。

もし常に新しいタブを開くようにしたい(Enter→新しいタブ、Alt-Enter→新しいタブ)場合は、about:configを開いて extensions.treestyletab.urlbar.invertDefaultBehavior を false に設定して下さい。

Windows 7のAeroPeek(タスクバーのプレビュー)にアドオンから手を出してみる - May 13, 2010

Windows 7では、特定のアプリケーションのウィンドウが複数開かれている状態でタスクバー上のボタンをポイントすると、各ウィンドウのプレビューが一覧表示されるようになっている。これはAero Peekという機能だ。Firefox 3.6以降ではこのAero Peekのためのコードが入ってて、about:configでbrowser.taskbar.previews.enableをtrueに変更して機能を有効にすると、ウィンドウごとではなくタブごとのプレビューが表示されるようになる。Trunkではデフォルトで有効になってるので、次のメジャーリリースでもそうなるんだろう。

この機能について、ツリー型タブで対応してくれという要望が何件か来ていたので、0.10.2010043001以降では折り畳まれたツリーの中にあるタブのプレビューは表示しないようにしてみた。これを実現するにあたって調べたことを書き記しておく。

FirefoxでウィンドウごとではなくタブごとのプレビューをAero Peekに表示させるためのコードのうち、アドオンから簡単に触れるのはWindowsPreviewPerTab.jsmにあるコードだ。以下のようにするとプレビューのマネージャにアクセスすることができる。

Components.utils.import('resource://gre/modules/WindowsPreviewPerTab.jsm');
alert(AeroPeek); // "[object Object]"

ツリー型タブの新機能(?)の「折り畳まれたタブに対応するプレビューを隠す」は、ここからどうやれば実現できるのか。

まずAeroPeek.windowsの中から、処理対象のウィンドウに対応する項目を探す。このプロパティは各ウィンドウに対応するオブジェクトの配列になっていて、オブジェクトのwinプロパティにFirefoxのブラウザウィンドウのDOMWindowオブジェクトがそのまま入ってる。なので、以下のようにすれば今のウィンドウに対応するオブジェクトを見つけられる。

AeroPeek.windows.some(function(aTabWindow) {
  if (aTabWindow.win == window) {
    // 現在のウィンドウに対する操作
    return true;
  }
  return false;
});

また、このオブジェクトはpreviewsというプロパティの中に各タブのプレビューに対応するオブジェクトを持っている。以下のようにすれば、プレビューからタブのDOMElementを辿ることができる。

aTabWindow.previews.forEach(function(aPreview) {
  var tab = aPreview.controller.wrappedJSObject.tab;
  // タブに応じた操作
});

プレビューのオブジェクトはvisibleという真偽値のプロパティを持っていて、これの値がtrueだとAero Peekのプレビューが表示され、falseだと非表示になる。ツリー型タブの場合、タブが折り畳まれているかどうかによってこの値を上書きするようにしている。

var tab = aPreview.controller.wrappedJSObject.tab;
aPreview.visible = !TreeStyleTabService.isCollapsed(tab);

初期状態では、visibleの値はbrowser.taskbar.previews.enableの値と同じになっている。アドオンでvisibletrueにするとユーザがAero Peekを設定で無効化してても問答無用でプレビューが表示されてしまうので、誤ってtrueにしてしまわないように気をつけないといけない。僕はうっかりこれをやってしまった。

で、プレビューの表示・非表示を切り替えた後は、表示されるプレビューの総数が変わったことをマネージャに通知してやる。

AeroPeek.checkPreviewCount();

Firefoxは、プレビューの数が多すぎる時は強制的にプレビューを非表示にするようになってる。その切り替えの判断は、このメソッドが呼ばれた時に行われている。

以上をまとめると、こうなる。

AeroPeek.windows.some(function(aTabWindow) {
  if (aTabWindow.win == window) {
    aTabWindow.previews.forEach(function(aPreview) {
      var tab = aPreview.controller.wrappedJSObject.tab;
      aPreview.visible = !TreeStyleTabService.isCollapsed(tab);
    });
    AeroPeek.checkPreviewCount();
    return true;
  }
  return false;
});

ツリー型タブでは、これをツリーの開閉が行われる度に実行している。開閉の捕捉はカスタムイベントで行ってる。

プレビューの並び順とかも変えれそうな気がなんとなくしてるので、やる気が出てきたらまたいじってみようと思ってる。ただ、他のアドオンもここに手を出すと衝突しまくりそうではある。

タブバーの縦置き・横置きをタブの数に応じて自動で切り替えたい(A new option to switch the position of the tab bar by the number of tabs.) - May 06, 2010

Q

I have a feature request for Tree Style Tab.

I'd like to use horizontal tabs when I have 5 or less tabs open and then have Firefox automatically switch to vertical tabs when I have 6 or more tabs open. These numbers could obviously be variables in the settings, and the feature could just be toggled from the settings as well.

ツリー型タブへの機能追加の要望です。

タブの数が5つかそれより少ない時はタブを横置きにして、タブの数が6個以上になったらFirefoxが自動的にタブを縦置きに切り替える、という機能が欲しいです。また、タブの位置を切り替える基準のタブの数は簡単に設定できるようになっていて欲しいです。

A

I have no plan to implement the feature to Tree Style Tab itself, however, you can do it by a tiny script using TST's APIs like:

(function() {
  var MAX_HORIZONTAL_TABS = 5;
  var onTabModified = function() {
    var newPosition;
    if (gBrowser.tabContainer.childNodes.length > MAX_HORIZONTAL_TABS)
      newPosition = 'left';
    else
      newPosition = 'top';
    if (TreeStyleTabService.currentTabbarPosition != newPosition)
      TreeStyleTabService.currentTabbarPosition = newPosition;
  };
  gBrowser.tabContainer
    .addEventListener('TabOpen', onTabModified, false);
  gBrowser.tabContainer
    .addEventListener('TabClose', onTabModified, false);
  onTabModified();
  window.addEventListener('unload', function() {
    window.removeEventListener('unload', arguments.callee, false);
    gBrowser.tabContainer
      .removeEventListener('TabOpen', onTabModified, false);
    gBrowser.tabContainer
      .removeEventListener('TabClose', onTabModified, false);
  }, false);
})();

For example, you can use this script for the userChrome.js. Steps to do it:

  1. Install userChrome.js from the official website.
  2. After installation, copy the codes above and paste to the file "userChrome.js" in your profile folder. (ex. C:\Users\username\AppData\Roaming\Mozila\Firefox\Profiles\***.default\chrome\userChrome.js )

そういう機能をツリー型タブ自体に付ける予定はないですが、ツリー型タブのAPIを使うと、上記のような小さいスクリプトでその機能を実現する事ができます。

例えば、このスクリプトはuserChrome.jsでそのまま利用できます。手順は以下の通りです:

  1. userChrome.jsをオフィシャルサイトからインストールする。
  2. インストールが完了したら、前述のコードをコピーして、プロファイルフォルダ内にある「userChrome.js」というファイルに貼り付ける。(例: C:\Users\username\AppData\Roaming\Mozila\Firefox\Profiles\***.default\chrome\userChrome.js )

CSS Transitions(CSSだけで簡単なアニメーション)の使い方・覚え方のまとめ - May 02, 2010

いろんな人がいろんな解説を既に書いてるみたいだけど、ツリー型タブでタブのインデントや折り畳みのアニメーションをCSS Transitionsで書き直してみるにあたり、自分で書いてみるまでよく分からんかったので、理解している内容をまとめてみることにした。

CSS Transitionsのフルスペックの説明でもないし、「こんなことができるぜすげーだろ!」というデモでもない。現実的にどういう場面でどういう風に使う事ができるのか、という事を淡々と述べます。いろんな機能を詰め込んだよく分からんデモスクリプトと組み合わせること前提の変なデモを見たせいで混乱してる僕みたいな人が、CSS Transitionsを理解するための手助けになれれば幸いです。

主な用途

マージンや色などの値を数値で表せるプロパティや、画像を表示する系のプロパティなどについて、スクリプトあるいは:hoverなどの疑似クラスによって動的に値が変化するようにしている場面で、元の状態と新しい状態の間をなめらかに変化させるようにする。

例えば、こんな風に。

ul.menu li {
  transition: margin-left 0.25s ease-out;
}
ul.menu li:not(:hover) {
  margin-left: 0;
}
ul.menu li:hover {
  margin-left: 50px;
}

この例では、分かりやすくするために敢えて指定を分けて書いている。ここでは以下のようなことが起こっている。

  • 何もしていない状態だと、margin-left: 0;が適用されている。
  • :hoverの状態になると、margin-left50pxになるようにアニメーションが始まる。
  • :hoverの状態が解除されると、margin-left0になるようにアニメーションが始まる。

何ができる?

  • CSSだけでやれる範囲でいうと、上記のサンプルのように「:hoverになった時にぽわーんとなめらかに出てきて、:hoverが解除されたらぽわーんとなめらかに引っ込む」ようなGUI要素をスクリプト無しで書けるようになる、という所に意義がある。例を挙げると、以下のような物が該当するだろう。
    • :hoverの時だけ出っ張るメニュー項目が、なめらかに出っ張る/引っ込むようになる、とか。
    • :hoverすると色が変わるボタンが、「じわっ……」と色が変わるようになる、とか。
    • :hoverで影が付く時に、「じわっ……」と影が濃くなる、とか。
    • メニューが透明な状態から「じわっ……」と表示されていく、とか。
    • アイコンが90°回転する時に回転がなめらかになる、とか。
  • スクリプトと組み合わせて使う場合、トゥイーンのための実装が要らなくなる(ネイティブ実装に任せてしまえる)というのが多分最大のメリット。
    • ポジショニングやマージンの調整で要素の表示位置を変える時、単に新しい値(=アニメーションの終了時点の値)を設定するだけでトゥイーンしてくれる。
    • CSSで初期値とdurationとイージング関数を指定しておいて、スクリプトで終了値だけを動的に指定する、という使い方。
    • CSSのクラスセレクタであらかじめいくつかの終了値のセットを定義しておいて、スクリプトでclassNameを書き換えて終了値を間接的に指定する、という使い方。
    • タイマーの管理が不要になるので、複数のアニメーションを同時に走らせる場合、アニメーションが全体的に軽くなると思われる。
  • 既に前のアニメーションが行われている間にまた値を変更した場合、現在の時点の値からの変化になる。
    • アニメーションの中断と再開のための面倒なコードは不要。
    • 例えば、margin-left0であったのを、20pxを設定してアニメーションが始まり、20pxに向けて変化していっている最中の10pxの時点でmargin-left0に再設定した場合、前のアニメーションが中断されて、新たに10pxから0に向けて変化するアニメーションが始まる事になる。
    • スクリプトでも動的疑似クラスでも。

「Windows Vista以降のAero Glass有効時のネイティブアプリのボタンみたいな物をWebに簡単に持ち込めるようにする」「GUIの端々にほんのちょっとだけ小粋なアニメーション効果を加えたい時に、スクリプトを書かなくてもよくなる」という話ですね。それ以上でもそれ以下でもないと思っておくと、CSS Transitionsを理解しやすいと思います。

何ができない?

  • テレビアニメのような、長くて複雑なアニメーションは無理。滅茶苦茶頑張ればできるかもしれないけど、CSS Transitionsの仕事ではない。
  • アニメーションと連動したスクリプトの複雑な制御。
    • アニメーション終了時にはDOM Level2 Eventsのイベントリスナで捕捉可能なtransitionendイベント(WebKitではwebKitTransitionEnd)が発行されるので、アニメーションの終了だけは検知できる。
    • それ以外のタイミングではイベントは発行されない(アニメーションが始まったかどうかも分からない)。
  • 無限に繰り返すアニメーション。
    • ループするアニメーションのデモではスクリプトと組み合わせていて、transitionendイベントを使ってその都度新しい「アニメーション終了時点の値」を設定し直してやることで、アニメーションを繰り返している。CSS Transitionsだけではループはできない。
  • どんなプロパティでもアニメーションできるわけではない。仕様書(のWorking Draft)にアニメーションできるプロパティの一覧がある。

書き方

transition:
    アニメーションさせたいプロパティの名前
    アニメーション終了までにかける時間(省略すると0)
    イージングの種類(省略するとease)
    アニメーションが始まるまでの遅延(省略すると0);

これで1セットと考えると分かりやすい。複数のプロパティをアニメーションさせたい時は、

transition: margin-left 1s ease;
transition: margin-top 1s ease;

とは書けないので、カンマ区切りにして

transition: margin-left 1s ease,
            margin-top 1s ease;

と書く。

アニメーション終了までにかける時間はCSS3 Values and Unitsの時間の値で指定する。例えば250ミリ秒で完了させたい時は250ms(ミリ秒単位)または0.25s(秒単位)と書く。アニメーションが始まるまでの遅延も同様。

イージング関数(値の変化の仕方)には、以下のいずれかを指定できる。

linear
等速直線運動的な変化
ease-in
最初はゆっくり、最後にいくにつれて激しく変化
ease-out
最初は激しく、最後にいくにつれてゆっくり変化
ease
ゆっくり始まって、途中で最高速になり、最後はまたゆっくり変化
ease-in-out
easeをもう少しきびきびさせたような感じ
cubic-bezier()
ベジェ曲線でアニメーションの変化の仕方を指定

現状ではまだ仕様が固まっていなくてどのベンダも先行実装の段階なので、ベンダープレフィクス付きの指定を書いてやらないといけない。

-webkit-transition: SafariとGoogle Chrome用の指定;
-moz-transition: Firefox用の指定;
-o-transition: Opera用の指定;
transition: 仕様通りの指定;

CSS TransitionsがRecommendationになったら、ベンダープレフィクス無しの記述だけでいけるようになるはず。

Why I'm using eval() instead of others? - Apr 06, 2010

参考:AMOエディタ権限剥奪きますた

Hello,

Surely I wrongly believed that the policy is flexible for cases, because Tree Style Tab was in the "recommended" list actually. When the policy was changed (to be applied completely for any addons), it had to be removed from the list quickly. This is not a cynicism, I'm really worrying that double standard will make developers confused.

In fact I had not reviewed addons as an editor yet, so this is nonsensically thing, but if I still can talk about this, I didn't mean to accept any addons include eval()s without reviewing. When there are alternative safer way, I thought that recommend him to rewrite his codes. I just told about cases which are not alternated by other ways.

Anyway, I agree to the decision that you've removed me from the group. I had no actual achievement as an editor (there is zero review! I'm very sorry.), instead, I'm all mouth. That's that. I'll still use AMO as an addon author, to put old XPI files, and I possibly move existing versions in the AMO to the beta channel. I think that AMO is really really great work. Editors also.

regards,

P.S.

Can I explain again the reason why I'm using eval() to override existing functions instead of other ways? Of course I use custom DOM events or other safe way when they are available. Following topic is about cases which don't fire custom events. In other words, I explain why I don't like replacing of existing functions by "originalFunction.apply(this, arguments)".

In old days I developed an all-in-one style addon named "Tabbrowser Extensions (TBE)" for Firefox 1.5 and older versions. It was one of major addons about tabbed browsing enhancements, until Tab Mix Plus appeared. In the addon, I aggressively replaced many internal functions of Firefox itself, like:

var origFunc = gBrowser.moveTabTo;
gBrowser.moveTabTo = function() {
  var result = origFunc.apply(this, arguments);
  // some post-process for the moved tab
  return result;
};

Yes, it is one of ways recommended in the entry http://adblockplus.org/blog/five-wrong-reasons-to-use-eval-in-an-extension for injecting some operations before/after the original function.

However, then I frequently suffered from compatibility problems with other addons around tabs, because they used eval() to inject their tiny codes to existing (Fireflx's original) functions, like:

eval("gBrowser.moveTabTo = "+gBrowser.moveTabTo.replace(
  "tab = ",
  "doSomething(); $&"
));

As you know, replacing of functions break addons which inject codes by eval() like above. So I had to choose how to solve this problem, from two ways: 1) import and merge the function of the addon conflict with TBE, 2) use eval() instead of replacing of functions. There was no other choice. To make another addon compatible to mine, it had to be re-written without eval(), but it can't be done in some cases, because the feature surely required injected codes to existing functions. I couldn't make mine compatible to the addon without eval(). I disliked eval(), then I chose "1". In the result, TBE became very very fat addon and I couldn't continue to develop it by me alone anymore. I abandoned it.

I can't force users to forbid using addons which depend on eval(). On the other side, I cannot merge too many features to my own addon because fat and huge project will annoy me. From both reasons "make my addon compatible with the addon" and "keep my addon simple (without extra features)", now I'm using eval()s to inject just minimal codes.

Safety margin about compatibility to other tab-related addons is one of core values of Tree Style Tab and other my addons developed after TBE. When I get reports of compatibility problems with other addons, I try to make mine compatible to others if at all possible (and, of course, for compatibility some my addons provide APIs for others.) If there were only "clean" ways (DOM events, Object.prototype.watch(), etc.) TST were far from satisfactory for tab addicts. Because I'm also using many other tab-related addons (not developed by me), if it doesn't work others, I also won't use TST. Just for making my addons compatible to existing and future addons, I chose eval().

If there were many other custom events for bookmark commands, new tab commands, etc., I won't use eval()s. XBL, CSS hacks also. However, margins for extending UIs (unused boxes etc.) are getting removed from Firefox, because "they eat the RAM, they make the startup process slowly". Only to adding extra elements to tabs, I had to use custom XBL at risk of compatibility problems with third party's themes.

Firefox is getting hard to be extended for me (and my addons). My addon was listed to "recommended", and people say "update it for latest Firefox". There is no way to provide features of my addon without dangerous way. That is my situation.

今evalを理由に審査を蹴られるのであっても、その代替となるより安全な手段が提供されるのであれば、迷わずそっちに乗り換えたいとは思ってる。問題は、独自のXBLを提供するなどの「危ない」事をしなければやりたい事を実現できないような、拡張機能から触れる伸び代の部分がどんどんなくなってるという事だ。それどころか、起動速度が落ちるからという理由でFUELがばっさり切られたように、今ある必要な物すらどんどん切られていっている。W3Cですら、テーブルレイアウトを必要とする人達のニーズにある程度答えられるような、position: absoluteのような仕組みを仕様に取り入れていたというのに。そういう現実を抜きにして、この話は語れないと思う。

あと先方から補足があったけど、曰く、AMO Editorsグループから外した直接の理由は確かに「ポリシーに同意していないから」だけれども、活動してないエディタを外す事自体はよくあることだそうで、ポリシー云々のことが無くてもレビュー実績0の自分はいずれ外されてただろうとのことです。

Why I don't roll Tree Style Tab back to the version which have the option "hide new tab button"? - Mar 31, 2010

I got some requests to add an option "hide new tab button" again.

Excuse me, but I say "no". There are two reasons.

First, by adding too many options, users consider Tree Style Tab as an all-in-one/versatile addon, and novice users who don't understand what is the purpose of TST will also install it. I don't hope that future. Actually, I received some requests like "please add an option to disable tree features, I want only a vertical tab bar." -- I just ignored it.

Yes, currently TST has some features not related to tree, but they are anguished decisions. When I find out other addons which provide those futures, I'll readily remove them from TST itself, and make TST work with those addons together. (Actually I removed "open selected links in tabs" and some features.) I hope that only users who want to use "tree of tabs" install TST.

By the way, in old days I developed an all-in-one style addon "Tabbrowser Extensions" which was well-known before the Tab Mix Plus became major. It had very various options about tabs, it had huge codes, I received too many requests, and I gave up to continue to develop it. I don't want to repeat stupid thing like that.

Second, hiding the "new tab" button is a choice of an user who use another addon to do it. TST is designed to work with visible"new tab" button, and not designed to work without the button. If you decide to hide the button at your own risk, you also have to care the result, especially when you hide the button by customizing of userChrome.css.

Nonetheless, If you hide the button by an option of an existing addon, then I should add some hack to TST for compatibility with the addon, because I said "and make TST work with those addons together." Which addon do you use, Tab Mix Plus? TMP Lite CE? Tab Utilities? If you tell me which is installed, then I can write hack for the addon promptly.

regards,

ツリー型タブにツリーと関係ない機能を加えてくれという要求は尽きない。何度でも言うけど、ツリー型タブを多機能アドオンにするつもりは全く無いし、現状でツリーと関係ない機能が含まれているのは実装上の都合とかそういう理由による苦渋の選択だし、そういう機能を取り除けるものならどんどん取り除いていくつもりだし実際そうしてきたし、とにかくそこを譲るつもりは全くこれっぽっちもありません。特に、アドオンを自分で作ってないエンドユーザの立場から物を言っている人に対しては。自分で作ってる人にはもちろんこう返しますよ、「じゃあそのためのアドオンをあなたが作って下さい。なるべく連携できるようにこっちも頑張るから。」と。

Minefield 3.7a4preのタブバーの仕様変更に対してツリー型タブで取った対応方法 - Mar 29, 2010

タブバーがtabbrowser要素の中から取り出されて1つのツールバーになったということで、タブ関係の挙動を変える系のアドオンが死屍累々なんじゃないかと不謹慎にもwktkしてるわけですけれども。特に影響が大きくて話としても「あーそりゃそうなるわな」ってのが分かりやすいのは、やはりタブバーの表示位置の変更機能ですよね。

今まで

今までは、Firefoxのメインウィンドウの中身は簡単に言えばこんな要素構造になってた。

<toolbox>
  <toolbar/>
</toolbox>
<tabbrowser>
  <tabbox orient="vertical">
    <tabs orient="horizontal">
      <tab/>
      <tab/>
    </tabs>
    <tabpanels>
      <browser/>
      <browser/>
    </tabpanels>
  </tabbox>
</tabbrowser>

XULのレイアウトは主にMozillaの関係者からCSS3に提案中のflexible box layoutに基づいてるんだけど、

  • -moz-box-orient: horizontal(XUL要素の属性指定だとorient="horizontal")だとボックスの中身が横に並ぶ。
  • -moz-box-orient: vertical(XUL要素の属性指定だとorient="vertical")だとボックスの中身が縦に並ぶ。
  • -moz-box-ordinal-groupの値(XUL要素の属性指定だとordinalの値)の順にボックスが並べ替えられて表示される。

これだけの事を組み合わせれば、タブバーの位置を上下左右好きな位置に移動できた。

  • 初期状態では、tabboxのorientがverticalで、tabsにもtabpanelsにもordinalは指定されていないので、タブバーは上に来る。
  • tabboxのorientをhorizontalにしてtabsのorientをverticalにすれば、タブバーが左に来る。
  • tabsのordinalを2、tabpanelsのordinalを1にすれば、タブバーが下に来る。
  • 両方を同時に指定すれば、タブバーが右に来る。

という具合。

これから

ところが、bug 347930のパッチで要素構造が以下のようにガラッと変わった。

<toolbox>
  <toolbar/>
  <toolbar id="TabsToolbar">
    <tabs orient="horizontal">
      <tab/>
      <tab/>
    </tabs>
  </toolbar>
</toolbox>
<tabbrowser>
  <tabbox orient="vertical">
    <tabpanels>
      <browser/>
      <browser/>
    </tabpanels>
  </tabbox>
</tabbrowser>

こうなると、単純にボックスの並び順やら並べる方向やらを変えただけではタブバーの位置を動かせない。

  • toolboxの中にtabsがあるので、ordinalではtabbrowserより下にtabsを持って来れない。無理に持ってこようとするとtoolbox全体がtabbrowserの下に来てしまう。
  • toolboxの中にtabsがあるので、orientではtabbrowserの横にtabsを持って来れない。無理に持ってこようとするとtoolbox全体がtabbrowserの左に来てしまう。

ドン詰まりですね。

他のタブ関係のアドオンが採用した方法

alice0775さんの調べによると、タブバーの位置を変える機能を持ってる他のアドオンでは、tabsを一旦DOMツリーから取り外して別の位置に挿入し直すという方法で、タブバーの表示位置変更を実現しているらしい。

しかしこのやり方だと、tabsがDOMツリーから取り外されるより前に他のアドオンが行った初期化処理の効果がリセットされてしまう場合がある。リンク先のエントリでいくつか挙げられてる懸念がそれ。

本当だったらFirefox本体の方でなんとか面倒を見て欲しい(タブバーの位置変更を行う機能を持たせて、位置が変わる前と後でイベントを発行するようにするとか)所なんだけど、責任者の人達をIRCで英語で説得する自信は全く無いチキンでTOEICスコアめためたで英語音痴な僕は、アドオン側でなんとかする方法を考えないといけない。しかし、最も単純なやり方(DOMツリーの改変)だと他のアドオンとの競合という点で弊害が大きすぎる。

そういうわけで、ちょっと考えてみました。DOMツリーをいじらずにタブバーの位置を変える方法を。

ツリー型タブが採用した方法

ヒントになったのは、XUL/Migemoの「タブバーの下に検索バーを移動する」機能や、Unified Sidebarの「サイドバーを縦型タブバーの下半分に表示する」機能の実装方法。

これらのアドオンでは「検索バーやサイドバーを表示したい位置にmarginやpaddingでスペースを設けて、検索バーやサイドバーをCSS2のポジショニングでその位置に重ねる」という方法で、DOMツリーを改変することなく要素の表示位置だけを変更している。また、ウィンドウの大きさなどが変わった時には、resizeイベントを捕捉して表示位置や要素の表示サイズを自動調整するようにしている。

ツリー型タブのMinefield 3.7a4pre対応でも、基本的にはそれと同じ方法を使う事にした。ただ、タブバーの幅をリサイズできるようにするsplitterを、ポジショニングで表示位置を変えられた状態向けにゼロから作りなおすのは面倒だったので、tabboxの中にダミーのhbox要素を挿入して、splitterは普通にXULのsplitterを使い続ける事にした。

<toolbox>
  <toolbar/>
  <toolbar id="TabsToolbar">
    <tabs orient="horizontal">
      <tab/>
      <tab/>
    </tabs>
  </toolbar>
</toolbox>
<tabbrowser>
  <tabbox orient="vertical">
    <hbox/>
    <splitter/>
    <tabpanels>
      <browser/>
      <browser/>
    </tabpanels>
  </tabbox>
</tabbrowser>

このようにした上で、

  • hboxを含むtabboxの内容を、Firefox 3.6までの手法でレイアウトして、tabsの表示用のスペースを確保する。
  • hboxの上に同じ大きさでtabsを重ねる。
  • splitterによってhboxがリサイズされた時は、tabsの位置や大きさを自動的に更新する。

とする事で、ぱっと見は今までと同じような挙動を実現しつつ、タブ周りのDOMツリーは一切破壊しないという実装になった。

どっちのやり方の方がいいのか

ツリー型タブのやり方とTab Mix Plus等のやり方のどっちがいいかは、一概には言えない。どちらにもメリットとデメリットがある。

ただ僕は、ツリー型タブで採用したやり方の方が「他のアドオンが全く動かなくなってしまうような衝突の仕方はしなくて、仮に衝突しても最小限の労力でなんとか回避できる可能性が高い」と信じている。

現在Firefox本体の側には、3.6以前のバージョンのFirefox向けに書かれたアドオンについて、Minefield 3.7a4pre以降でもそのまま動くようにするためのパッチも取り込まれている。ちょっとアドオンの作り方に気をつけさえすれば、タブをダブルクリックした時の挙動を変えるとか、リンクから開いたタブの位置を制御するとかいった単機能のアドオンは、ほとんど何も手を加えずにMinefield 3.7a4pre以降に対応できるようになってる。

しかしながら、Tab Mix Plusが現在採用している(らしい)DOMノードを切り貼りするやり方では、「ほっといても他のアドオンがちゃんと動いてくれる」ようにはなりにくい。「DOMノードの切り貼りでタブバーの位置が変更された事」を検知して何らかの特別な初期化処理を行うようなコード、を他のアドオンの側に加えてもらわないと互換性を保てない。僕は、僕のアドオンと競合しないで使えるようにするために、他のアドオンの作者がわざわざ気を使ってくれるとは思えない。僕が作ってる物が、そこまで他のアドオン作者から特別視してもらえる存在だとは、思えない。

なので、僕がアドオンを作る時はなるべく、他のアドオンの側に変更が必要になるような作りにはしないでおこうと思ってる。どうしてもそうなる時は、APIを提供してAPI経由でスッキリと連携できるようにしようと思ってる。そういう謙虚というか悲観的な姿勢が、「ユーザがどんなアドオンと組み合わせて使うかは全く分からない」アドオンを作る上では必要なんじゃないかと思ってる。

ツリー型タブのサイドバーをAll-in-One Sidebarと連携させられないの?(I want the tree of tabs to be shown in the sidebar.) - Mar 19, 2010

Q

I was wondering if there is any way to have it open inside All-in-One Sidebar. If so could you please tell me how to do it?

ツリー型タブの縦型タブバーをAll-in-One Sidebarの中で表示する方法があるなら、教えてもらえませんか?

A

Unfortunately, there is no way. Tree Style Tab's vertical tab bar is not a "sidebar panel", so, it cannot be showin in the AIOS sidebar.

There is another addon "Tab Tree" which provide a sidebar panel of tree of tabs.

It is abandoned by the author, however, it is very similar to your requirement. He published it as a public domain software, so, if you can, you'll take over the project without any warranty.

By the way, I think that Unified Sidebar possibly help you.

残念ながら、方法はありません。ツリー型タブが提供する縦長のタブバーはサイドバー用のパネルではないので、All-in-One Sidebarの中に表示する事はできません。

他のアドオンで、タブのツリーのサイドバーパネルを提供する「Tab Tree」という物があります。

作者はこのアドオンをもう更新しないという事を公言していますが、これはあなたの求めているものによく似ています。彼はこのアドオンを、著作権を主張しないパブリックドメインソフトウェアとしているようなので、もしやる気があるなら、あなたはこのアドオンの開発を(許可を求めずとも)引き継ぐ事ができます。

あと、ひょっとしたらUnified Sidebarもあなたの役に立つかもしれません。

Some reasons why I say that eval is not absolutely dangerous than other hacks. - Feb 08, 2010

This is an translated version of my another entry, evalが危険でそれ以外の方法が安全だと思ってる人へ . This is an objection for the entry: Five wrong reasons to use eval() in an extension written by Wladimir Palant.


Recently I updated Source Viewer Tab and Tree Style Tab. However, when I uploaded the latest version to AMO, both files were retained in the sandbox, never made public by AMO editors. They said with one mouth: "Your add-on uses the 'eval' function unnecessarily, which is something we normally don't accept. There are many reasons *not* to use 'eval', and also simple alternatives to using it. You can read more about it here: http://adblockplus.org/blog/five-wrong-reasons-to-use-eval-in-an-extension"

I know the point of their blames very well, because I read and translated the entry to Japanese for my understanding. When I got a rejection about another addon, I got just same comment.

Now I have an objection about indiscriminate rejections by "too many eval()s" like this.

Both "wrong" and "right" are infelicitous adjectives about eval.

First of all, there is no "wrong" use of eval in any JavaScript codes (not only my addons). All of evals are "right" if it does its own work correctly.

For example, by the HTML specification, <em> is defined as "means emphasizing", "cannot appear in <title>", and so on. If you write <em> against the definitions, your HTML will be "invalid".

How about eval? 15.1.2.1 eval (x) in the ECMAScript specification describes about the function. It just says: runs the specified string as a script. There is no cautionary statement about the purpose of using eval.

There is no "wrong" use, it is just "dangerous" use. There are many usecases: some is high-risk, some is low-risk. But, they all evals are "right" use if it works as required by the spec. So, I think that it is a suitable subject for the entry: "Five dangerous use of eval() in an extension".

Risks of eval have to be managed, in other words, risk-managed evals are useful tool to extend Firefox. For end users, I think some eval should be allowed if it is safe enough in the case. "Eval? No, no, it is evil function! Don't use it anyway!" - I think that is slapdash work.

When you get 5-minute recipes via HTTP, do you untrust it anyway? Because it is insecure protocol, you cannot trust any information without SSL? Note, VeriSign certifies that the website you are accessing via HTTPS is surely hosted by the author, but he doesn't certify that the author is not evil. If you cannot trust any people via internet, you have to live offline - it's a internet phobia. In many cases you maybe trust them anyway if it is low-risk.

In the entry, he negates any eval without considering about its risk if it is out of the "valid uses". I think it is just a eval phobia.

Can the eval eat codes from the Web, really?

I agree to blame some cases of 5 cases in the entry. The 1st (parsing JSON), the 2nd (accessing to properties dynamically), and the 4th (running event handlers of HTML or XUL elements) - those three cases must be blamed because they possibly run untrusted scripts from the Web as privileged. This is just same to caution about SQL injections for web apps.

I totally agree this topic. I also think any developer must be careful to make eval isolated from the Web. If my addons are rejected because they have this security issue, I totally back the judgment up.

So, how about my cases?

Both addons, Source Viewer Tab and Tree Style Tab, use eval only for injecting codes to functions in Firefox (and other addons). They never get codes from the Web. If editors decided to reject those addons by the reason, like "This is dangerous because it includes eval! Eval can run codes from the Web!", then it means: they reviewed addons without reading codes, and just checks warnings by the "not perfect" validator.

If so, I cannot agree to the decision. We shouldn't overestimate the power of the validator on the AMO system, because it can detect only a few patterns which are defined as "dangerous". It doesn't parse the JavaScript, it only reports the matching result about simple regular expressions, it cannot detect dangerous codes from obfuscated programs.

You have to judge case by case whether the eval is danger or not. Same about XBL hacks, CSS hacks, replacing of functions, and others. "Yes, this doesn't use eval. I accept it." "Oh, this uses eval. This is wrong. I reject it." Such a rash judgment possibly jeopardize people who download addons from AMO. I believe that we should review sources by our eyes to detect dangerous code cleverly obfuscated, even if it take time.

Is injection by eval absolutely dangerous than other hacks?

All of evals in Source Viewer Tab and Tree Style Tab are used to inject codes to functions of Firefox, it is the 5th case described in the entry. In the entry, he blames this use because:

  • When the definition of the target function changed, terrible problem (crashing, data loss, etc.) possibly appear.
  • It possibly invites "already fixed" security issues again.

And, he said that we should use "less dangerous" ways like:

  • Use closure, and wrap up the original function by a new function. In the function, call the original function by func.apply(this, arguments).
  • Watch changes of values of some property by Object.watch().
  • If you cannot do it with those safer ways, you should not do it. Give up.

In other words, in the entry he said that "those ways are safer than eval".

I think it is an unfair suggestion. If you talk about risk of those cases, you should think other risks too, which are not listed in the entry. We also would like to avoid eval if at all possible. However, in our cases eval is the way really better than others.

Risk: possibilities of conflicting to Firefox features and other addons

Methods to extend Firefox can be sorted as:

  1. Using stable APIs provided by Firefox or other addons. (Toolbar buttons, sidebar panels, contents filtering by nsIContentPolicy like AdBlock Plus, Jetpack Features, etc.)
  2. Using other unstable ways.
    1. Using XBL hacks.
      1. Applying new XBLs.
      2. Replacing existing XBLs. (Tab Mix Plus, etc.)
    2. Using JavaScript hacks.
      1. Replacing existing functions. Using closure, wrapping up original functions in new functions.
      2. Hooking operations of existing functions by Object.watch() or other ways.
      3. Injecting codes to existing functions by eval.
    3. Using CSS hacks. (Personas, third-pirtys' themes, etc.)

One addon can use multiple ways above, but we can call it "safe" addon if it uses only "stable APIs". Otherwise they are possibly unstable. Any addon using unstable ways possibly breaks Firefox and other addons. Themes also.

He said that the "less dangerous" way is safer than eval. But, actually it possibly isn't. For example, I tried to watch the toggling of the Sidebar in Firefox 3.6, by document.getElementById("sidebar-box").watch("hidden", ...). Then it breaks the original behavior of XUL element - the Sidebar was never toggled. (So I had to use an event listener for the "DOMAttrModified" generic event.)

Another case, if you wrap the original function by a new function, any other addon which aimed to inject codes to the original function will never work. Hmm, "Because it is evil. Evil addons using eval must die!" Don't say that. It is the fact, you didn't take care about people who use addons with eval.

By the way, there are features which cannot be implemented without injecting codes into existing functions. Dorando told about those addons in the comments to the entry. The conclusion of the entry is "don't do it, you should not do it". However, if you cannot explain how dangerous eval is than others, it is just a tautology: "you should not do it, because it is wrong use of eval." and "it is wrong use of eval, because you should not do it."

Risk: possibilities of causing troubles with updating of Firefox

On this point, both methods (eval and the "less dangerous" way) have same risk. He said that eval will never work if the definition of the function changed. However, the "less dangerous" way will collapse too if the original function is renamed. It is just a bias that functions will be never renamed in security updates. There is no "rule" like this.

Moreover, if you wrapped two functions A and B, expecting they work as "A-mod => B-mod", the hack will break down if only one mate changed by security fix. We cannot imagine how terrible thing caused is. Not only updating of Firefox, but conflicting to other addons too.

Anyway, we addon developers must catch up changes in any update of Firefox. It is the common issue for any addon which uses unstable ways to extend Firefox. I think blaming like "how terrible eval is than wrapping original functions" is nonsense. More importantly, I believe that we should talk about providing failovers for unexpected matters.

To put it bluntly, any addon is just a "dynamic patch". If you use Linux, you possibly download patches from ML or other places, apply it to the source, and build binaries. It is not uncommon sight. And, it is also important note in those cases: Don't apply the patch to any revision different from the base of it. Using addons on unverified versions of Firefox is just same to that.

Risk: possibilities of less maintainability and/or readability

If we use eval hack, only "codes should be replaced" and "codes should be injected" will appear in the source.

Generally reading source codes like this is certainly hard, because we have to refer the codes of the function which is being overwritten. Instead, there are less codes and sources become compact. If it is very simple like replacing from "width" to "height", it will be human readable enough. So know-how to keep maintainability and compatibility is important for this hack.

Even if you choose the way to wrap original functions, only fragmentary codes will appear in the source too. "Pre-operations", "post-operations", "wrapping functions", "watching functions for property changes", and others. Moreover, if you cannot get the result of operations by the original function as its returned value, eventually you have to know well how the function work.

In this case, if you want to implement a feature which require injection of some codes into the logic of an existing function, you need to copy the complete codes of the original function into your addon (of course you have to modify it.) Then, too many codes are possibly duplicated, so:

  • You possibly cannot include the codes of the original function because their licenses conflict.
  • It possibly re-invite security issues fixed by updates of Firefox, as told in the entry.
  • Too many codes simply make themselves hard to be read.

Risk: possibilities of rejection by editors

This is common to the topic about maintainability. AMO editors finally have to review addons with reading of their sources. If there are tricky codes or too many/long lines, then the cost of reading source codes increases. On this point, both eval hacks and wrapping hacks are similarly tricky.

Although if updates of addons are always rejected by the reason: "there is any eval", then, it becomes a new common practice: writing codes without eval anyway, with tricky hacks, even if they become hard to read. Otherwise the update won't be accepted. It is also a tautology: "we should not use eval, because they never accept codes including eval." and "they don't accept eval hacks because we should not use it."

The conclusion

As I described, I think evals in Source Viewer Tab and Tree Style Tab are not unnecessarily. In other words I believe that those evals are the best way to implement the feature with keeping compatibility. I think those evals are not absolutely dangerous than the "less dangerous" ways described in the entry, and I also think there are no alternative ways to do it.

How many people who says "eval is dangerous than others" actually read and reading the source codes of Mozilla products? Trying to extend Firefox even if there is no stable API? Catching up updates of Firefox constantly? Trying to solve compatibility problems with other addons? I'm feeling blue.

Only XPCOM components are really stable APIs, which are marked "FROZEN" in their IDL files. Otherwise they are absolutely unstable. There are only a few "FROZEN" APIs, preferences I/O, W3C DOM, etc. JavaScript functions in the browser window are very unstable. Even the FUEL - which was the component advertised as providing stable APIs independent from Firefox versions - is possibly removed from the next major release of Firefox. Yes, this is the Mozilla. I think it is just a kidding: "eval is dangerous, wrapping original functions by new functions with the name same to originals is safer than it."

In conclusion, I think it is unjust treatment that addons are retained in the sandbox because "they have evals".


To reject spams, you have to answer a quiz to comment to this entry. "今の日本の首相の名字(ひらがなで回答)" means: the family name of the current prime minister of Japan, in "hiragana". You'll see the answer from wikipedia (Japanese version of the page).

Page 6/245: « 2 3 4 5 6 7 8 9 10 »

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のつぶやき