PopupNotification.jsm を使うにあたっての注意点

Mozilla Vision 2012 のライトニングトークでも話したんだけど、PopupNotification.jsm を使うに当たってはドキュメント化されていない注意点とかバグが結構あったりする。
自分でこうしたバグを踏むかソースコードを熟読すれば回避できるバグなんだけど、そんなのいちいちやってられないし、ドキュメントが整備されていないんじゃせっかくの機能が勿体無いので、簡単に注意点とかをまとめておくことにする。
いずれ MDC かどこかに反映はさせたい。

独自のアンカーアイコンを設定する際の注意点

XUL アドオンの定石に則れば、以下のようにオーバーレイすればいいと思いがちだったりする。

  <box id="notification-popup-box">
    <image id="hoge-notification-icon"
           class="notification-anchor-icon"
           role="button"/>
  </box>
#hoge-notification-icon {
  list-style-image: url("chrome://hoge/skin/hoge-notification-16.png");
}

けれども、アンカーアイコンの表示を行うためには、 CSS をさらに指定する必要がある点に気を付けなければいけない(mozilla-central mozilla/browser/base/content/browser.css#437~445

#notification-popup-box[anchorid="hoge-notification-icon"] > #hoge-notification-icon {
  display: -moz-box;
}

あんまりスマートじゃないけど、仕方がない。

Bug 641892 – Support showing multiple popup notification icons at the same time が修正されたことで、この記述は不要になった。あっても動作するので互換性も問題なし。

複数のアンカーアイコン(doorhanger 通知)を表示できない

これは現在の所は By Design 。一応アサインされていて、且つパッチ自体も第一稿が上がってはいる(Bug 641892 – Support showing multiple popup notification icons at the same time)。
これが直らないと複数のdoorhangerを表示できないので、ジオロケーション API の許可の確認を出した状態で、Indexed DB の使用許可の確認を取ることができなかったりする。

件のバグが直ったんで、Firefox 15からは問題なく複数表示可能になる。

タブを異なるウィンドウ間で移動させたときに、doorhanger表示が引き継がれない。

タイトルの通り。具体的には、

  1. Google Map でジオロケーションの許可通知を出す
  2. 異なるウィンドウを開いて、そこに 1 のタブを移動させる
  3. doorhanger 通知が表示されない(ページ中の状態は変わらない)

みたいな感じ。

PopupNotifications.show() の第4引数に"default-notification-icon"と指定すると、アンカーアイコンが表示されない

これもタイトルそのまま。MDCのドキュメント中では、「nullと指定すると、PopupNotification オブジェクトのアイコンボックスが表示される(chrome://global/skin/icons/information-16.pngが表示される)」とあるんだけど、じゃあ、"default-notification-icon"と指定するとどうなるかというと、アンカーアイコンが表示されない。
理由は単純で、mozilla-central mozilla/browser/base/content/browser.css#437 で、#notification-popup-box[anchorid="default-notification-icon"]の場合を指定していないから(anchorid属性が、通知のアンカーIDになる)。
APIとしては実装ミスだと思う。

Notification Action の accessKey に空文字列を指定するとエラーが投げられる

Notification Action に指定されたメンバを持ったオブジェクトを、PopupNotifications.show() に渡すことで、通知のアクションを指定するようになっているんだけど、必ずしもアクセスキーを付けるケースばかりじゃない(もちろん本当はつけた方が良いだろう)。そういう場合に、accessKey プロパティに空文字列を指定すると、エラーが投げられてしまう。
これは mozilla-central mozilla/toolkit/content/PopupNotifications.jsm#237 の実装が問題。
accessKey プロパティが文字列かどうか確認すればいいのに、単純にNOT演算子で確認してるためにアウトになってしまっている。
暫定的な回避方法としては、空白文字をプロパティに設定すればよい。

アクセスキーが重複すると衝突するものだと思っていて、それに基づいてaccessKeyの確認処理を修正するパッチを送ってみた( Bug 688142 )んだけど、そもそもXULのアクセスキーはフォーカスが当たっている要素から親の方に順にたどる実装らしいので特に衝突するわけでもなく、「引数の型のチェックを厳密にした方が良いんじゃないの?」とツッコんでみても「JSで使える(アドオンから使える)APIでは、型チェックはゆるい方針。nullが許可されてるか不明な状況でのチェックのように、よくあるミスを調べる意味でのチェックは行う」( Bug 688142 comment13 )とのこと。
配列とかオブジェクトを間違えて入れていないかチェックするコードも考えたけど、処理が少し長くなるうえに発生頻度は少ないケースだろうから、実装しても釣り合いが取れないので、蒸し返す理由もない。

Notification Action のコールバック関数のthis

別に Notification オブジェクトだったりはしない。
mozilla-central mozilla/toolkit/content/PopupNotifications.jsm#597Function.call() を使って呼び出してるんだから、thisNotification オブジェクトにしてくれれば、コールバック関数内でNotification.remove()とかできて便利なのに。
ちなみに、Notification options の eventCallback は、thisNotification オブジェクト だったりする。ずるい。