Gecko1.8を利用した製品は、Firefox1.5やThunderbird1.5です。
この文書は、Mozilla Japanの公式文書ではありません。 また、内容はエンドユーザ向けではなく、開発者向けのものとなっていますのでご注意ください。
Gecko 1.7(Firefox1.0のベースとなったコード)のリリース時、既に私は失業してまして、 時間があったことからBugzilla-jp上の話の流れで、私がとあるバグをハックすることになりました。 そこから、始まった私のバグ修正の内、ここではGecko 1.7以降、Gecko 1.8で修正したバグの紹介を行います。
ちなみに、私はMozilla Japanのメンバーとして(Mozilla Japanの仕事として)修正作業を行っていますので、 このリストはMozilla JapanがMozilla Foundationのプロダクトに対してどのような貢献を行ったのか、 というリストの一部と考えてもらってもかまいません。
ですが、どのバグをどのように修正するのか、その仕様は私の裁量に任されています。 そのため、ここで紹介する内容の詳細はMozilla Japanの会社としての方針と一致するとは限りません。 ですので、修正内容等に対してご意見、ご不満がある場合、 Bugzilla-jp からバグとして報告をしていただいて、より良い改善案を提案していただければ柔軟に対応できるかと思います。
Windowsのみのバグ。
ATOKでCtrl+Back Spaceを押すと、確定アンドゥという操作になるのだが、これがうまく動作しなかった問題。
ATOKは確定アンドゥの際、Back Spaceキーが押されたことをエミュレートして、 直前の確定文字列を削除しようとするのだが、このエミュレートの質が悪かったことが原因。
通常、一回キーが押されると、WM_KEYDOWN、WM_CHAR(× n回)、WM_KEYUP
という順序でメッセージが来るのだが、ATOKはこのシーケンスの間にIMEの関連メッセージ等を含めているため、
Mozilla側では、Back Spaceキーが数回押されたとは認識されなかったというバグ。
Gecko 1.7では、Mozilla側の設計上、これをATOK側の意図通りに処理しようとすると、 強引な修正が必要だったのだが、そのパッチでは、ATOK側のバグで、クラッシュしたり、 Win32APIに期待通りの反応をしなかったり、という難題があった。
しかし、Gecko 1.8において、別のバグで設計が変更されたのでより単純なパッチが提案でき、 これが採用された。
パスワード入力欄にフォーカスが移動しても、IMEがオンになったままだと不便があるので、 パスワード入力欄ではIMEはオフになった方が良い、というバグ。
Mozillaの目に見えるウィジェットが、OSにおけるひとつのウィジェット、とはなっていない。 フレームがある場合を除き、原則、ひとつのWebページは、ひとつのウィジェットとして作成されている。
このため、解決方法としてはMozillaのウィジェット間でフォーカス移動があった時にIMEを制御して、 擬似的に複数のウィジェットが存在しているかのようにエミュレートするしか無い。
そこで、nsIKBStateControlインターフェース経由で、 各OS上でのウィジェットの基本単位と一致するnsWindowもしくは、 nsWidgetがIMEをオンにしたり、オフにしたりしてIMEを制御する方法が考えられた。
nsIKBStateControlの持つメソッドを、Mozilla内部では(XPコードに対する)IME APIと呼んでいる。 現在、IMEをON/OFFするAPIはWindowsでのみ実装されており、Windows以外ではこのバグは修正されていない。 (Windows以外でも、このAPIを実装することで対応できる。)
結果として、Windowsではパスワード入力欄にフォーカスが移ると、IMEが自動でオフになり、 パスワード入力欄がフォーカスを失うと、IMEが自動的に直前の状態に戻るようになっている。 ただし、パスワード入力欄でIMEを使用した場合、フォーカス喪失時のIMEの状態の復元処理は行われない。
WindowsのnsWindowクラス内でのIME関連のバッファがインスタンスごとに確保されるため、メモリが無駄に使用されていた。 また、コードが非常に古いため、汚く、複雑になっているのでUnicode化して単純化した方が良いという提案。
Mozillaでは、フォーカスを失うときに、IMEを強制的に確定させるため、複数のウインドウがIMEの未確定文字列を同時に保持することがありえない。 つまり、IMEに関する情報は静的な変数で十分ということである。
詳しい内容は採用されたパッチを参照。
Windowsで再変換が全く利用できなくなったというregression。
原因はDOM Eventの実装のクリーンナップ作業において、再変換処理の分岐が忘れられていたため、 再変換処理が発生した場合に、何の処理も行われずに失敗していたことが原因。
採用されたパッチを見れば分かるように、単なるケアレスミスである。
エディタ以外にフォーカスが当たっている時に、IMEの入力を行いエディタにフォーカスを移すと、 エディタで一文字入力する度に、前の未確定文字列が再出力されてしまうというバグ。
原因は実はよく分かっていない。フォーカス移動時にIMEは強制確定されるのがMozilla上での仕様なので、 新たにフォーカスを受け取ったエディタから見れば、 前のウィジェットで入力された未確定文字列は既に破棄されているはずなのだが、 それを取得してできていておかしくなっている。
原因が全く分からないのでエディタがフォーカスを受け取った時に直前のIME入力を強制的にキャンセルし、 未確定文字列を破棄することにした。
nsIKBStateControlにCancelIMECompositionというAPIを追加し、
エディタがフォーカスを受けたときは常にこれを呼ぶようにしている。
このAPIはWindowsとMacのCamino用のコードで実装された。
MacのCamino用のコードを書いたのは私ではなく、waveriderさんである。
WindowsNT上でJapanistというIMEを使って再変換を行うと、未確定文字列が文字化けしてしまうというバグ。
Japanistでは再変換にWM_IME_REQUESTメッセージを使っている。
Mozillaはこれまで、このメッセージに対しては、常にシステムのデフォルトの文字コードで選択文字列を返信していたのだが、
MozillaのウインドウがWindowsNT上ではUnicodeウインドウとして生成されているためか、
JapanistはUnicodeで選択文字列が返されることを期待しているようである。
そこで、NT上で動作している場合にはUnicodeで返すように修正した。
ちなみに、私の知る限り、WM_IME_REQUESTを使った正攻法の再変換処理を行っているのは
このJapanistだけなので、今のところ副作用は報告されていない。
(MS-IMEとATOKはそれぞれ、独自の専用メッセージを使って、常にUnicodeでやりとりしている。)
Webページを表示しているウィジェットにフォーカスがある時に、 WindowsのMS-IME 2002/2003を利用していて、詳細なテキストサービスを無効にしておくと、 ロケーションバーのドロップダウンをマウスで開こうとしても、一瞬で消えてしまうが、 ロケーションバーにフォーカスが当たった後は正常に開くことができるというバグ。
Mozillaはドロップダウンリストのようなポップアップウインドウが開いているときに一部のメッセージを受け取ると、 ポップアップウインドウを閉じてしまう。
MS-IME 2002/2003は上記の条件の時、フォーカスが移動するときに移動した先のウインドウに、
本来送信する必要のないWM_GETMINMAXINFOを送信するようになっている。
このメッセージを受け取ったウインドウは最大化された、もしくは最小化されたということなので、 Mozillaの挙動は妥当なものだった。つまり、本来は、トップレベルのウインドウのみが受け取るメッセージである。 しかし、MS-IMEによって本来このメッセージを受け取ることがないはずのトップレベルではないウインドウにもメッセージが配信されており、 これが問題になっていることから、非トップレベルのウインドウがこのメッセージを受け取った場合は、 ポップアップウインドウを閉じないように制限を加えることで解決した。
Firefox1.0PRではウインドウ右上の検索ボックスでIMEの入力が未確定のままフォーカスを移すとクラッシュしていたというバグ。
KENZさんが緊急回避用のパッチを提供 してくれていたため、Firefox1.0のファイナルリリースでは再現しなくなっていたが、 原因が不明なままではいけないし、今後の再発防止のためにも原因を究明し、根本的なところで修正することにした。
KENZさんのパッチを頼りに、周囲を調査した結果、オートコンプリートのコードが想定していたイベントの発生順序と、 実際の順序にずれがあったことが問題と判明。
まず、オートコンプリートを管理しているオブジェクトは、 ターゲットとなるエディタがフォーカスを持っている間だけそれに関連づけられている。 つまり、エディタがフォーカスを失うときに、オートコンプリートのオブジェクトは関連づけを解除される。
普通に考えれば、フォーカスを失っている時に、テキストの入力イベントは発生しないので、 テキストの入力イベントが発生した時には、 オートコンプリートのオブジェクトとエディタは常にリンクしていると考えられるのが自然だ。
だが、Mozillaはエディタがフォーカスを失う時にIMEを強制確定させている。 これによる確定文字の入力イベントがフォーカスを失ったイベントの後に発生しているため、 オートコンプリートのオブジェクトとリンクしているポインタが既にNULLになっていて、 これに無警戒にアクセスしていたのでクラッシュしていたのだ。
より根本的な問題解決方法はイベントの順序を変更することであるが、 私がイベントのメカニズムをあまり理解できていなかったので、 とりあえず入力イベント時にオートコンプリートのオブジェクトを示すポインタが有効かどうかを常にチェックするように修正した。
再発防止のために、イベントの順序の問題も修正する予定ではあるが、現在の所、優先順位は低い。
WindowsのATOKではキャレットの下に入力ステータスを示す、ATOKナビというツールバーが表示されるのだが、 Mozillaではこれが表示されなかった問題。
原因を調査するため、Spy++を使ってメッセージを監視してみると、WM_IMEREQUESTのIMR_QUERYCHARPOSITIONを使って未確定文字列の表示位置を取得していることが推測できた。
Mozillaではcomposition windowという未確定文字列を表示するIMEが制御するウインドウの生成を抑制しており、 その代わりに独自に未確定文字列の描画を行っているため、 表示すべき位置を調査するために発行されたメッセージのようだ。 (だから、通常のアプリでは、このメッセージは発行すらされていない。)
他のIMEイベントではキャレット位置をnsWindowが取得できていたので、同じ手法を使って、 新たな専用イベントで、キャレット位置を取得し、このメッセージに応答できるようにしたことで解決した。
WXGにも似たような機能があるので、これにも対応するように、パッチを作ったのだが、それが次のregressionを生むことになった。
上記バグの対応で、WXGのナビキャレットの入力位置への表示にも対応したのだが、 これが深刻な問題を生んでしまった。
MozillaはIMEの管理するcomposition windowの生成を抑制しているにもかかわらず、 これが表示されてしまうことがある上に、WXGがこれを必要無くなっても消去しないという問題が見つかった。
WXGでは変換結果に注釈がある場合、それを表示する機能があるのだが、 これがATOKのように通常の未確定文字列に埋め込むという手順を踏まずに、 IMEが独断でcomposition windowを生成して表示する上、 それを消すべきタイミングに、適切に消すことを怠っていたというのが原因。
おそらく、強制的にcomposition windowを表示してしまうのはバグで、 Mozillaがcomposition windowの生成を抑制しているので、 composition windowの管理をしなくても良い、と考えて動作しているのではないかと推測される。
原因はさておき、結果として変換が終了しても注釈を表示したcomposition windowがずっと表示されたままになり、 次のテキスト入力や表示に深刻な影響を及ぼしていた。
結局、対応策が見つからないので上記のバグで入れた修正から、 WXGのために入れたコードのみを取り除き、 ナビキャレットへの対応を断念した。
Win9xで、IMEや入力ロケールの切り替えができなくなっていた問題。
Windowsのさまざまなツールとの親和性を高めるために、ウインドウのクラス名を変更したのだが、 古いクラス名のまま、IMEが利用可能なウインドウのフィルタリングを行っていたのが原因。
単純に新しいウインドウクラス名でフィルタリングするように修正しただけ。
ちなみに、(本来はすべきではないことだが)このバグで同時に、韓国語のIMEでクラッシュするバグを修正している。
このクラッシュバグは私のBug-org 253035による修正が原因のregressionである。
本来、IMEのWin32APIの仕様では、未確定文字列一文字以上(韓国語のIMEの場合、一文字しか無いのだが)ある場合には、 未確定文字列の文節情報を取得すると、その文字数分、情報が返ってくるはずなのだが、 MSの韓国語用IMEはこの仕様を無視していて、未確定文字列がある場合であっても、 文節情報は全く返されなかった。つまり、あたかも未確定文字列が無いものとして返されていたのである。
このため、未確定文字列がある場合に本来作成されているはずの配列に無警戒にアクセスしていたのがクラッシュの原因だった。
オートコンプリート用の候補ウインドウが、IME用の候補ウインドウの上に表示されるため、 IME用の候補ウインドウが使えない、というバグ。
WindowsとMacでのみ発生する問題だったので、当初、オートコンプリート用の候補ウインドウがこれらのOSでのみ最前面表示されていることが問題だと考えた。 そのため、新しいウインドウの種類を作成し、最前面表示ではないポップアップウインドウを生成できるようにしようと考えたのだが、 とてつもなく膨大な作業になることが分かり、途方に暮れていた。
そこで、IEではどのようにしてこの問題に対応しているのだろうかと気になり、テストしてみた。 するとIEでは、IMEの未確定文字列が入力されるとオートコンプリート用の候補ウインドウが消えるではないか。 とても賢明で、シンプルな解決方法である。
そこで、Mozillaでも未確定文字列の入力が始まったらオートコンプリートを終了するようにした。 もっとも、これは言葉で言うのは簡単だが、実際には様々な副作用があり、 修正パッチは非常に大きくなっている。
WindowsのATOKでIMEをオンにして、パスワード入力欄で入力を行うと、見えない、しかも消せない文字が入ってしまい、 フォームの送信で送信されてしまうというバグ。
これもATOKの奇妙なメッセージ送信に原因があった。 しかも、Mozillaの方もアプリケーションがでたらめなメッセージを送信してくる可能性がある、 ということを警戒していないために発生していた。
MSDNによると、IMEの未確定文字列の入力開始時にはWM_IME_STARTCOMPOSITIONが送信され、
実際の変換操作はその後、WM_IME_COMPOSITIONで通知されるとある。
しかし、ATOKはWM_IME_COMPOSITIONをWM_IME_STARTCOMPOSITIONよりも前に送信しているのだ。
この時、MozillaはWM_IME_STARTCOMPOSITIONも同時に受け取ったものとして処理するのだが、
その後、WM_IME_STARTCOMPOSITIONを実際に受け取るとIME関連の初期化処理を再度実行してしまっていた。
しかも、その再初期化処理が中途半端で、完全に元の状態に初期化できていないのが、見えない文字を生むことになっていた。
そこで、IMEの処理中にWM_IME_STARTCOMPOSITIONを受け取っても再び初期化処理が走らないように修正して解決した。
ATOKナビを表示するようにして、エディタ以外でIME入力を行うとクラッシュするというバグ。
Bug-org 278061によるregression。 エディタ以外では、正常なキャレット座標が返らないのに、 常に正常にキャレット位置を取得できることを前提に処理していたのが原因。
WindowsのATOKの文字パレットからエディタに入力できないというバグ。
Windowsでも通常のソフトウェアキーボードでは問題無いのだが、ATOKの文字パレットは、 これ自身がフォーカスを持つことができるウインドウであるという点が通常のソフトウェアキーボードとは違っていた。
Mozillaがフォーカスを持たない場合、最後にフォーカスのあったウィジェットにキー入力、 IME入力のイベントを送信していないのが原因で、似たような問題としてUNIXのIMEの候補ウインドウがフォーカスを奪うことで、 確定した文字が入力できない、という問題が過去に発生していて、 そのときにSun Microsystemsの片貝さんが修正してくれていた。
だが、その修正の副作用を警戒してUNIX以外のOSではコンパイルされないようにしてあったので、 これをWindowsでもコンパイルするようにすることで修正。
Macでは今のところ似たような問題を確認できない、ということだが、もし発生すれば、 これをMacでもコンパイルするようにすれば解決できるだろう。
Windowsで再変換が行われたときに、MS-IME2003では再変換に失敗したり、 Win9x上でATOKを使って再変換するとクラッシュすることがあったというバグ。
MSDNによるとdwSizeに、IMEに返す文字列の長さも含めた構造体のサイズを返すように記載があるのだが、 Mozillaは単純に構造体のサイズを返していたのが原因。
Windowsで再変換が行われたときに、再変換のメッセージに応答する時に必要な、 選択された文字列の情報を再変換処理が終了しても解放していなかったというバグ。
再変換の応答に成功したら、必ずIMEの変換処理が開始されるので、その初期化の際に、このバッファも解放するように修正。
文字列を選択した状態でIMEの入力を開始した後、アンドゥすると、バッファが壊れていて、正常にアンドゥできなくなるというバグ。
Mozillaのエディタのアンドゥのためのトランザクション処理は複雑で未だに理解できていない。 しかし、デバッグ実行で流れを追いかけると、明らかに期待に反する判定を行う場所があった。 詳しくは採用されたパッチを見て欲しい。 パッチを提案した私もよく理解できていないので説明できない。
ただ、この条件を消した方が、アンドゥがより、直感的にトランザクションを切るようになり、 この条件を追加した元のバグも再発することがなかったので、ゴーサインが出るに至った。
FirefoxのFAYTでIMEが使えなかったというバグ。
Firefox1.0になる直前に、突然、FAYTのコードが大修正され、国際化対応することができないままにリリースされてしまった。 Mozilla Foundationの国際化問題に対する意識の低さが問われたバグである。
もともとSuite(現SeaMonkey)から移植されたC++のコードでFAYTは実装されていたのだが、 Find Toolbarの実装に伴い、FAYTのフロントエンドの処理をJavascriptで処理するようになった。 この時、英語圏の開発者らしい誤解で、キー入力 == 入力文字確定という考え方を元に、 ブラウザウインドウに入力されたキーコードを文字に変換し、 それを確定文字としてそれをFind Toolbarのエディタに入力していた。
しかし、IMEを使わないヨーロッパですらこの前提は成り立たない。 キー入力が単なる文字の入力中であるという状況がすべて無視されていたため、 ヨーロッパでもアクセント記号付きの文字を入力できないという問題が出ていた。 (キーボードのレイアウト次第では、先にアクセント記号を入力し、 次にアルファベットを入力することで入力が確定するという入力方法がある。)
このような複雑なキーボードからの入力処理をJavascriptで完全に実現するのは不可能に近い。 そこで、FAYTが開始されたら、Find Toolbarのエディタにフォーカスを移動させ、 エディタに入力処理をさせようという案を提案した。
その代わりにFAYTで発見したリンクにはCSSのoutlineを利用して、動的に擬似フォーカス(pseudo focus)を持たせることにした。
リンクが発見されている状況で、Enterキーが入力された場合は擬似フォーカスを持つリンクにフォーカスを移動させ、 Enterキーの入力イベントを再発行してやることで、元の機能を完全に再現したわけである。
WindowsでMSの中国語用のIMEで句読点(と呼ぶのかな?)を入力すると、 その後は文字入力以外のキー入力(矢印キー等)が無視されていたバグ。
中国語のIME、MS PinYinでは一文字入力した段階で確定してしまう文字の場合、
WM_IME_STARTCOMPOSITIONとWM_IME_ENDCOMPOSITIONを送信せずに
WM_IME_COMPOSITIONのみを発行していたのが原因。
先に述べたようにWM_IME_STARTCOMPOSITIONが発行されなくても、
WM_IME_COMPOSITIONが発行されると、MozillaはIMEの入力処理を強行する。
しかし、WM_IME_ENDCOMPOSITIONが来ないことは想定されていなかった。
つまり、未確定文字は無いのにずっとIMEの入力待ちが続いている状態になっていたのである。
そこで、WM_IME_COMPOSITIONの処理後、未確定文字列が無かったらWM_IME_ENDCOMPOSITIONも
発行されたものとして扱う様にし、副作用防止のために、IMEの入力中以外に、WM_IME_ENDCOMPOSITIONを受け取った場合には
この終了処理が再実行されないようにコードを追加している。
FAYTでフレームで分割されたページのリンクを発見しても、擬似フォーカスが表示されなかったバグ。
検索結果の選択位置を取得するメソッドを実行する前の初期化処理が不十分で、 このメソッドが失敗して、処理が中断し、正常に検索結果を取得できないことがあったのが原因。
このメソッド内で初期化が不十分であれば、初期化するように修正することで対応。
FAYT中にEnterキーを押すと、FAYTは終了し、入力受付も終了しているのに、 Find Toolbarが表示されたままであたかも入力を受け付けているかのように誤解を与えるというバグ。
FAYT終了時には常にFind Toolbarを閉じるように修正した。
FAYTではなく、Ctrl+Fによる通常の検索でリンクを見つけた後、 EscでFind Toolbarを閉じてもそのリンクにフォーカスがセットされないのは不便なので改善して欲しいという要望。
Bug-org 259454が修正されるまでは、発見したリンクに設定されるのが、 擬似フォーカスではなく、本物のフォーカスだったのでこの要望は実現不可能だったのだが、 擬似フォーカス方式を採用したことで、対応することができるようになった。 (本当のフォーカスをリンクに奪われるとFind Toolbarのエディタがフォーカスを失ってしまい、検索を続行できなくなっていた訳だ。)
これまでは、通常の検索時にはリンクにフォーカスを設定していなかったので、 そもそも検索結果にリンクが含まれているかどうかを検査していなかったのだが、 これを解除して通常検索でもリンクを発見したかどうかを検査するようにした。 ただし、通常検索時は発見したリンクを内部で保存しておくだけで擬似フォーカスは設定されない。 これは元の仕様に合わせた形だ。
そして、Find Toolbarが閉じられるときに発見したリンクが内部で保存されていたら、 そのリンクにフォーカスを移動するように修正した。
Bug-org 259454のregression。
FAYTモードでリンクを発見してリンクに擬似フォーカスが当たっている時に、 Tabキーを使ってフォーカスを移動させようとしても本当のフォーカスはFind Toolbarのエディタが持っているため、 擬似フォーカスを中心にフォーカスが移動しないのは直感的ではない、というバグ。
擬似フォーカスを持ったリンクがある場合にTabキーが押されたら、 まずFAYTモードを終了し、そのリンクにフォーカスをセットしするようにした。 そして、その状態でTab、 もしくはShift+Tabに応じたフォーカス移動を行うように修正した。
フォーカスの移動指示は、キーイベントの再発行ではうまくいかないので、 nsIDOMXULCommandDispatcherを利用している。
既にFind Toolbarが表示されている状態で/か'でFAYTを開始すると、 /や'が検索文字列の一文字目として入力されてしまうというバグ。
FAYTの開始時の/キーと'キーは文字入力としては扱わないように修正した。
擬似フォーカスを持ったリンクがある状態でFind Toolbarが閉じられる時にはそのリンクにフォーカスが移動するが、 それによってそのリンクが表示される位置までコンテンツがスクロールしてしまうというバグ。
例えば、FAYTでキーとなるリンクを探した後、マウスホイールでスクロールしてコンテンツを読んでいると、 FAYTがタイムアウトした途端に、先ほど検索したリンクの位置にスクロールさせられてしまう。 つまり、ユーザの操作を無断で取り消してしまうので、非常に不愉快なバグである。
リンクにフォーカスを設定する前にフォーカス移動によるスクロールを抑制するように指定することで修正。
Bug-org 259454のregression。
FAYTで、リンクではなくテキストを検索した状態でTabキーを使っても、 その選択された文字列の前後のリンクにフォーカスが移動しないというバグ。
FAYT中に発見したリンクを保存しているだけでは対応できないので、 検索が成功した時は検索された文字列が選択されているウインドウもしくはフレーム(Javascriptのdocumentオブジェクト)を保存するように修正。
リンクを発見していない場合にTabキーが押された場合、 FAYTを終了してから保存しておいたdocumentオブジェクトにフォーカスを設定し、 nsIDOMXULCommandDispatcherを利用してフォーカスの移動指示を出すようにすることで対応。
Bug-org 259454のregression。
FAYTでリンクに擬似フォーカスを与えたときに、そのリンクのリンク先がステータスバーに表示されないというバグ。
リンクを発見したときに、リンクの上をマウスが通過した場合と同様の処理をするように修正。
単純にリンク先URLを表示するだけではなく、そのURLがエンコードされていた場合はデコードするように対応している。
ちなみに、元々FAYTのテキストモードでは発見したリンクのリンク先が表示されていなかったバグがあったのだが、 それも修正できている。
UTF-8以外の文字コードでURLエンコードされたURLをメールに添付できなかったバグ。 例えばEUC-JPを利用しているWikiのURLがこれにあたる。
添付ファイルのファイル名を取り出す処理で、UTF-8によるデコードに失敗した場合に処理を中断してエラーを返していたことが原因。 UTF-8でのデコードに失敗した場合は、URLエンコードされたままのファイル名で添付するように修正。
Thunderbird1.5からは添付ファイルをdetachして、メール本体から分離保存できるようになったが、 そのファイル名に非ASCII文字が含まれていると、そのメールからdetach済みのファイルを開けなかったバグ。
URLエンコードされたままのfileスキームのURLをメソッドに渡さなくてはいけない所で、 URLをデコードしてから渡していたのが原因。 デコードしていた理由は、過去に別の問題があり、それを回避するためだったのだが、 実際にデコードを止めてみても正常に動作する上、過去のバグも再発しないので根本的な改良が既に行われているものと思われる。
というわけで、非常に手探りな形ではあるが、修正することができた。
添付ファイル名に一部の文字が含まれると、文字化けするというバグ。
元の処理が複雑すぎて、全てのバグのパターンと原因が割り出せない。
元の処理では、fileスキームのURLをURLのままデコードし、文字コードを変換し、 そこからファイル名の部分のみを取得しようとしていたため、 URL独特の文字制限等の仕様からどこかで処理に失敗するとおかしな結果になっていた訳だ。
fileスキームのURLから、まずローカルファイルのオブジェクトを生成し、 そこからファイル名を取得するように、処理を単純化することで全てのバグを一掃することができた。
detachされたファイル名を開こうとした時に、開くアプリケーションを選択する"Unknown content type"ダイアログで、 ファイル名がURLエンコードされたまま表示されるというバグ。
ファイルシステムの文字コードがUTF-8以外のOSで発生する。
本当はメーラのバグではないのだが、通常の利用においては、このケースでしか発生しないのでここに分類している。
通常、URLオブジェクトを生成するときには、初期化の段階で、そのURLで利用する文字コードを指定するのだが、 これが適切に指定されていない場合があり、それに頼っていたファイル名のデコード処理が失敗し、 URLエンコードされたままのファイル名が表示されるようになっていた。
Mozilla内部で生成されるfileスキームのURLは常に、ファイルシステムの文字コードでエンコードされている。 だから、fileスキームのURLを生成する時は常に、URLオブジェクトの文字コードに、 ファイルシステムの文字コードを保存するように修正した。
しかし、Mozillaの基本設計に関わる部分の修正のため、起動時にクラッシュするようになったりと、 予想外のトラブルが出たが、T Rowley、Christian Biesinger、Darin Fisherの多大な協力のおかげで、 なんとか修正することができた。
IDNによる、類似文字による詐称を困難にするために、ブラウザ独自にIDNでの使用禁止文字を設定しようという提案。 各TLDのレジストリによる使用文字の制限があっても、サブドメインにおいてはこの制限をかけれないため非常に危険であるということでこの提案に至った。
IDN表示が許可されたTLDであっても、特定の文字を含んだ場合は危険性のある信頼できないホストであると断定し、 強制的にPunycodeによる表示に切り替える様にしている。 つまり、Firefox1.5では、Punycodeで表示されたサイトは信頼できないサイトである可能性があるということである。
実際のブラックリスト作成にあたり、まずはスラッシュによく似た文字を禁止してしまおう、という提案。
サブドメインでスラッシュによく似た文字を使うことで、本当のドメインをパスの一部のように見せかけて、 サブドメインの一部をドメインのように見せかけることができる。 例えば、http://foo.com∕sub.bar.jp/というURLの場合、 本当のドメイン名はbar.jpであるが、人間の目にはfoo.comがドメイン名のように見えてしまう。 このURLは実際には、bar.jpのfoo.com∕subというサブドメインを参照しているのである。
この修正のため、このドメインは常にhttp://foo.xn--comsub-re3c.bar.jp/と表示されるようになった。 このURLはPunycodeで表示されているので、信頼すべきではないということだ。
実際にはこの修正のあと、ブラックリストの拡張が議論されている。
Windowsでは、最後に使われたプリンタの名前が変更されたり、削除されたりすると、Mozillaを再起動するまでプリンタが使えなくなっていたバグ。
最後に使われたプリンタへのアクセスに失敗した場合、エラーを返すのではなく、 通常使うプリンタに指定されているプリンタをデフォルトプリンタとして処理を続行するように修正した。
印刷時に一ページ目のみを印刷するように指示していても、IFRAME要素がそれ以外のページに配置されていた場合、 そのページもIFRAME要素の内容だけが印刷されていたバグ。
IFRAMEのdocument(Javascriptのdocumentオブジェクトのこと)は、ページ全体のdocumentから見れば、子documentになる。
この子documentの一ページ目が親documentの二ページ目以降にあっても、 印刷対象候補の全documentで一ページ目にあたる部分を印刷していくと、 全体の一ページ目以外のページも印刷されてしまう、という理論の破綻が原因。 要するに、違う基準にあるページ番号を同じものとして扱っていたのが原因である。
元々、子documentは親documentの印刷時に同時に印刷されるので、 子documentは印刷対象かどうか検査する際のチェックで無視するように修正した。
UNIX/Linux以外のOSでは印刷時の用紙設定等が保存されない、というバグ。
UNIX/LinuxではOS標準の印刷ダイアログというものが無いため、 その代替としてクロスプラットフォームな印刷ダイアログをMozillaが用意している。 印刷時の用紙設定等はこのダイアログが保存していたため、 これを使わないWindowsやMacでは保存が一切行われない、という結果になっていた。
ダイアログがOSごとに異なるので、 処理がダイアログからクロスプラットフォームなコードに戻ってきた時に印刷設定を保存するように修正することで対応した。
最後に使ったプリンタが常に無視され、印刷時に毎回、 システムデフォルトのプリンタが選択されるというregression。
最後に印刷したプリンタの名前も設定に保存するように修正した。
印刷プレビューで拡大率や、用紙の向きを変更しても、再表示時に設定をリセットされていたregression。
フロントエンドを無視した、バックエンドの印刷用APIの仕様変更が原因。 APIの仕様を元に戻すように提案したが、物別れに終わっている。
とりあえず、Firefox1.5のリリースまで時間がなかったので、 印刷プレビューで拡大率や用紙の向きを変更した場合には変更された新しい設定値を保存することで動作するようにした。
WindowsのDDE通信時に、WWW_GetWindowInfoを利用してIDNのURLや、 非ASCII文字のタイトルを取得すると文字化けしていたバグ。
これらの情報がASCII文字しか含まない、という前提でUnicode文字列をASCII文字列に劣化変換していたのが原因。 Unicodeから、システムデフォルトの文字コードに変換するように修正。
Win9xのみのバグ。 メールの着信時にタスクトレイに表示されるアイコンのツールチップに非ASCII文字が含まれていると文字化けするバグ。
Unicode文字列をASCII文字列に劣化変換していたのが原因。 これもシステムデフォルトの文字コードに変換するように修正。
ちなみに、WinNTではUnicode化されているので問題無かった。
HTTPヘッダに、Last-Modifiedフィールドが含まれていない場合や、 ローカルファイルを表示する場合、その文書でdocument.lastModifiedを取得すると、 ローカライズされた文字列が文字化けしていたというバグ。
別のバグで、document.lastModifiedの返す値が国際化され、 そのOSの標準の書式が返されるようになったのだがその文字列が文字化けしてしまっていた。
ローカライズされた文字列をASCIIであると仮定して、それをUnicodeに変換していたのが原因。 ローカライズされた文字列はシステムデフォルトの文字コードの文字列なので、 それをUnicodeに変換するように修正。
MacIEからのインポートができるようになったが、日本語の入ったブックマークを取り込むと、文字化けしてしまうというバグ。
MacIEのブックマークはHTMLファイルなのだが、METAタグで指定された文字コードの読み込み処理で、 既存のコードは文字コードの正式名称しか認識できないようになっていて、別名を考慮していなかったのが原因。
元々、Netscape、Mozilla、Firefoxのブックマークファイルを読み込むだけのコードだったので、 今まではこれでも問題無かったのだが、MacIEでは別名を使っていたため、問題が発覚した。
該当部分でも文字コードの別名を認識できるように修正して対応。
ランゲージパック(LP)でintl.menuitems.alwaysappendaccesskeysという設定をtrueとすると、
メニュー等のキャプションの後ろに自動的にアクセスキーが追加されていたのだが、
この設定ができなくなったというregression。
リファクタリングがあったようで、 このときに、Localized String型の設定値を単に、String型として読み込むようにしてしまっていたことが原因。 適切なメソッドで読み込むようにしただけで改善。
intl.menuitems.alwaysappendaccesskeys設定でアクセスキーをメニューの文字列の後ろに自動的に付ける場合(例えばFile(F))は、
括弧の前にスペースを挿入した方が見やすい(File (F))、という欧米の一方的な論理で、
改悪されていたのだが、
JLPを適用すると明らかに違和感があるということで(ファイル (F)となる)、
これをランゲージパックで選択できるようにしようというバグ。
パッチの理屈は単純に半角スペースを挿入しない選択肢を用意しただけ。 (実際にはかなり大きいパッチだが。)
ちなみに、チェックボックス等の一部のウィジェットで アクセスキーをキャプションの後ろに自動で付加することができなかったバグも修正している。
日本語では、text-align: justify;が適切にレイアウトされなかったバグ。
ちなみに、中国語も同様である。
単純に、その要素自身か、祖先のlang属性が日本語、もしくは中国語を示していた場合、
日本語、中国語の文字もjustify用のスペースを追加する文字として処理するようにしただけ。
なぜ、lang属性を意識しているかと言うと、 韓国でも漢字の需要が無い訳ではないらしい(実際にはほとんどハングルしか使わないが)。 しかも、韓国語は、日中と違い、スペースで単語を区切る言語なのでこのような処理はふさわしくない。 だから、lang属性で明示されていない限りは無視するようすることになった。
ちなみに、IEとは違い、Shift_JISに含まれていた記号類も日本語として認識するようにしている。 このため、IEよりも日本人の期待に添った表示結果になると思う。 しかし逆に、欧米言語の文書内にこれらの記号を使う場合、lang属性に気をつける必要がある。
上記バグで、lang属性の制限さえ超えれば無条件に日本語と中国語にスペースを付加していたため、 行末が揃わないので見苦しいというバグ。
行末の文字はスペース付加の対象からは外した。 言葉で言うと単純だが、レイアウト段階では、そのテキストの終端が、行の終端かどうか判別できないので、 なかなかややこしいことをしている。詳しくはパッチ参照。
欧米優先主義で、フォントのデフォルト設定がSerif(いわゆる明朝体)になっているため、日本語が読みにくかったというバグ。
言語ごとにフォントのSerif/Sans-serif設定を設定できなかったため、欧米の言語が綺麗に見えるSerifがデフォルト設定となっていた問題。 ちなみに、日本語版で設定を変更しなかったのは、ライセンス上、 特定の設定以外はデフォルト値を変更してはいけないことになっており、 この設定の変更が許可されていなかったことが原因。
この修正では言語ごとに、Serif/Sans-serifを設定できるようにし、 日本語のデフォルトはSans-serif(いわゆるゴシック体)に変更されている。 Firefox1.0.xのSerif/Sans-serif設定はFirefox1.5では無視されるので、 「私はSerifの方が良いんだ」という場合には再設定が必要になる。
CSSでfont-variant: small-caps;が指定されていると、選択文字列の色がおかしくなっていたバグ。
文字を描画する前に、text-decorationによる線引きを行う処理が呼び出されていて、
ここでそのコンテキストに設定した色が変更されてしまっていたというのが原因。
文字の描画前に、毎回きちんと文字色をコンテキストに再設定することで対応。
CSSでletter-spacing、word-spacing、text-algin: justify;、font-variant: small-caps;のいずれかが設定されている文字列を選択すると、
右に下線(もしくは上線や取消線)がはみ出していたバグ。ただし、Quirksモードのみ。
Mozillaでテキストを描画する場合、1.選択されていないテキスト、2.選択されているテキスト、 3.選択されていないテキスト、といった感じで、最大、三回に分けて描画されるのだが、 下線を描画する際に、毎回そのテキスト全部の幅分、描画するように指示していたのが原因。
描画する文字列の幅分のみ下線を描画する様に修正。
文字列を選択したとき、その要素の背景色が選択文字列の背景色と似ている場合、見分けが付きにくいという問題。 IEでは昔から、このような場合に選択文字列の文字色と、背景色を交換して対応している。
当初、IEの処理を真似しようと、IEのアルゴリズムを調査した。 IEは文字色と背景色は常にコントラストが十分にとられている、という前提のもとに文字色からのみ、 背景色を推測し、色交換を行うかどうか判断している。 これは、背景画像が利用されているのに、背景色が無指定というページの場合にも有効なので、利口なやり方だ。 だが結局、どのような計算式で判定しているのかを解析することはできなかった。
そこで、文字色と、RGB色空間で反対位置にある色を擬似背景色と仮定して、これと、 選択文字列の背景色とのコントラスト差が不十分な場合に、色を交換することにした。 一度はこれでチェックインされたのだが、判定失敗(これはIEでもよくあることだ)が多い、 ということでバックアウトされた。
また、WindowsXPの配色シルバーを使っていると、背景色が白でも色交換が発生するという問題も分かった。 そこで、背景画像が指定されているのに、背景色が指定されていないという行儀の悪いサイトへの対応は諦めて、 実際の背景色を根拠に色交換を行うようにした。また、WinXPの配色シルバーの教訓から、 デフォルトのウインドウの背景色(Windowsの場合白)と、選択文字列の背景色は十分なコントラスト比である、と仮定し、 このコントラスト比が、コードで元々の設定しているしきい値よりも小さい場合はそちらをしきい値として利用するようにしている。 (つまり、デフォルトの背景色なら、色交換は絶対に発生しない。)
ちなみに、Macではこのバグ修正の恩恵は受けれない。これは、Macの選択文字列の配色が特殊で、テキストの色は元の色を使い、背景色のみを変更するという仕様であったことと、 Macユーザはこういう変更を好まない、という意見があったためである。
また、::-moz-selectionで選択文字列の色を指定した場合には、適切な色が指定されていると仮定し、
色交換は絶対に発生しないようになっている。
これを利用して、この機能が不要なユーザはユーザスタイルシートで無効化することもできる。
FAYTで見つけた文字列の選択色が、背景色と見分けが付きにくいことがあるという問題。 要するに、上記バグと同じ。
上記バグのパッチで同時に修正されている。
Bug-org 56314の修正中に、::-moz-selectionをMacユーザは嫌っているから、
Macでは機能しないようにしてくれ、と言われたので変更したものの、やはり出てきたそれに対する反対意見。
結局、Macでも::-moz-selectionは機能するように戻した。
ただし、選択文字列の色交換は相変わらず機能しないままである。
WindowsNTでドラッグ&ドロップで、そのURLへのショートカットを作る際に、 文書のタイトルにシステムデフォルトの文字コードで表現できない文字が含まれていると、 ショートカットファイルの名前が文書のタイトルのまま作成できない、というバグ。
クリップボードのUniformResourceLocatorWと、FileGroupDescriptorWという形式に追加対応したので、 WindowsNTでショートカットを作成する場合には、ショートカットファイルのファイル名がUnicode化された。 (Windows9xでもこの修正は有効だが、エクスプローラがこの形式に対応していない。)
また、やたらと長いタイトルのページだと、ショートカットファイルの作成に失敗していたので、 タイトルの頭128文字のみを使うように制限した。 ただし、ドラッグ時には、ドロップされるフォルダが確定していないので、 128文字を超えるパスにドロップした場合は、相変わらずショートカットの作成に失敗する。
Windowsで入力ロケールを切り替えた場合、IEだとウインドウごとに入力ロケールを記憶するが、 Mozillaはアプリケーション全体でそれを共有している、という問題。
ウインドウの切り替え時に入力ロケールを、前回、そのウインドウが非アクティブになる時に使用していたものに切り替えるようにすることで対応。
ただし、デフォルト設定では今まで通り、アプリケーション内、全てのウインドウで入力ロケールの切り替えを共有している。
これをウインドウ単位に切り替えるには、intl.keyboard.per_window_layoutをtrueに変更する必要がある。
ちなみに、この設定を有効にすると、新しく作られるウインドウは、直前のウインドウの入力ロケールを引き継ぐ。 これは、新しいウインドウが常にシステムデフォルトのロケールに設定されるIEとは動作が異なっているので注意が必要だ。
Windowsのタスクバーを左もしくは上に配置していた場合、 Suiteのインストーラのウインドウが再表示される度に表示位置がずれていたバグ。
ウインドウの座標の保存時に、デスクトップ内での座標を保存していたにも関わらず、 ウインドウ位置を移動させる時にはスクリーン座標で位置指定していたのが原因。
ウインドウ位置を保存する時に、デスクトップ領域の上端、下端も加算して保存するように修正。
Win9xでは、 Suiteのインストーラで、 "Destination Directory"(インストール先のディレクトリ) の表示部分に日本語を表示しようとすると文字化けしていたバグ。
単なるWM_SETFONTの発行し忘れ。
Firefox/Thunderbirdのインストーラを翻訳すると、大半の文字が文字化けしていたバグ。
こちらも単なるWM_SETFONTの発行し忘れ。ただし、量が膨大で、ほとんどのウインドウが対象となった。
Firefox/Thunderbirdのインストーラの見出し文字が通常のフォントで表示されてしまうというバグ。 Bug-org 266309のregression。
新たに見出し文字用の設定も用意して、
WM_SETFONT発行時に見出し文字列にはその設定を送信するようにした。
Windows版インストーラを日本語化すると、一部の文字が消えてしまうバグ。
インストーラはシンプルなアプリケーションにするため、 内容量からテキストの表示領域を計算したりはしていない。 そのため単純にリソースファイルで、日本語用に余裕を持たせることで解決。
WindowsXPでは、Firefoxのインストーラで、!uninstallというフォルダが作成されたり、 他のWindowsでもランダムな文字に、uninstallという文字列の続くフォルダが作成され、 しかもアンインストール時に削除されないというバグ。
Suiteのインストーラからの移植時に不要な変数と、フォルダの作成処理を削除し忘れていて、 未初期化の文字列変数に、"uninstall"という文字列をつなげてフォルダを削除していたのが原因。
単にこの無駄な処理を削除して修正完了。
WindowsでFirefox/Thunderbirdをインストールし続けると、 レジストリのSoftware\Mozilla以下に、各バージョンのエントリが残り続けるというバグ。
インストール時に、直前のバージョンの該当項目を削除するように修正。 ただし、直前のバージョンしか削除できないので、Firefox1.0.xを複数バージョン使った人は、 Firefox1.5をインストールする前に、アンインストールして、この無駄なレジストリエントリを全て削除しておくことを推奨。 (アンインストールすれば、それまでに登録されたレジストリエントリは全て削除される。)
ちなみに、Flash playerのインストーラで、 過去にインストールしたFirefoxのバージョンが全てインストール対象の候補として表示されるのはこのバグが原因。
上記バグのSuite版。当然、Windowsのみ。
こちらも似たようなパッチで修正。
Javascriptでdocument.lastModifiedを取得すると、
HTTPヘッダのLast-Modifiedの値がそのまま返されるため、
時刻が常にGMTで表示されるのでわかりにくい、というバグ。
HTTPヘッダから取得した日時をシステムロケールによって補正することで当初の問題は改善。
しかし、Bug-org 275960の修正で分かるように、 Mozillaの仕様は、返される文字列をローカライズすべきだという論調だった。
だが、ローカライズされた文字列からDateオブジェクトが生成できないという問題が発覚したので、 Dateオブジェクトの生成を保証するために何らかの共通フォーマットで値を返すべきだと考えた。
document.lastModifiedで返されるべき文字列の標準仕様は無いので、
世間で最もシェアの高いWindows版IEの仕様にあわせるのが好ましいと思い、調査してみたところ、
MSDNでIEの仕様が明文化されていた。
これを根拠に、IEにあわせて、常にMM/DD/YYYY hh:mm:ss形式で返すようにした。
より、訪問者になじみのあるフォーマットで表示したい場合、Dateオブジェクトを生成して、
toLocaleStringメソッドを利用することで、OS標準の日時フォーマットを利用できる。
var date = new Date(document.lastModified); var formatted = date.toLocaleString();
Windows版Firefox1.0.xで日本語を含むパスのファイルからFirefoxを起動できないというバグはあったのだが、 それは既に修正されていた。 しかし、Shift_JISで二バイト目に0x7Cが来る場合にのみ、うまくいかないというバグ。
原因は、ASCIIコードで0x7C、つまりパイプ(|)があると、 パイプで区切られた複数のURLが指定されていると判断するというFirefoxの独自拡張(Mozillaではない)が原因のひとつ。
そして、本来なら、URLエンコードする場合には0x7CはURLに使えない文字なのでエスケープするべきではあるのだが、 古いNetscape Navigatorでは、ドライブレターの後に付けるコロン(:)の代わりに、パイプ(|)を使用していた、 という歴史的な問題があり、0x7Cは特別にエスケープしないようになっていたのがもうひとつの原因。
そこで、トップビットが立ったバイトの次に0x7Cが出現した場合は、 常にエスケープするようにURLエンコードの関数を修正した。 トップビットが立ったバイトの後にパイプが出現した場合は、 ドライブレターの後に来るパイプとは異なる、ということが保証されるためである。
一行入力用のエディタで改行文字から始まる文字列を貼り付けると複数行のテキストを入力できてしまうというバグ。
改行文字が二文字目以降で見つかった場合にのみ改行文字以降を削除して貼り付ける、 というケアレスミスがあったことが原因。
一文字目が改行文字だった場合、改行文字以外の文字を含む最初の行を貼り付けるように改善した。
リストボックスをマウスホイールで一番下までスクロールして、 更にホイールを回し続けても祖先の要素がスクロールしないことがあった、というバグ。
スクロールバーを持つ要素で、ホイールによるスクロールが可能かどうか判断する時は、 Mozilla内部でピクセルよりも細かい座標系で判断していた。 (スクロール不可能な場合は、親要素の検査へと移っていく。) だが、この単位による判断では、まだスクロールする余裕がある場合であっても、 実際にはピクセル単位で既に一番下までスクロールしてしまっているため、 結果的にどの要素もスクロールしないという事態に陥っていたのがこのバグである。
ホイールでスクロールしようとしたときに、 スクロールできるかどうか検査するときにもピクセル単位で判断するように改善することで解決。
HTMLのTABLEのセル内にあるLEGEND要素内に、A要素があり、 これがフォーカスを受け取って、outlineが描画されるとセルの幅が縮んでしまうというバグ。
outlineの表示によって再レイアウトが発生した時に(本当はoutlineの描画のために再レイアウトが発生すること自体もバグである)、 FIELDSET要素の内容の幅も再計算しなくてはいけないのに、 それをゼロとしてFIELDSET要素の最小幅を計算して返していたことが原因。
この再レイアウトの時には、LEGEND要素の内容と、FIELDSET要素の内容幅を再計算するように修正。
WindowsでKE_DEBUGを定義して、デバッグビルドを作ろうとすると、ビルドに失敗するというバグ。
単に、デバッグ用のコードを書き換えた時に、ビルドテストを怠っていただけのバグ。
感謝の意を込めて、Gecko1.8の開発サイクルにおいて、お世話になった日本の方々の名前を挙げておきたいと思います。 これらの方々の協力が無かった場合、Gecko1.8及び、Firefox1.5、Thunderbird1.5の品質は実際のものよりも大きく低下していたでしょう。 皆様、本当にありがとうございました。そして、Gecko1.9でもご協力、よろしくお願いいたします。
パッチ提供
Bugzilla-jp運用
他にも、
敬称略(Bugzilla-jp、もしくはBugzilla-orgでのユーザ名で表記しています)