この日記はMozillaのプロダクトへの貢献者としての私の成果を中心に、気になったバグやWeb界隈の話題について書いていますが、 断り書きがある場合を除き、いかなる団体のオフィシャルな見解ではありません。あくまでも個人的なものです。 Mozilla Foundation、Mozilla Corporation、及び関連企業の公式情報ではないことに注意してください。

現在、XHTML 1.0 (もどき)から、HTML5なコンテンツに修正中です。古い日記は修正が完了していませんので表示が崩れます。 順次、修正していく予定ですのでしばらくお待ちください。

もずはっく日記(2015年6月)

2015年6月6日

Bug-org 1130935 [IMM] Support vertical writing mode 初回投稿日時: 2015年06月06日13時04分55秒
最終更新日時: 2015年06月06日13時31分39秒
カテゴリ: Mozilla Core Mozilla41 Windows バグ修正
固定リンク: id=2015060600
SNS: (list)

writing-mode: vertical-lr;や、writing-mode: vertical-rl;でエディタを縦書きにした際にIMMのIMEも縦書きに対応させようというバグです。

IMMでは縦書きはAPIレベルではサポートされていないのですが、composition fontに@で始まる縦書き用のフォント名を指定した場合に、IMEが縦書きをサポートしているなら、縦書きのUIや操作形態に切り替えるという暗黙のルールがあります。ですので、最初は単純にcomposition fontを取得し、その頭に@を付けたり外したりして再設定することでIMMモードで動いているIMEのUIも切り替える予定でした。しかし、色々とIMEごとに問題があり、様々なprefを追加することで、最悪の場合はユーザ自身で自分の利用しているIME用に設定を変更する必要があります。

intl.imm.composition_font

通常、Geckoはcomposition fontを取得し、それを横書き用、@を付けて縦書き用とします。しかし、特定のフォントを指定しておかないとUIが崩れる環境では、この設定にフォント名を設定しておけば、常にそのフォントを利用するようになります。

縦書き時には自動的に@を追加して利用されますので、@で始まらない、横書き用のフォントを指定しておいてください。また、そのフォントが縦書きに対応していることも確認しておいてください。

intl.imm.composition_font.japanist_2003

通常、デフォルトのcomposition fontはSystemです。しかし、Japanist 2003に対して@Systemを設定すると、候補ウインドウのレイアウトが壊れるバグがあります。これを回避するために、Japanist 2003専用のcomposition fontを指定するprefを用意しています。

このprefのデフォルト値はMS PGothicです。

intl.imm.vertical_writing.always_assume_not_supported

Geckoは、現在アクティブなIMEが縦書きに対応しているかどうか、IMEのプロパティを取得して検査します。しかし、Google Chromeのように、未確定文字列の表示にだけ縦書き対応しているものの、候補ウインドウ位置の配置が縦書きに対応していないようなケースも考えられます。

もし、あなたの利用しているIMEが縦書きに対応していない場合、このprefをtrueに変更しておけば、Geckoは常に、そのIMEが縦書きに対応していないものと仮定して、未確定文字列と候補ウインドウが重ならないように、候補ウインドウ位置を調整します。

intl.imm.japanese.assume_active_tip_name_as

Windowsは、アクティブなIMEがTSFに対応しているTIPの場合にTSFに対応していないアプリ上では、CUASという仕組みを用いて、アプリから見ると複数のTIPが一つの同じIMEに見えるようなトリックを使っています。

例えば、Windows 8以降では、Google日本語入力はTIPとしてインストールされていますので、IMMモードで動作しているGeckoからは、アクティブなIMEの名前やプロパティが取得できないため、縦書き非対応のIMEとして処理することができません。

もし、Windows 8以降でGoogle日本語入力のみを利用している場合、この設定値をGoogle 日本語入力 IMM32 モジュールとしておくと、TIPがアクティブな間は、常にそのIMEをGoogle日本語入力だと仮定して動作するようになります(ちなみに、Firefox 40以降、TSFモードが標準で有効になるため、Google日本語入力のユーザは、自分でTSFモードを無効化しない限りはこの設定を行う必要はありません)。

現在、縦書きのサポートがいつからリリース版で標準で有効になるかは不明ですが、縦書きがサポートされた場合、TSFモードを無効にしない方が無難です。また、縦書きのエディタを使うことがある場合は、Google日本語入力以外の縦書きに対応したTIP(MS-IMEやATOK等)を利用することをお勧めします。

Bug-org 1117087 crash in nsEditor::EnsureComposition(mozilla::WidgetGUIEvent*) 初回投稿日時: 2015年06月06日13時19分37秒
最終更新日時: 2015年06月06日13時31分53秒
カテゴリ: GTK Mozilla Core Mozilla40 バグ修正
固定リンク: id=2015060601
SNS: (list)

ATOK X3に対応した際のregressionで、Facebookのコメント入力欄が空の場合に、IMEで未確定文字列を入力するとクラッシュするというバグです。

Facebookのコメント入力欄はcontenteditableで作成されていて、placeholderのような入力時に自動的に消える文字は、通常のテキストノードです。

このため、未確定文字列を挿入しようとした際に、このテキストノードがFacebookにより削除され、内部ではselection changeが発生します。selection changeが発生するとGTKアプリでは、gtk_im_context_reset()を呼び出すことになっていますが、iBusは、preedit_startシグナルの送信中にgtk_im_context_reset()が呼び出されても未確定文字列を削除しない、バグっぽい動作を行います。しかし、Gecko内部では空文字列ですでに確定していますので、NS_COMPOSITION_STARTが発生していない状態でNS_COMPOSITION_CHANGEイベントが発生し、あり得ない状況としてGeckoはMOZ_CRASH()を呼び出して安全にクラッシュしていました。

どちらにせよ、preedit_startシグナルの送信中に未確定文字列がキャンセルされるのはユーザの意図する状況とは言えませんので、preedit_startシグナルの送信中にselection changeが発生してもひとまず無視するように修正しました。ただし、IMEを混乱させないように、未確定文字列の開始位置はselection changeが発生した段階で補正するようにはしています。

Web開発者の方は、compsoitionstartイベントの発生時に、選択位置や、コンテンツの内容を書き換えるのはやめてください。おそらく、様々な問題が潜んでいると思います。

Bug-org 1163317 browser_tabopen_reflows.js fails if IME tries to query focused editor content at selection change 初回投稿日時: 2015年06月06日13時29分14秒
最終更新日時: 2015年06月06日13時32分06秒
カテゴリ: Events Mozilla Core Mozilla41 バグ修正
固定リンク: id=2015060602
SNS: (list)

mochitest-browserの、browser_tabopen_reflows.jsが、選択範囲変更時のreflowを不要なものと判断し、テスト失敗としていたというバグです。

現在、IMEContentObserverはエディタ内で選択範囲が変更された場合、それをIMEに通知しています。その際に、IMEやプラットフォームによっては、新しい選択範囲や、選択範囲の位置を取得しようとします。この際に、ContentEventHandlerは保留されているreflowを全て先に処理しようとします。このため、日本語環境で実行するとこのテストはかなりの環境で失敗するようになっていました。

このテストが選択範囲を変更した際に発生するかもしれないreflowは無視するように修正しています。

Bug-org 1167022 Shouldn't notify IME of focus/blur when a focused editor is reframed 初回投稿日時: 2015年06月06日13時37分48秒
カテゴリ: Mozilla Core Mozilla41 バグ修正
固定リンク: id=2015060603
SNS: (list)

<input>要素等のwidthheightoverflow等、再レイアウトが必要なCSSプロパティが変更された場合、Geckoは、テキストエディタのフレームを再生成します。この際に、IMEには一度、フォーカスを失い、その直後にまた、フォーカスを得たという通知を行っていました。

フォーカスを失うという通知は、IMEやプラットフォームによっては編集中の未確定文字列を強制確定してしまうため、これらの通知は行うべきではないと言えます。そこで、今回の修正では、エディタのフレームが再生成された際に、これらの通知を出していたIMEContentObserverを再生成せずに部分的に再度初期化するようにしました。この再度の初期化に成功した場合、そのまま通知無しで処理を終えます。もし、再初期化に失敗するような、まだ分かっていない状況が発生した場合は従来通り、IMEにフォーカス移動の通知が行われます。

Bug-org 1162818 [IME] Typing a name in Japanese in facebook message compose produces junk (or crashes) 初回投稿日時: 2015年06月06日14時01分03秒
最終更新日時: 2015年06月06日14時01分31秒
カテゴリ: Mozilla Core Mozilla41 バグ修正
固定リンク: id=2015060604
SNS: (list)

Facebookでメッセージを作成する際に、宛先をIMEを利用して入力しようとすると、入力結果が重複していき変になる上、WindowsでTSFモードだとTIP内部でクラッシュすることもあるというバグです。

メジャーなサイトなのに、今までバグ報告が無かったのが不思議ですが、新しいregressionではありません。

Geckoは、<input>要素等のテキストエディタのwidthプロパティ等、再レイアウトが必要になった場合、そのエディタのフレームを一度破棄してしまいます。その際に、エディタの内容と選択範囲は一度nsTextEditorStateに保存され、nsEditorは破棄こそされないものの、一度、そのメンバが一部、クリアされます。その後、フレームが再生成されると、nsTextEditorStateが値と選択範囲を復元後にnsEditorを再度初期化し、nsEditorが選択範囲等を実際にDOMに反映させます。

この際に未確定文字列は、value値の一部になってしまっていますし、IMEの未確定文字列の範囲の情報は破棄されてしまっていたため、nsEditorは再初期化された後は、元の未確定文字列を消すことができず、新しいキャレット位置に未確定文字列を新たに挿入するという挙動になってしまっていました。

そこで今回、nsEditorが再初期化される際に、未確定文字列を確定済みの文字としてではなく、未確定文字列として復元するようにしました。

まず、最新の未確定文字列の状態や文節情報は幸い、TextCompositionクラスが保存しています。そこで、nsEditorは破棄される際にTextCompositionへのポインタをクリアせず、再初期化された際に再利用することにしました。

nsEditorが再初期化されている際には、保存していた未確定文字列を含むテキストノードは、フレーム破棄時に同じ内容で再生成されているため、今までと同様に捨てるようにしましたが、未確定文字列のスタート位置は初期化せず、そのまま保存しておくようにしました。

次に、選択範囲が初期化される際に、TextCompositionから得られる情報と、未確定文字列のスタート位置の情報を基に、文節ごとのIME用の選択範囲を復元し、見た目を元に戻すようにしました。ただし、これは、非アクティブウインドウで発生した場合、次にフォーカスが得られるまで、実行されません。レアケースですし、一部プラットフォームでしか発生しない問題ですが、現在のGeckoの仕様上、どうしようもありません。

そして、次にNS_COMPOSITION_CHANGEイベントをnsEditorが受け取った際には、未確定文字列だったはずの場所を新しい未確定文字列で置換するようにしました。なんとこの部分(nsEditor::InsertTextImpl()nsEditor::InsertTextIntoTextNodeImpl()は、メンバ変数を使ったトリックで、未確定文字列がある場合に引数を無視することで動いていたため、その呼び出し元から修正する必要があるという、Netscape時代からの隠れたバグの修正になってしまいました。

最後に、TSFモードでは、未確定文字列が期待通りにTIPから送信されないことが多々あったので、フレームの再生成中には一切、TSFに通知を送らないようにし、情報を提供できる準備が整ってから通知を出すように修正して対応しています(ただし、一部のケースで高速に入力すると未だにこのバグは再生しますが、レアケースにはなっています)。

Bug-org 1168079 Ensure to set selection after reframing an editor 初回投稿日時: 2015年06月06日14時12分51秒
カテゴリ: Mozilla Core Mozilla41 バグ修正
固定リンク: id=2015060605
SNS: (list)

Bug 1162818のデバッグ中に見つけたバグです。<input>要素等のテキストエディタのフレームが再生成された際にnsEditorが再初期化される際に、大量のwarningがターミナル上に出力されていました。

WARNING: NS_ENSURE_TRUE(aSelection->RangeCount()) failed: file a:\mozilla\mc-e\src\editor\libeditor\nsEditor.cpp, line 3664
WARNING: NS_ENSURE_SUCCESS(rv, rv) failed with result 0x80004005: file a:\mozilla\mc-e\src\editor\libeditor\nsEditor.cpp, line 3643
WARNING: NS_ENSURE_SUCCESS(res, res) failed with result 0x80004005: file a:\mozilla\mc-e\src\editor\libeditor\nsTextEditRules.cpp, line 437

初回の初期化時には、nsEditorの通常の選択範囲を管理しているSelectionはひとつの選択範囲を持っています。しかし、何故か再初期化の段階ではこれが無く、空の状態になっています。

選択範囲が存在していない場合、nsTextEditRules::Init()の最後の方でエディタの末尾にキャレットを置くことで選択範囲を必ず存在させるという処理がありましたが、その前に、nsTextEditRules::CreateBogusNodeIfNeeded()でbogus nodeが必要だった場合に生成しようとします。しかし、そのエディタ内に編集可能なテキストノードを見つけてしまうと、キャレット位置をセットせずに処理を終了してしまいますが、編集処理後に自動的に走るpost processingでは、選択範囲が存在していることが前提のメソッドが先に呼ばれてしまい、上記のwarningが発生し、なんと初期化処理を途中で投げ出してしまっていました。

今回の修正では、問題のpost processingが開始された際に、選択範囲がもし無かった場合、一旦、エディタの末尾にキャレットをセットすることで選択範囲を生成し、初期化処理が完遂されるようにしています。

Bug-org 1169139 Remove all trailing whitespaces in editor 初回投稿日時: 2015年06月06日14時16分18秒
カテゴリ: Mozilla Core Mozilla41 バグ修正
固定リンク: id=2015060606
SNS: (list)

editor/配下のソースコードは、Netscape時代からそのまま無修正の箇所が多く、現在のコーディングルールとかけ離れていたり、いい加減なエラーハンドリングがやたらとあったりと、初歩的な問題が多いのですが、そのひとつに、行の末尾に空白がある行がやたらと存在しているという問題があります。

今回の修正では、秀丸の機能を利用して、全ファイルの行末にある無駄な空白を削除しておきました。

Bug-org 1163304 Nighglty crashes at [@ nsEditor::EnsureComposition(mozilla::WidgetGUIEvent*) ] 初回投稿日時: 2015年06月06日14時27分43秒
カテゴリ: GTK Mozilla Core Mozilla41 バグ修正
固定リンク: id=2015060607
SNS: (list)

Linux版のFirefoxでは、Altキーでメニューバーを表示し、続いて、文字入力のキーを押すことで、それに対応したメニューを開くことができます。しかし、検索バー等のエディタでサジェスト用のポップアップが既に開かれている状態で、なおかつIMEがオンになっている際にこの操作を行うとクラッシュするというバグです。

原因は、Altキーを押した際に疑似フォーカスがメニューバーに移動していないため、IMEの無効化が行われず、IMEが意図せずフォーカス済みのエディタを無視して動作してしまったために、Gecko内部での状態管理に矛盾が生じていたことにありました。

何故か、既にポップアップが開かれていると、メニューバーがアクティブになった際に、メニューバーのキーイベントリスナに主導権が渡されず、その結果、IMEStateManagerがIMEを無効化するタイミングを失っていました。

今回の修正では、メニューバーをアクティブにする前に、存在している全てのポップアップをまずは閉じるようにしました。これにより、UI上もユーザの混乱は無くなりますし、キーイベントの奪い合いも発生しなくなります。

ただし、この修正によって、存在しないとは思うのですが、ポップアップ上にメニューバーを設置しているアドオンはキーボードでそのメニューバーを開くことができなくなっています(しようとすると、そのポップアップ自体が閉じられてしまうため)。もし万が一そういうUIを持ったアドオンでこの問題を確認された方が居ましたら、bugzillaの方へ報告し、私にご一報ください。その場合、アクティブにしようとしてるメニューバーの親がポップアップかどうかを調査し、それより下位(見た目では上)にあるポップアップしか閉じないようにコードを追加します。

Bug-org 1169917 ContentEventHandler::GetStartFrameAndOffset() shouldn't assert even if found frame is not a text frame 初回投稿日時: 2015年06月06日14時33分42秒
カテゴリ: Mozilla Core Mozilla41 バグ修正
固定リンク: id=2015060608
SNS: (list)

ContentEventHandlerが、NS_QUERY_CARET_RECTを処理する際に発見したキャレットの親となるフレームはnsTextFrameであるという前提で実装されていました。しかし、エディタの内容が空の場合等にはそうではないことが分かりました。

今回の修正で、問い合わせのあったオフセットのノードがテキストノードでは無かった場合に、そのノードの子がテキストノードではないかどうかを確認した上で、それでも見つからなかった場合のみ、その非テキストノードのプライマリフレームに頼るようにしました。また、問題の間違ったassertionは無用なテスト失敗の原因になりますので、削除してあります。

Bug-org 1166436 crash in mozilla::dom::TabParent::HandleQueryContentEvent(mozilla::WidgetQueryContentEvent&) 初回投稿日時: 2015年06月06日15時33分38秒
最終更新日時: 2015年06月06日15時34分05秒
カテゴリ: e10s Mozilla Core Mozilla41 バグ修正
固定リンク: id=2015060609
SNS: (list)

Windows x64版でe10sが有効かつ、IMMモード(現在、Nightlyでもe10sモードの場合はIMMモードが標準)の場合、TabParentNS_QUERY_TEXT_RECTをハンドリング中にクラッシュする、というバグです。ちなみに、crash reportを見てみると、Macでも希に発生している模様です。

散々デバッグした結果、その原因は、TabParentがキャッシュしている未確定文字列の各文字の矩形にアクセスする際のチェックにありました。もともと、おかしな値であるUINT32_MAXがオフセットとして指定されている場合限定のバグなのですが、取得する文字数がゼロではない場合、そのオフセット(UINT32_MAX)と長さを足すことで、uint32_tからオーバーフローし、小さな値になります。その結果、オフセットは、キャッシュしてる文字の矩形の最初のオフセット以上かつ、キャッシュしてる最後の文字の矩形のオフセット以下という判定にパスしてしまいます。C++に詳しくないので、なぜこれがx64ビルドでのみ発生しているのかその原因は分かりませんが、ありえないオフセットが来た場合のチェックが甘いことがクラッシュの原因でした。

TabParentは元々、Android版のFirefoxを開発時に段階的に実装され、e10s対応でさらにコンテンツのキャッシュが増え、コードがかなり見づらい状態に陥っていましたので、上記の原因はコードを読んでいるだけでは発見できませんでした。そこで、検証をより簡単にするために、リファクタリングを行うことにしました。

現在のTabParentは、PuppetWidgetがIMEへの通知を受け取る度に、様々な情報を更新していくスタイルです。しかし、非同期でこれが行われているため、TabParentからすると、一部の情報のみが更新されているタイミングで、IMEからコンテンツの問い合わせが来るかもしれません。その場合、TSFではよくあるのですが、想定外の問い合わせ結果を返してしまうとTSFやTIP内部でクラッシュしてしまうことがあります。これを解決するには、PuppetWidget側で必要な情報を揃えてからTabParent側で一括でキャッシュを更新してしまう必要があります。

これらを踏まえて新しいデザインを考えた結果、PuppetWidgetTabParent双方で同じクラスをデータの保存のために利用し、IMEに対して何らかの変更通知を出す際に、PuppetWidget側で必要な情報を揃えてから、通知に添えて新しいコンテンツの情報を送信するようにしました。

この新しいクラスは、mozilla::ContentCacheで、メンバ変数は全てprivateで、直接それらにアクセスすることも今はできません。その代わりにこのクラスがWidgetQueryContentEventを直接ハンドリングしますし、PuppetWidgetの代わりにコンテンツの情報を必要に応じて自動的に取得するようにしています(例えばテキストが変更された場合は、選択範囲や、テキストの矩形も変化している可能性が高いので自動的に取得します)。

また、デバッグを容易にするため、ログも取れるようになっています。NSPR_LOG_MODULES=ContentCacheWidgets:5で動作ログと、キャッシュの情報が取得できますので、デバッグの際にはご利用ください。

選択範囲の開始位置や終了位置の文字の矩形もキャッシュするようにしたり、キャレットの問い合わせ位置に実際にキャレットが無かった場合は、文字の矩形のキャッシュが無いか調査し、もしあれば、そこから推測してキャレットの矩形を返すようにもなっていますので、いくつかのケースで動作が改善しているかもしれません。

Bug-org 1171847 [TSF] logging at nsTextStore::Initialize() is buggy 初回投稿日時: 2015年06月06日15時39分12秒
カテゴリ: Mozilla Core Mozilla41 TSF Windows バグ修正
固定リンク: id=2015060610
SNS: (list)

TSFの動作ログを取ろうとすると、nsTextStore::Initialize()のログで、sCreateNativeCaretForATOK=の後ろが常に壊れた値が記録されていたバグです。イージーミスでした。printf()形式の入力の検査はコンパイラにやって欲しいですね……

2015年6月8日

Windows版Firefoxで、Flash Playerがクラッシュするという方、他のプラグインがクラッシュの原因になっていませんか? 初回投稿日時: 2015年06月08日12時50分49秒
最終更新日時: 2015年06月08日15時21分44秒
カテゴリ: Firefox Flash plugin 雑談
固定リンク: id=2015060800
SNS: (list)

Firefoxでは、OOPPという仕組みを導入し、プラグインのクラッシュでFirefox本体がクラッシュしないように、plugin-container.exeという別のプロセス上で、プラグインを実行しています。

ただし、ここで注意が必要なのは、全てのプラグインがplugin-container.exe上で動作しているという点で、プラグインごとにplugin-container.exeが起動されている訳ではありません。つまり、プラグインがひとつでもクラッシュすると、plugin-container.exeがクラッシュしますので、他のプラグインを利用しているコンテンツでも、「クラッシュしました」というメッセージが表示されることになります。

今回、Army of Awesomeで有益な情報が寄せられました。RealTimesのRealTimes Downloader (旧RealPlayerの時代にインストールされていたらRealDownloader)というプラグインがインストールされており、その設定でChrome ブラウザと FireFox ブラウザで [この動画をダウンロード] をオンにしますを有効にしていると、Flash Playerがクラッシュすることがあるようです。

解決策として、RealTimesそのものを(コントロールパネルから)削除するか、(Firefoxの設定から)無効化するか、RealTimesの設定画面からChrome ブラウザと FireFox ブラウザで [この動画をダウンロード] をオンにしますから無効化するか、Flash Playerの保護モードを無効化することで解決するそうです。

2015年6月19日

Bug-org 1171858 ContentEventHandler::OnQueryCaretRect() should honor writing mode when it guesses caret rect from frame's point 初回投稿日時: 2015年06月19日17時07分57秒
カテゴリ: IME Mozilla Core Mozilla41 バグ修正
固定リンク: id=2015061900
SNS: (list)

IMEがキャレットの矩形を問い合わせて来た場合、GeckoのContentEventHandlerは現在のキャレット位置を問い合わせてこられた場合にはキャレットの矩形をそのまま返しますが、別の位置のキャレットの矩形をリクエストされた場合、その位置にキャレットがある場合の矩形を推測して返します。

この推測するケースでキャレットの矩形を計算するコードに縦書きの対応が入っていなかったので、それを修正しました。

Bug-org 1171810 [e10s] TabParent should cache union text rect of whole selection 初回投稿日時: 2015年06月19日17時12分29秒
カテゴリ: e10s IME Mozilla Core Mozilla41 バグ修正
固定リンク: id=2015061901
SNS: (list)

e10sモードでは、IMEが同期的にコンテンツの情報を取得することができないので、TabParent内のContentCacheが必要されるであろう文字の矩形を予めキャッシュしています。このような手法でIMEのハンドリングを実装しているため、様々なケースに対応できるように矩形のキャッシュを無理の無い範囲で増やしていかなくてはいけません。

このバグでは、IMEが選択範囲全体を含む矩形をリクエストしてきた場合に、それを返すことができるように修正しています。

Bug-org 1119133 Keyboard shortcut to toggle devtools docking mode between last two positions 初回投稿日時: 2015年06月19日17時22分28秒
カテゴリ: Mozilla Core Mozilla41 バグ修正
固定リンク: id=2015061902
SNS: (list)

このバグ自体は私の修正ではないのですが、このバグを修正してテストを書いてみると、nsITextInputProcessorにバグがあってテストがパスしないということで、その修正だけを行いました。

nsITextInputProcessorbeginInputTransaction()が呼び出された際にその引数のDOM windowに対応するnsIWidgetのインスタンスからTextEventDispatcherを取得し、リンクします。

その後、そのnsITextInputProcessorが別のDOM windowと共にbeginInputTransaction()が呼び出された際に、それまでのTextEventDispatcherから新しいものに切り替えますが、リンクが解除されたTextEventDispatcherにその旨を通知していませんでした。そのため、すでにリンクしていないTextEventDispatcherIMEへの通知を既に別のものとリンクしているnsITextInputProcessorに通知し、デバッグビルドではそのバグを検知してクラッシュしていました。

今回の修正では、TextEventDispatcherEndInputTransaction()を追加し、nsITextInputProcessorは内部で明示的にリンクを解除するようになりました。JavascriptからnsITextInputProcessorを利用する場合には、これまでと変わらずbeginInputTransaction()のみの呼び出ししか必要ありません。これは、endInputTransaction()を設けてしまうと、これを呼び出し忘れたアドオン等によって他のアドオン等からの入力が再起動するまで阻害されてしまうことを防ぐためです。

Bug-org 1130937 [Gtk] Need to investigate if IMEs on Linux support vertical writing mode and how do we tells it to IME 初回投稿日時: 2015年06月19日17時33分48秒
カテゴリ: GTK IME Mozilla Core Mozilla41 writing-mode バグ修正
固定リンク: id=2015061903
SNS: (list)

GTKというかLinuxのIMEには、縦書きという概念そのものが存在していませんでした。そこで、抜本的な解決策として、誠さんがGTK側に仕様を追加するように依頼して、既に修正されました

しかし、GTK3のみでの修正になりますし、現在のFirefox/GeckoはあくまでもGTK2がターゲットです。また、各IMEがきちんと縦書きモードをハンドリングできるようになるまで時間がかかるでしょう。そこで、Gecko側でもなんらかの対応が必要になります。

この修正では、変換のために選択された文節、もしくはそれが無い場合は、未確定文字列全体にIMEの候補ウインドウが重ならないように文節全体を縦断する大きなキャレットが存在しているかのように、それをGTKに通知するようにしました。

この修正により、候補ウインドウの文字の大きさが変化したりすることを懸念していましたが、幸い、テストした範囲ではそのような挙動の変換エンジンはありませんでしたのでこのハックを入れています。もし、UIの文字の大きさがおかしい場合を発見したらバグ報告をお願いします。

Bug-org 1172466 IMEContentObserver shouldn't notify IME during reflow 初回投稿日時: 2015年06月19日17時47分20秒
カテゴリ: e10s IME Mozilla Core Mozilla41 バグ修正
固定リンク: id=2015061904
SNS: (list)

IMEContentObserverはフォーカスを持ったエディタの内容の変化を監視し、IMEが必要としている場合はそれをnsIWidget経由で通知します。また、自身の生成時と破棄時にはIMEにフォーカスを得たことと失ったことを通知します。

これまで前者はDOMイベントの発火が安全では無い場合のみ、安全になるのを待って非同期で生成し、後者は同期で通知を行っていました。しかし、リフローの最中はDOMイベントの発火が安全ではないにも関わらず、前者でも通知が行われるということが分かりましたし、後者は言うに及ばずです。

もし、リフロー中にIMEになんらかの通知を出すと、その通知に反応して同期的にコンテンツの内容を取得しにくる可能性があります(というかそういうIMEがほとんどです)。また、e10sモードでは、ContentCacheがそれを必ず行っています。

リフロー中にコンテンツの情報を取得しようとした場合、ContentEventHandlerはそんな状況を想定していないので、そのままペンディングとなっているリフローを全て完了させようとnsIPresShellに指示を出しますが、既にリフロー中だと、nsIPresShellはこれを無視します。このため、まだリフローが終了しないコンテンツにアクセスして、処理が失敗するケースが存在していました。

このバグの修正では、フォーカスを失う場合以外の通知を全て非同期で通知することを可能にして、非同期で実行された際にもリフロー中かどうかを確認し、リフロー中であった場合には再び、IMEContentObserverに通知を再予約します(IMEContentObserverはリフローが終了すると自動的に貯まっている通知を行うことを試みます)。

残念ながらblurの通知のみ非同期にできなかったのは、別のエディタにフォーカスが移動した際に、新しいエディタからのfocus通知との順番を保証することができなかったことと、blur通知からコンテンツを問い合わせてくるケースが通常は存在しない点にあります。

Bug-org 1173678 [e10s] ContentCache::GetUnionTextRect() should ignore some text rects which are not cached 初回投稿日時: 2015年06月19日17時56分25秒
カテゴリ: e10s IME Mac Mozilla Core Mozilla41 TSF バグ修正
固定リンク: id=2015061905
SNS: (list)

e10sモードではTabParentIMEから受け取ったイベントを子プロセスに送信し、その結果を受けとるまでにはタイムラグがあります。そのため、未確定文字列の変更直後にIMEがコンテンツを確認しにきた場合、必ず、TabParent側のContentCacheには古い情報がキャッシュされていることになります。

しかし、このようなシステムを想定して設計されているTSFでも肝心のTIPで対応が完璧なものはありませんし、CocoaのAPIに至っては、そのようなアプリを想定すらしていませんので、またしてもハックが必要な局面です。

今回の修正では、文字の矩形を問い合わせに来た場合、普通は最初の文字の矩形のみが重要ですので、その矩形がキャッシュにある場合、2文字目以降の矩形の情報をキャッシュしていなくても、分かる範囲で矩形を結合してIMEに返すようにしました。

Bug-org 1171814 [e10s] ContentCache should always store first text rect because Yosemite's Japanese IME tries to retrieve it 初回投稿日時: 2015年06月19日18時01分23秒
カテゴリ: e10s IME Mac Mozilla Core Mozilla41 バグ修正
固定リンク: id=2015061906
SNS: (list)

Mac OS X Yosemiteの日本語入力のアプリは、長らく標準で使われていたことえりから別物になっています。この新しいIMEは何故か時折、最初の文字の矩形を取得しに来ます。

そこで、TabParentContentCacheがこれをキャッシュしておくように修正しました。

Bug-org 1172219 [TSF][e10s] nsTextStore should put off to send notifications to TSF if it's dispatching composition events but hasn't received update composition notification 初回投稿日時: 2015年06月19日18時06分59秒
カテゴリ: e10s Mozilla Core Mozilla41 TSF Windows バグ修正
固定リンク: id=2015061907
SNS: (list)

今のところ実害を発見していないバグですが、nsTextStoreはイベントの発火後に、そのハンドリングが終了したという通知が来ているか確認せずにTSFに様々な通知を返しているため、e10sの動作によっては、TSFやTIPがコンテンツの内容を問い合わせて来ても、想定していない結果が返されて、挙動がおかしくなったり、そもそも動作しなくなったりする可能性があります。

この修正では、イベントの発火後から、通知が来るまでの間を魔の時間帯と考え、コンテンツから変更完了通知が来るまではTSFへの通知を延期するようにしています。ただし、二つ以上のイベントが投げられた状態で、一つ目のイベントへの通知のみが返ってきた場合のようなケースには今回の修正でも不十分です。

Bug-org 1175442 nsContentUtils::SendKeyEvent() should take nsIWidget* rather than nsCOMPtr<nsIWidget> at its first argument 初回投稿日時: 2015年06月19日18時13分14秒
カテゴリ: Mozilla Core Mozilla41 バグ修正
固定リンク: id=2015061908
SNS: (list)

他のバグを修正中に、何故かnsContentUtils::SendKeyEvent()の最初の引数がnsCOMPtr<nsIWidget>になっていることに気付きました。このため、例えばnsRefPtr<DerivedClass>を持っているクラスからの呼び出し時には面倒で無駄なコストが発生します。

そこで、生のポインタをそのまま受け取るように修正しています。

Bug-org 549674 Uncommitted IME means you can't set value of an input 初回投稿日時: 2015年06月19日18時31分19秒
カテゴリ: Firefox Google Chrome IE IME Mozilla Core Mozilla41 バグ修正
固定リンク: id=2015061909
SNS: (list)

Geckoは昔から、未確定文字列がある場合に<input>要素や<textarea>要素のvalue属性値を変更しても、IMEは未確定文字列を持ったままで動作がおかしくなるようになっていました。

このバグが長年修正されなかったのは、まず、標準仕様でどうするべきか策定すべきではないかという話がありました。しかし、これは実装側の事情でどうにかしろという話になりました。IE11やGoogle Chromeでは未確定文字列は確定されます(後者はどうにも挙動が怪しいですが)。

もう一つの理由は、LinuxのiBusのように確定のリクエストが非同期で実行される場合にどうすれば良いのかという点がありました。しかし、これはTextCompositionがコンテンツ上での同期的強制確定を保証できている時点で既に問題ではなくなっていました。

今回、IMEまわりの修正を盛大に行っているため、Androidでは一部のサイトでのサジェスト機能がうまく機能しなくなるというregressionが発生してしまっていましたが、その原因の特定やバックアウトが困難なため、今回、この機能の修正に踏み切りました。

今回の修正により、以下のような例では、value属性が変更された場合に、Geckoではtext (Gecko独自イベント)、compositionendinputイベントが発生するようになっています。また、その最中にvalue属性値を取得して処理する際にも期待通りに動作するように、内部では若干、ハッキーな手法をとって、セットした値がそのまま取得されるようになっています。これは、maxlength等を無視することを意味していることに注意してください。

var textarea = document.getElementsByTagName("textarea")[0];

function handler(aEvent)
{
  textarea.value += ", " + aEvent.type;
}

textarea.addEventListener("text", handler);
textarea.addEventListener("compositionupdate", handler);
textarea.addEventListener("compositionend", handler);
textarea.addEventListener("input", handler);

// 未確定文字列("あいうえお")がある状態で
textarea.value += ", " + "setting value";

この結果、textareaの内容は、あいうえお, setting value, text, compositionend, inputとなります。IE 11ではtextcompositionendは発火しません(前者はともかく、後者はバグですが……)。

Bug-org 1175382 [GTK] nsGtkIMModule should use WidgetCompositionEvent::TargetClauseLength() rather than TextRangeArray::TargetClauseLength() 初回投稿日時: 2015年06月19日18時38分03秒
カテゴリ: GTK Mozilla Core Mozilla41 バグ修正
固定リンク: id=2015061910
SNS: (list)

Bug-org 1130937の修正時のミスです。WidgetCompositionEvent::TargetClauseLength()や、WidgetCompositionEvent::TargetClauseOffset()を利用すべき時に、WidgetCompositionEvent::mRangesの、TextRangeArray::TargetClauseLength()TextRangeArray::TargetClauseOffset()を利用していたため、WidgetCompositionEvent側で実装されている、選択された文節が無い場合の回避処理が行われていませんでした。

今回の修正では、TextRangeArrayのこれらのメソッドはWidgetCompositionEvent以外が利用する必要はないので、friend宣言を利用しつつ、これらのメソッドをprivateメンバーに変更しています。

Bug-org 1175383 [e10s] TabChild should store PuppetWidget directly instead of nsIWidget 初回投稿日時: 2015年06月19日19時19分05秒
カテゴリ: e10s Mozilla Core Mozilla41 バグ修正
固定リンク: id=2015061911
SNS: (list)

TabChildは自身でPuppetWidgetのインスタンスを生成し、保持し続けますが、その間、ずっとnsCOMPtr<nsIWidget> mWidget;として保持しています。そのため、ぱっと見、mWidgetPuppetWidget以外の可能性があるかのように見えますし、実際にPuppetWidget固有のメソッドにアクセスする場合にはstatic_castを利用していて、コードがスッキリしていませんでした。

この修正で、nsRefPtr<PuppetWidget> mPuppetWidget;に保存するようにしたので、簡単・確実なコードになっています。

Bug-org 1171796 [e10s] MOZ_LOG() and stderr from child process are not outputted into log file nor terminal on Windows 初回投稿日時: 2015年06月19日19時23分24秒
カテゴリ: e10s Firefox Mozilla Core Windows バグ報告
固定リンク: id=2015061912
SNS: (list)

Windows上でe10sをデバッグしようとすると、デバッグビルドの実行時にプロンプトにもprintf()等での出力が出力されませんし、MOZ_LOG()で出力したログも、ファイルは生成されるものの一行も生成されないというバグです。

まだ修正されていませんが、原因は子プロセスのサンドボックス化のためらしく、デバッグ時には環境変数でMOZ_DISABLE_CONTENT_SANDBOX=1とすれば解決するとのことです(実際、それで解決します)。

ちなみに、LinuxやMacでは問題ありません。

Bug-org 1172200 Since Firefox 37, Video DownloadHelper causes Firefox slowdown 初回投稿日時: 2015年06月19日19時33分12秒
最終更新日時: 2015年06月19日19時46分06秒
カテゴリ: Firefox Mozilla37 Mozilla38 Mozilla39 Mozilla40 Mozilla41 バグ報告
固定リンク: id=2015061913
SNS: (list)

例のVideo DownloadHelperをインストールしていると、Firefoxの動作が遅く、軽くハングアップするという問題ですが、bugzillaに報告したところ、アドオンの作者の方が作業を開始してくれました。これにテスタとして協力してくれているやっさんさんにも感謝です。

At this point, we know we fixed an important cause of slowdowns (CPOW) since version 5.3.1. My plan is to release 5.4.0 with this fix, auto-detection (gallery and screen capture) and icon animation off by default. We'll see if users continue to complain about VDH slowing down the browser.

I'll post here when 5.4.0 is ready (this should happen in a few days).

Many thanks for your help Yassan.

原因の一つは、CPOWを利用していることによってFirefoxのメインスレッドが待ち状態になっていることが多いことのようですが、これはまもなく公開予定の5.4.0で修正されるそうです。

しかし、やっさんさんの検証では他にもバグがあるらしく、相変わらず動作が遅くなることがあるとのことで、やりとりが今でも続いています。

Bug-org 1172239 High CPU usage when open amazon.co.jp in several tabs 初回投稿日時: 2015年06月19日19時36分56秒
カテゴリ: Firefox Mozilla Core
固定リンク: id=2015061914
SNS: (list)

Amazon.co.jpを複数のタブで開いていると、FirefoxのCPU使用率が100%になってしまうというバグです。いつもながらAliceさんからの報告です。

原因等はまったく分かっていませんが、CSSを適用しなかったら再現しなくなるとのこと。profilingできる人は協力をお願いします。

Bug-org 1172205 Amazon preloads resources with <object> tags causing the throbber to blink heavily shortly after page load 初回投稿日時: 2015年06月19日19時45分34秒
カテゴリ: Firefox
固定リンク: id=2015061915
SNS: (list)

こちらのバグは世界中のAmazonのサイトでの問題のようです。

Amazon, shortly after the page has loaded, calls createElement(OBJECT) a dozen of times to load resources. We handle that just like iframes and show the spinner. Amazon does that only in Firefox... in Chrome it just doesn't do that.

Amazon checks for |document.documentElement.style.MozAppearance| and if that exists uses <object> elements to preload .js, .css, .gif, etc. files. So they basically visually f up every page load to preload resources possibly needed for further navigation.

FTR, this isn't something we changed. I can reproduce this issue with Firefox back to 2012-01-01 builds. Amazon is preloading resources using <object> tags ~2.5s after the page has finished loading and that causes our throbber to go wild. They use different tags in Chrome and IE.

とのことで、Firefoxの場合にのみ、何故か処理が遅くなる<object>要素を利用して様々なものを先読みしているので遅くなっているようです。Amazonのサイト側の問題ということで、こちらはAmazonにコンタクトを取っている模様です。

2015年6月30日

Bug-org 1175789 underline position of vertical text should be adjusted in Gecko 初回投稿日時: 2015年06月30日22時23分47秒
カテゴリ: CSS Mozilla Core Mozilla41 text-decoration writing-mode バグ修正
固定リンク: id=2015063000
SNS: (list)

縦書き時の下線と上線の方向(右が下線か、左が下線か)を、Gecko内部で直接調整してしまおうというバグです。

日本と韓国では縦書き時は右側が下線にあたり、中国・台湾やそれ以外の国・言語では左側に下線があるべきなのですが、CSSではデフォルトでは、多数派(?)の下線は左側というルールになっており、このままでは主要な縦書き需要のある市場の日本では問題になります。本来なら、下線の左右を指定できるtext-underline-positionを実装し、ブラウザのデフォルトスタイルで、言語ごとに下線の方向を決めておくべきなのですが、肝心の仕様が未だに安定していません。

そこでこのバグではIEと同様に、text-underline-positionを実装せずに言語ごとに決め打ちで下線の位置を決めてしまうようにしました。将来的にtext-underline-positionを実装しても、デフォルトスタイルと挙動が変わることはない処理を行う様にしています(逆に言うと、text-underline-positionのあるべきデフォルトスタイルをハードコーディングしたという話)。

Bug-org 1177388 [e10s] ContentCache should be separated as two clasesses 初回投稿日時: 2015年06月30日22時33分24秒
最終更新日時: 2015年06月30日22時35分59秒
カテゴリ: e10s Mozilla Core Mozilla41 バグ修正
固定リンク: id=2015063001
SNS: (list)

ContentCacheの初期実装時には、親プロセスのみで利用されるべきメンバと、子プロセスでみ利用されるべきメンバをコメントや、ContentCache::mIsChromeでバグを検出するようにしていました。しかし、親プロセス側にメンバを大量に追加する必要が出てきているのと、mIsChromeは親プロセスでtrueになるわけではなく、chromeプロセスでのみtrueになるようになっていたため、B2Gで利用されているネストされたマルチプロセスではうまく動かなくなっていました。これらの問題を修正するためにクラスを親プロセス用と子プロセス用に分離する必要が出てきました。

この修正により、どちらのプロセスでも利用する共通のメンバをContentCacheで定義し、親プロセス用にはContentCacheInParent、子プロセス用にはContentCacheInChildを定義し、それぞれが必要なメンバのみを定義・実装するようになりました。これにより、chromeプロセスかどうかで動作を変える基準になっていたmIsChromeも廃止され、シンプルなコードになっています。

Bug-org 1175392 [e10s] IME Blur may be too late when moving focus from content to chrome due to race condition 初回投稿日時: 2015年06月30日22時51分48秒
カテゴリ: e10s IME Mozilla Core Mozilla41 バグ修正
固定リンク: id=2015063002
SNS: (list)

子プロセスのエディタがフォーカスを失い、親プロセスのエディタがフォーカスを得る場合には確実に発生するのですが、chromeプロセスからIMEに対してfocusとblurを通知する順序が、

  1. 子のfocus
  2. 親のfocus
  3. 子のblur

となったり、もっとひどい場合(子プロセスがビジーな場合)には、

  1. 子のfocus
  2. 親のfocus
  3. 親のblur
  4. 親のfocus
  5. 子のblur

といった可能性もあります。これを解決するために、chromeプロセスのIMEStateManagerを通して、nsIWidget::NotifyIME()NOTIFY_IME_OF_FOCUSNOTIFY_IME_OF_BLURを通知するようにし、IMEがフォーカスを持っているかどうかを記録しておくことにしました。

これにより、IMEがフォーカスを持っている場合に再度NOTIFY_IME_OF_FOCUSを通知しようとした場合にはNOTIFY_IME_OF_BLURを先に通知するようなり、後から遅れてくるNOTIFY_IME_OF_BLURや、子プロセスから来る不要な他の通知も破棄するようになりました。