たまに18歳未満の人や心臓の弱い人にはお勧めできない情報が含まれることもあるかもしれない、甘くなくて酸っぱくてしょっぱいチラシの裏。RSSによる簡単な更新情報を利用したりすると、ハッピーになるかも知れませんしそうでないかも知れません。
の動向はもえじら組ブログで。
宣伝。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。
以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能!
次の版をリリースする前にやっとかなきゃ、と毎回毎回思いながら放置してた、ロケーションバーまわりの自動テストを昨日の晩からちょっとずつ作り始めてる。
どっちもUxU用のテストケースです。Firefox 3.1で導入されたキーワードによる絞り込みのテストは以前書いてたので、それ以外の、SQL文を生成したりとかデータベースから結果を取り出したりとかの部分のテストを今作ってる。
何故ずっと後回しにしてしまってたかというと、Placesのデータベースが絡んでくるから、Railsのfixtureみたいなのを上手くやれる仕組みができないことにはどうにもならないと思ってたせい。プロファイルを指定してテストを実行する機能を使えば問題ないんだけど、これはテストの実行がめちゃんこ遅くなるからなるべく使いたくないわけで……(←ひどい)
でもそれを言い訳にしていつまでも放置してる方が良くないよなと思ったので、一念発起して、Placesデータベースとの間でべったりだった所とかメソッド間の依存でシッチャカメッチャカになってた所とかを整理して、純粋にロジックだけの単体テストをしやすいように修正を進めてる。千里の道も一歩から……ちょっとずつ切り崩して、ゴールに近づいていこう。
最近ずっと仕事でまたRuby on Railsやってて、前は既に動いてたプロジェクトのお手伝いという立場だったんだけど今回はゼロからのスクラッチだったから、何か作ってはすぐテスト書いて……みたいなサイクルで作業してて、その影響だと思う。テスト書かなきゃ気持ち悪い、みたいな。
しかしずっとRubyばっか書いてたから、ついつい普通のハッシュでhash.each
とか書きそうになってしまったり、メソッドの最後のreturnを書かずに値だけ書いてしまいそうになったり、行末のセミコロンを書き忘れそうになったり、ハッシュの前後を囲うブラケットを書き忘れそうになったり、メソッドを呼び出す時に括弧を書き忘れそうになったり、function
と書くべき所をdef
と書きそうになってしまったり、だんだん思考が侵食されてきてて困る。Ruby脳の恐怖だ。
5日追記。
ダミーのデータだけを登録したplaces.sqliteを用意して、それを使って検索のテストを行うようにしてみた。SQLite Managerを使ったけど、結構めんどかった。fixtureをCSVかなんかで用意してテスト実行時に自動でSQLiteデータベースを作成する、みたいな機能がUxUに欲しくなってくる……
Firefox 3.1での仕様変更以来、SQLite Managerでplaces.sqliteを開けなくなってる件について、ホント困ってる。XUL/Migemoのデバッグとかに使いたいのに。問題として報告はされてるけどWontFix(修正予定無し)になってるし……
もう、SQLite Manager用のアドオンでも作るしかないか?
こうすればいいんじゃね?というコードの例をコメントに付けてみた。
追記。作者の人から早速反応があった。なんだ、単にやり方に気付いてなかっただけなのか…… コメントにも書いたけど、Cookieのデータベース(cookies.sqlite)はplaces.sqliteと同様にロックがかかってるにもかかわらず、コネクションオブジェクトが公開されてないから今の所まだアクセス不能のままだ。こればっかりはどうにもならない……Bugzillaの方にバグを立てて上手いこと説得できたら、Firefox 3.2とかそれ以降でなら対応してもらえるだろうか?
追記。バグ立てた。例によってC++のコードは僕は書けないので、どなたかヨロシク……
アドオン作者にとって、Mozilla Add-onsにアドオンを登録することには以下のようなメリットがある。
ただし、場合によっては「べつにAMOじゃなくてもいいじゃん」と言える事もある。例えば日本語圏のユーザに特化したアドオン、はてなのサービス専用のアドオンなどであれば、AMOにおける国際化や「グローバルを相手にアピールできるぜ」関係の機能のメリットはあまり意味がない。統計情報やセキュアな公開方法・更新方法(=SSL)、過去のバージョンの保存などを自前でできていて、ランキングやレビューも特にいらないということだったら、AMOに登録するメリットはほとんど無いということにもなるだろう。
それどころか、逆に、一般公開されるまでに審査待ちのタイムラグが生じるとか、そもそも一般公開されるために必要なレビューが集まらなかったりエディタの人に公開を承認してもらえなかったりすらする(今アクティブに活動してる人で日本語圏の人はいない状態だと以前聞いた)、そんな感じでデメリットの方が大きくなってしまうとも言える。
要は適材適所ということですね。
Browser chrome tests - MDC 見ながらなんとか環境整えてビルドしてテスト実行して……という風な事をしてみたけど、テスト結果のあまりのわかりにくさに閉口した。しかも一個テストがこけたら後の物も続けて失敗するし。クリーンなプロファイルで起動してくれるのはいいけど、あとがもうメタメタすぎて、とても常用(?)する気にならないよ……
というわけでUxUの次のテーマはFirefoxのソースツリー上にある自動テストを実行する機能ということにしたいと思います。
waitForExplicitFinish()
とfinish()
での非同期テストをサポートする。この辺が鍵でしょうか。
追記。概要をつかむために説明を翻訳した。これによると、「browser_*.js」という名前のファイルだけがブラウザ用のテストとして認識されるようなので、ファイル名がこのルールに一致していたら上記のような特別な処理を行うようにする、という感じで行けそう。
Firefoxタブ常用者のための最新エクステンションガイド - SourceForge.JP Magazine で「ツリー型タブを入れてるとTab History が無効になる」と書かれてたので「なに!」と思って入れてみたんだけど今の所特に不具合無く動いてるように見える。一応ソースも見てみたけど、特に衝突する点も無いような……一カ所「もしかして、ここか?」と思う所は無くもないんだけど。そこだけ次版で手を入れておくか……(追記:ツリー型タブ 0.7.2008120401で一応手を入れてみた)
その問題はさておき、Tab Historyは確かに良い。万人にお勧めできると思う。よくある「初心者ユーザがリンクをクリックした時に勝手に新しいウィンドウが開かれて、それが全画面表示になっているせいで、『元のページに戻りたいのに戻るボタンを押しても何も起こらないムキー!!!』となってしまう」という現象、のタブ版を防ぐ物だと言えるだろう。自分はよく、あるタブから子タブを開く→子タブを見ている間に親タブを閉じる→やっぱり親タブをもう一度見たくなる→閉じたタブを開き直す という操作をやるのだけれども、Tab Historyが入っていれば、子タブしか残っていない状態でも「戻る」ボタンで親タブで見てたページに戻れる。
ていうかソース覗いてみて思ったけど、これ作った人頭いいなー。タブが開かれる時に引数でリファラが指定されていたら現在アクティブなタブから開かれたタブであると見なしてセッションヒストリを引き継ぐ、という判定をしていて、最小限の変更で適切な動作になるようにしてる。まあリファラを偽装する系の他のアドオンと組み合わせた時には問題が起こるかもしれないけど。僕にもこういうピンポイントで問題を解決する力が欲しい。
あとPrint All Tabsにちょっと興味を引かれたので、マルチプルタブハンドラのタブ選択時のメニューに「選択したタブを印刷」を加えるようにしてみてる(Print All Tabsをバックエンドに使うので、Print All Tabsが入っていない場合は使えない機能となる)。
Ctrl-Tabとタブカタログを比較して良し悪しを語るのはいいんだけど、2年近く先行して開発された(一覧の表示方法を現行の形式に変更した時で比較しても、約1年先行)物をとっつかまえて、後から出た物の劣化品
呼ばわりは、さすがに無いと思うんだ。「時代遅れ」なら許せる。
あと、タブカタログが劣化品と言うなら、Ctrl-Tabのサムネイルの上で右クリックした時にタブの上と同じコンテキストメニューくらい出して欲しいです。
コンテキストメニュー拡張を久しぶりにアップデートした……けどアップデートの内容は実質デグレードみたいなものだ。外部アプリケーションでソースを表示する機能、mailto:のリンクをメールソフトやWebメールのサービスに渡す機能、ユーザスタイルシートを編集する機能、任意のスタイルシートを登録して切り替える機能、あたりをゴッソリ削除した。
できれば無駄にRDFを使ってるバックエンドも全部捨てたいんだけど、これを捨てると旧版の設定が全部失われてしまうことになるというのが痛い。
ツリー型タブとマルチプルタブハンドラで、Firefox 3.1からの「ウィンドウ外にタブをドロップしたら新しいタブを開く」機能に対応した。子タブを持っているタブをウィンドウ外にドロップしたら子孫タブまで含めて新規ウィンドウに分離され、複数のタブを選択してウィンドウ外にドロップしたら選択されたタブすべてが新規ウィンドウに分離される。という感じ。ちょっと前の分割ブラウザの更新もこれに関係してる。
Minefield 3.1b3preでは、ブラウザのタブをドラッグした時はapplication/x-moz-tabbrowser-tabという型のデータがドラッグデータのリストの先頭に加わるようになった。今までは、ドラッグセッションの「ドラッグを開始した要素」をその都度参照していたようだったので、やっとまともな実装になったなーという感じだ。
分割ブラウザやツリー型タブでは、この型のデータも受け入れ可能なように修正した。そうしておかないと、「application/x-moz-tabbrowser-tab型のデータはドロップできないんだな」と判断されて、タブをタブバーや分割された領域にドロップできなくなってしまう。
Minefield 3.1b3preでの「ウィンドウ外へのドロップ」はどのように実装されているのかを調べてみた所、dragendイベント(ドラッグが終了した時に、「ドラッグが開始された要素」で発行されるイベント)のタイミングで、ドロップ操作に失敗した(ドラッグ操作終了時点でポインタの状態が「ここにはドロップできません」のポインタになっている)場合には「ウィンドウ外へドロップされた」と判断して、新しいウィンドウを開きそのタブとドラッグ元のタブを入れ替える、という風にして実現していた。
この時ドラッグ元のウィンドウでは、tabbrowser要素の_replaceTabWithWindow()
メソッドにおいて、新規ウィンドウの第1引数にtab要素を渡して開くだけで処理を終えている。そこから先の「ドラッグ元のタブと新しいウィンドウの内容の入れ替え」は、新しく開かれたウィンドウの初期化処理(BrowserStartup()
関数)の方でやってる。
なので、ツリー型タブとマルチプルタブハンドラでは、その両方の処理に割り込むようにした。_replaceTabWithWindow()
を呼び出している_onDropEnd()
メソッドで、_replaceTabWithWindow()
メソッドを呼ぶ直前に割り込んで、切り離されようとしているタブの収集結果がそのウィンドウのタブ全部だった場合には操作をキャンセルしている。また、BrowserStartup()
の方では、ウィンドウの第1引数がtab要素だった場合はまずツリー型タブとマルチプルタブハンドラに処理を渡して、何も行われなければ(渡されたタブが子タブを持っておらず、選択もされていないならば)Firefox本来の処理(単一タブの切り離し)に入る、という感じにしている。
ドラッグ元のタブ自身の上にドロップした時までウィンドウの切り離しになってしまうなど、Minefield 3.1b3preの当該機能自体がまだまだ作り込みが甘い感じなんだけど、そういう所にまで手を出すと収拾がつかなくなる&Firefox 3.1正式版までの間に手を入れられたらまた作業のやり直しになるので、そこら辺は基本的に放置してる。ただし複数のタブを同時に閉じようとした時の問題だけは、閉じるのに失敗したタブが永遠に閉じられなくなるなどの致命的な問題を引き起こすので、ツリー型タブの側で対処している(提出したパッチと同じ事をやってる)。
英語で書かれた障害報告のメールに返信する時にルーラーがひどくずれていたのが気になってたけど放置してた件について、ルーラーバー 0.3.2008120101で修正した。
今まで、ルーラーの表示サイズの基準には編集領域のdocument.documentElement
のfont-size
を使ってたけど、こちらはエンコーディングが変わっても値が変化しない。それに対して、document.body
のfont-size
は、エンコーディングごとのフォントサイズの違いの影響を受ける。ということでbodyの方の値を参照するようにしたら、ルーラーの間隔はおおむね正しいものになるようになった。
ただ、これでもカーソル位置の強調表示のずれは残る。フォントサイズだけでなくフォント自体もエンコーディングによって変わる可能性があり、フォントサイズだけ合わせても、実際の編集領域とカーソル位置検出用の非表示のフレームとでフォントが違ったら、ピクセル単位で位置を拾った時に微妙にずれが発生する可能性がある。そこで、非表示のフレームの方にもエンコーディングの変化を適用させるために、SetDocumentCharacterSet()
のタイミングで非表示のフレームの方のエンコーディングも変更するようにした。エンコーディングの動的な変更の方法はこんな感じ。
// this.calculator は非表示のフレームのbrowser要素
var docCharset = this.calculator.docShell
.QueryInterface(Components.interfaces.nsIDocCharset);
docCharset.charset = aCharset;
var webNav = this.calculator.webNavigation;
webNav.reload(webNav.LOAD_FLAGS_CHARSET_CHANGE);
var self = this;
this.calculator.addEventListener('DOMContentLoaded', function() {
self.calculator.removeEventListener('DOMContentLoaded', arguments.callee, false);
// 読み込みが終わった段階でルーラーの表示を更新する(カーソル位置の検出をやり直す)
self.updateRulerAppearance();
}, false);
最後にリロードしないと表示が変わらない、のかな?(リロードしなかった場合の挙動については未検証)