Now browsing the archives for the 'General' category.

Linuxテスト環境導入 これまでの経緯

2月頃
拡張機能開発の際にFirefoxのプラットフォームに依存した挙動に頭を悩ませることが多くなり、Windows以外のテスト環境の必要性を切実に感じ始める。

3月20日
VMWare Player(無料)をインストールし、Ubuntu 6.10 VMWare Image 日本語版をダウンロードして起動。いとも簡単にWinXP上でLinuxやFirefoxが使用可能になった。特に何も設定せずにインターネットにもつながるし、Windowsとのファイル共有も可能で便利。しかし、メモリ256MBのせいかUbuntu起動に7~8分近くかかり、動作が極端に遅く、使い物にならない。

3月30日
メモリ512MB(6000円程度のバルク品)を購入して増設。VMWare上でのUbuntuの起動が2~3分程度に短縮され、動作もかなりマシになった。マウスポインタの動きが早すぎで焦るものの、「xset m 1 10」とかやって解決。とはいえ快適といえるほどではなく、とくにタブを切り替える動作なんかにモッサリ感を感じる。また、これはVMWare Player側の問題だけど、ウィンドウサイズを覚えてくれなくて起動するたびに800×600くらいにリセットされるのが微妙に嫌だったり、全画面表示中にマウスを上の方に持っていくと、青いツールバーが表示されるのがかなりウザかったり。多分無料版だからか?でもワンタッチでWinXPとLinuxを行き来できる利便性は半端じゃない。

4月15日
CDから起動が可能なLinuxであるKNOPPIXを試す。KNOPPIX 5.1のISOイメージをダウンロードしてCD-RWに焼き、PCを再起動してCDのドライブから起動させる。しかし”No suitable X-Server found for your card”というエラーが出てXが起動しない。少し調べて、起動時に「boot: dynabook」と打ち込むことで無事解決。今回はVMWare上ではないのでさすがに動作は快適である。しかしインターネットにつながらない(設定方法がよくわからない)、ファイルを編集して保存しても、あとでWindows上から内容を取り出せない(もしかしたら可能かも?)などといった問題があり、開発環境としては不足。でも、Ubuntuと比べて画面の雰囲気とかがWindowsに近い感じで好き。

4月16日
第三の方法として、WindowsとLinuxのデュアルブート環境構築を試案中。でもパーティションを切る必要があったりして、やったことない自分にはハードルが高そう。

TOP

Software Design 2007年4月号

Software Design 2007年4月号

Software Design 2007年4月号
「Firefox拡張機能開発チュートリアル」の5章「Firefox拡張機能を作ってみよう!」を執筆しました。
現在発売中ですので、拡張開発を始めようとしている方は参考にしてください。

使用したソースコードはこちらで入手可能です。

TOP

拡張機能が設定値「browser.sessionstore.restore_prompt_uri」を変更することの危険性

先日開催された Firefox Developers Conference 2006 の個別セッションのコーナーにて、設定値「browser.sessionstore.restore_prompt_uri」を変更することで、クラッシュからのセッション回復時に拡張機能が独自にこしらえたプロンプトを使用することが可能となる、という話をして、実際にカウントダウン式のセッション回復プロンプトを動かすデモを行った。
これに関してPiroさんから、「拡張機能を削除して変更した設定値がそのまま残ってしまった場合、何らかのフォールバックはあるのか?」という指摘を頂いた。

調べてみたところ、nsSessionStartup.js の250行目あたりからを見ると、セッション回復プロンプトを開く処理は nsIWindowWatcher::openWindow() メソッドによって実行されていることがわかる。このメソッドの引数として「browser.sessionstore.restore_prompt_uri」の値を渡してウィンドウを開くのであるが、その値によって以下のような挙動となる。

存在するchrome: URI ウィンドウが開き、XULなどがロードされる。例えば、拡張機能独自のプロンプトが開かれる。
存在しないchrome: URI ウィンドウは開かず、何も起こらない。処理は先に進まない。
空の文字列 標準のセッション回復プロンプトが開かれる。
http: URI ウィンドウが開いてWebページがロードされる。ウィンドウのxボタンをクリックして閉じれば、セッションが回復する。
明らかにURIではない文字列 プロンプトは開かれず、セッションが回復する。これは openWindow メソッドで発生した例外をキャッチするフォールバック処理があるため。

やはり問題となるのは、拡張機能を削除した場合に存在しないchrome: URIが設定値として残ってしまうケースだろう。この場合の危険性は以下のような話に例えることができる。

Firefox 初級ユーザであるA君は、「Countdown Recovery」という拡張機能をインストールした。
すると設定値「browser.sessionstore.restore_prompt_uri」が「chrome://countdownrecovery/content/prompt.xul」に変更され、クラッシュからのセッション回復時に当該URIのプロンプトが開かれるようになった。
しばらくしてA君はこの拡張機能が気に入らなくなったので、アンインストールした。このとき、変更された設定値がそのまま残ってしまったことに、A君は当然気付くはずもなかった。
後日A君の Firefox がクラッシュしたため再起動したところ、何度試しても Firefox のブラウザウィンドウは開かれなかった。不思議に思ったA君は Firefox を再インストールしたが、結果は同じ。
困ったA君は Firefox 中級ユーザであるB君に助けを求め、セーフモードで起動しろというアドバイスに従って試したが、やはり Firefox のウィンドウは出現しない。これにはB君もお手上げ状態で、最後の手段としてプロファイルを作り直すしかないと判断した。A君は新しいプロファイルを作ることでようやく Firefox を起動することに成功したが、泣く泣くカスタマイズを一からやり直すこととなった。

この例え話で起こった症状は、Firefox を終了させた状態で prefs.js に書き込まれている問題の設定値を削除するか、あるいは sessionstore.js および sessionstore.bak を削除した上でセッション回復させずに Firefox を再起動し、about:config から設定値をリセットすることで解決される。

一般に、拡張機能をアンインストールしても、prefs.js に書き込まれたその拡張機能に関係する設定値などはそのまま残ってしまう。また、拡張機能が独自に生成したファイルなどのデータも当然残ったままだ。しかし、Piroさんの話では NoScript という拡張機能ではアンインストール時に何らかの処理を行う仕掛けがあるそうなので、さっそく調べてみた。

TOP

ライブブックマークとRSSフィードのプレビュー表示機能に関する考察

9月19日一部追記

Firefox にはライブブックマークという機能があって、それが人気の機能No.3であることは知っているが、実は自分はこの機能をまったくといっていいほど使ったことが無い。そこで、ライブブックマークについて少し調べてわかったことをまとめてみる。ただし多少推測も含みます。

  1. ライブブックマークを登録するにはロケーションバーのRSSアイコンをクリックしてブックマークへ追加する
  2. ライブブックマークはそのRSSを配信しているサイトをブックマークするのではなく、配信しているRSS自体をブックマークする
  3. ライブブックマークは、ブックマークメニューやブックマークツールバー上ではRSSアイコンとして表示されるが、サイドバーのブックマークツリーではなぜかフォルダやFaviconで表示される。
  4. ライブブックマークの更新はデフォルトでは30分毎に行われる
    (登録された全ライブブックマークの更新チェックがバックグラウンドで30分毎に行われるということ?)
  5. ライブブックマークが更新されているかどうかは、ブックマークメニュー、ブックマークツールバー、サイドバーのブックマークツリーのいずれかで、そのライブブックマークを選択して展開させてみないとわからない。
  6. そもそもライブブックマークの更新チェックは「前回更新チェックとの比較」ではなく、「常に最新の状態へ更新」するためのものである。したがってライブブックマークが更新されたかどうかは、ユーザが記憶に頼って判断しなければならない。

また、ライブブックマークに関連して、Firefox 2.0ではRSSフィードのプレビュー(整形表示)が可能となる。この機能についても以下のような疑問を抱いている。

  1. RSSフィードのプレビュー表示はあくまでもユーザに購読するための手段(ライブブックマークか、はてなRSSやLivedoorReaderといったWebサービスへ登録するかなど)を選択させることに主眼を置いたものなのか?「フィードの購読は常に○○○を利用する」を選択してしまえばそれ以降はプレビュー表示はされず、お役御免となるのか?
    だとすると、RSSフィードの内容を整形表示させる意味はあるのか?単純に購読手段を選ぶためのUIがダイアログで表示されるだけで良いのではないだろうか?
  2. あるいは、RSSフィードが Firefox で読めるようになるということに主眼を置いたものであるのか?例えば Sage のような拡張機能では今までは独自でRSSフィードを整形表示させていたが、 Firefox 本体に整形表示機能が搭載されたことにより、その必要がなくなるのだろうか?
    だとすると、購読手段を選ぶためのUIはかなり邪魔である。しかもユーザが購読手段を選択してしまうと、当然ながらRSSフィードのプレビュー表示は行なわれなくなってしまう。

TOP

XULのシングルクォーテーション内にDTDのエンティティを使用するときの注意

ScrapBookをいくつかの特定のロケールで使用している場合に「設定」→「データ保存先」の「参照」ボタンが反応しないという重大なバグが発覚した。原因は、XULのシングルクォーテーション内に埋め込まれたDTDのエンティティにシングルクォーテーションが含まれているため、文法エラーが発生することによる。下記の例をご覧ください。

sample.xul

<button label="Click me!" oncommand="alert('&sample.hello;');" />

sample.dtd

<!ENTITY sample.hello "やあ、'みなさん'こんにちは。">

このとき、シングルコーテーション内で展開されたエンティティ内にシングルコーテーションが含まれるので、以下のような文法エラーとなる。

エラー: missing ) after argument list
ソースファイル: sample.xul
行: 1, 列: 11
ソースコード:
alert('やあ、'みなさん'こんにちは。');

DTDのエンティティ内にどのような文字列が展開されるかは、そのDTDの作成者すなわち翻訳者しだいで予想が付かない。下記のように独自の属性の中にエンティティを埋め込むような回りくどいやり方にしたほうが安全である。

sample.xul

<button label="Click me!"
        oncommand="alert(this.getAttribute('alerttext'));"
        alerttext="&sample.hello;" />

ローカライズ可能な文字列を properties ファイルでなく DTD ファイルで定義するテクニックも今回の件と少し関連しているため、十分に注意が必要である。

TOP

ローカライズ可能な文字列を properties ファイルでなく DTD ファイルで定義するテクニック

一般的に、ローカライズ可能な文字列の定義は、以下のように2通りの使い分けが必要となる。

(1) XULファイル内で使用する文字列
DTD ファイル内に実体参照として定義し、XULファイル から DOCTYPE 宣言によって呼び出す。

(2) JavaScript内で使用する文字列
properties ファイル内に定義し、XULファイル から stringbundle 要素によって呼び出す。その例を以下に示す。

sample.xul

<stringbundle id="sampleString" src="../locale/sample.properties" />

sample.properties

sample.hello=こんにちは

sample.js

var sampleString = document.getElementById("sampleString");
alert(sampleString.getString("sample.hello"));

しかし、時にはわざわざ DTD ファイルとは別に properties ファイルを作るのが面倒なケースもある。そのような時、DTD ファイル内で文字列を定義し、XUL ファイル内に直接 JavaScript を書き込んでその中で実体参照を用いるというテクニックがある。この場合、JavaScript を CDATA セクション内に記述すると実体参照が行われないので注意する必要がある。

sample.xul

<!DOCTYPE window SYSTEM "../locale/sample.dtd">
...
<script type="application/x-javascript">
    var gSampleString = {
        hello : "&sample.hello;"
    };
</script>

sample.dtd

<!ENTITY sample.hello "こんにちは">

sample.js

alert(gSampleString.hello);

TOP

Firefox 2.0 Beta 1 ファーストインプレッション

  1. タブの閉じるボタン
    無くても我慢できるけど、あったらあったで便利そうではある。けど、タブがひとつしか無い時に閉じるボタンが表示されなくなるのは困る。何も見ていないときは空白タブにしておきたいので。
  2. タブオーバーフロー
    タブがあふれたときに表示されるボタンの大きさは適当だけど、その中の三角形が小さすぎて存在感が薄い。無いよりはましだけど決して使いやすいとはいえない機能。もっとましなユーザーインターフェースはありそうだと色々考えてみるものの、いいアイデアは浮かばない。
  3. 閉じたタブを元に戻す
    Undo Close Tabは今まで All-in-one Gestures に頼っていたが、本体に備わったのはうれしい。ただ、タブを右クリックしての操作はあまり使わないだろう。結局マウスジェスチャーに頼ることになりそうだ。
  4. メニューバーの履歴メニュー
    メニュー直下の「戻る」「進む」「ホーム」は間違いなく使わない。履歴10個表示も要らない。でも、新たに追加された「最近閉じたタブ」のリストはかなり重宝しそう。どうせなら「閉じたタブを元に戻す」をここに配置して欲しかった。
  5. RSS フィードの整形表示
    ありがたい機能。Sageは更新チェックだけやって、整形表示は Firefox に任せる、という使い方ができたらいいな。
  6. 検索プラグインの管理
    これはあって当然の機能だろう。欲を言えばセパレータの追加や、個々のエンジンを一時的に無効にする機能があればよかった。
  7. アドオンマネージャ
    拡張マネージャはよく使うけどテーママネージャはめったに使わないので、統合してもあまりうれしくない。自動でABC順に並ぶのは潔くて良い。選択している項目にはボタンが表示されるわけだが、項目を選択するといちいち縦幅が変化する動きがあまり好きでない。あと Firefox 1.5 でもそうだったが、項目クリック時の反応の鈍さも気になる。もう少し動作が軽くならないかな。
  8. フィッシング対策機能
    お世話になることは無いと思うけど、万が一に備えて有効にしておいた方がよさそうな機能。「ローカルに保存されているリスト」というのはウィルス定義ファイルみたいに定期的にアップデートされたりするの?
  9. クラッシュ時のセッション復元
    突然のクラッシュに泣かされることは少なからずあったので、これはありがたい。逆に、任意のタイミングでセッション保存や復元もできたらうれしい。
  10. インラインスペルチェック
    英語圏のユーザには重宝するかもしれないけど、今のところあまり必要性を感じない。 Firefox と打ち込んだだけでいちいち指摘されるし。デフォルトで無効、使いたいときだけ右クリックから有効にするようにしたい。
  11. Web検索ボックス
    検索エンジンの選択を右側のボタンから行うのは慣れないし、なんでわざわざIE7のマネして改悪するのだろう。と思いきや、今後のバージョンでは左側に戻されるようだ。そうなると、虫眼鏡ボタンはもはや邪魔なだけと思われる。userChrome.css で入力履歴のドロップダウン表示を可能にしている場合はなおさら邪魔だ。
    あと、今までは横幅狭すぎと思ってたら、今度は横幅広すぎになった。
  12. Web検索ボックスでのGoogleサジェスト
    一見面白い機能なんだけど、実際のところ、↓キーを押して候補から選択する手間を考えるとキーワードを入力しきってしまった方が確実だし速いに違いない。いちいちインターネット接続されるのもうっとうしいし。
  13. 検索プラグインのフォーマット変更
    今までのへんてこなSRCファイル+PNGアイコンの組み合わせからXML単独となり、すっきりした。POSTメソッドにも対応したもよう。旧形式との互換性はどうなんだろう?
  14. ブックマークのマイクロサマリ
    わかりづらい機能だし、こんなの誰が望んでいるんだろうと思っていたが、いつのまにか消滅した?
  15. JavaScript 1.7 のサポート
    色々変わったなかでも let は特に重要そう。あと、var [foo,bar] = “hoge<>huga”.split(“<>“); みたいなことができるのも良い。
  16. Client-side session, persistent storage
    面白そうだけどすぐには効果的な使い方はわからない。
  17. 新しいインストーラ
    どうでもいい。

TOP

タブに開いたchromeウィンドウからタブを閉じる

ブラウザタブに chrome:// のURLをロードして読み込まれた Window から、タブを閉じる方法。
単純に Window 内で window.close(); してやればタブは閉じられる。
しかし、タブが残りひとつであった場合、ウィンドウ自体も閉じられてしまう。
これを防ぐには、親のブラウザウィンドウを参照し、 cmd_close コマンドを実行すれば良い。
タブ内の Window から親のブラウザウィンドウを参照するには、 nsIWindowMediator を利用すれば良い。ただし、最後に使用したブラウザウィンドウが親のブラウザウィンドウであるという前提条件付きである。

var winMed = Components.classes['@mozilla.org/appshell/window-mediator;1'].
             getService(Components.interfaces.nsIWindowMediator); 
var browserWin = winMed.getMostRecentWindow("navigator:browser");
browserWin.document.getElementById("cmd_close").doCommand();

TOP

Mozilla Party 7.0 – プレゼンテーション資料

4月30日に Mozilla Party 7.0 が開催されました。そのときのプレゼンテーション資料はこちらへアップしました。

TOP