灯台下暗し -カッターナイフで恐竜を腑分けした記録-

仕事で携帯向けアプリを書いて、趣味で携帯電話を買い、趣味で同人小説を書いて、何もしていません。

ブラウザを立ち上げ損ねても気にしない話

2004-11-20 00:50:18 | Mozilla
mozillaZine 日本語版に、Thunderbird は Windows の標準ブラウザの設定が壊れていると http:// のリンクをクリックしても反応しないという話が投稿されていました。投稿主は、Eudora のように実行ファイルが見つからないときはファイル選択のダイアログを出すなど対策をとるべきだとお怒りの様子。

そこでソースコードを見てみました。

リンクを選択したときのメソッドから見るのではなく外部アプリケーションを呼び出すコードからボトムアップに見ているので間違えているかも知れませんが。

不満を漏らした人は Thunderbird がブラウザへのパスを記憶していると思い込んでいる節がありますが、私は Thunderbird はブラウザへのパスを記憶していないと思っています。なぜなら Windows には URL だけ渡せば関連付けされたアプリケーションを呼び出す ShellExecute() という API があるから。
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/functions/shellexecute.asp

Thunderbird も、この API を使用しています。
http://lxr.mozilla.org/mozilla/source/uriloader/exthandler/win/nsOSHelperAppService.cpp#251

しかし、この API がアプリケーション起動に失敗したことを無視するとしたらちょっとおかしいです。API リファレンスを見てもエラーを示す返り値が返ります。では Thunderbird がこのエラーコードを見ているのかという話ですが。

ShellExecute() を呼び出しているのは nsOSHelperAppService::LoadUriInternal() というメソッドで、LoadUriInternal() というメソッドを呼び出すのは nsExternalHelperAppService::handleExternalLoadEvent() というメソッドだけ。このメソッドがエラーコードを握りつぶしています(返り値を変数に代入することも return 文で返すこともしていません)。
http://lxr.mozilla.org/mozilla/source/uriloader/exthandler/nsExternalHelperAppService.cpp#1088
このメソッドは OS 中立のモジュールなので、どの OS でもブラウザの立ち上げに失敗したことは見ていないことになります。

じゃあエラーコードを返せばいいのかというと、本当はここからが大変なんです。ユーザにエラーを伝えて、リカバリーして。私にはそこまでの技術力がありません。
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Bug 61363 が起きる原因を見る (その1)

2004-11-19 00:23:35 | Mozilla
Bug 61363<meta> with charset and autodetection should NOT cause reload (loads twice/two times)
ページをダウンロードしたときに文字集合の自動検出によって文字集合がユーザ設定と違うと分かったときに再度 GET/POST を発行してしまう、という日本人にとってとんでもないバグ。いきなり大物から見ていくのは、自分の力を考えていないから。

HTML 限定と当たりをつけてソースを読むと nsHTMLDocument::StartDocumentLoad() というメソッドにて nsHTMLDocument::StartAutodetection() というメソッドが呼ばれている。(POST の場合は自動判定しないという Mozilla ユーザにはおなじみの条件が入っているので間違ってはいないと思う)
http://lxr.mozilla.org/mozilla/source/content/html/document/src/nsHTMLDocument.cpp#857

nsHTMLDocument::StartAutodetection() というメソッドの心臓部は nsICharsetDetectionAdaptor::Init() というメソッド。
http://lxr.mozilla.org/mozilla/source/content/html/document/src/nsHTMLDocument.cpp#666

nsICharsetDetectionAdaptor クラスはインタフェースしか定義しておらず
http://lxr.mozilla.org/mozilla/source/intl/chardet/public/nsICharsetDetectionAdaptor.h#50
実装しているのは nsDetectionAdapter クラス
<>http://lxr.mozilla.org/mozilla/source/intl/chardet/src/nsDetectionAdaptor.h#98

nsDetectionAdapter::Init() は中心部で nsMyObserber::Init() というメソッドを呼んでいる。
http://lxr.mozilla.org/mozilla/source/intl/chardet/src/nsDetectionAdaptor.cpp#137

この nsMyObserber::Init() メソッドは mNotifyByReload というフラグが立っているとリロードを実行してしまう。
http://lxr.mozilla.org/mozilla/source/intl/chardet/src/nsDetectionAdaptor.cpp#67
自動検出を担当するオブジェクトにリロードをするための機能が用意されているところまでは分かった。

するとこのフラグがどこで何のために立つのかを見るべきなのだけれど、ここからの見通しが立たない。

このフラグを立てるのは nsMyObserber::SetNotifyByReload() メソッドだけで、
http://lxr.mozilla.org/mozilla/source/intl/chardet/src/nsDetectionAdaptor.h#79
呼び出しているのは nsDetectionAdaptor::RawBuffer() メソッドだけ。
http://lxr.mozilla.org/mozilla/source/intl/chardet/src/nsDetectionAdaptor.cpp#158
nsDetectorAdaptor::RawBuffer() メソッドを呼び出すのは static ParserWriteFunc() メソッドだけ。
http://lxr.mozilla.org/mozilla/source/parser/htmlparser/src/nsParser.cpp#2506
このとき nsDetectAdaptor オブジェクトを保持するのは static ParserWriteFunc() メソッドの引数 closure 。
http://lxr.mozilla.org/mozilla/source/parser/htmlparser/src/nsParser.cpp#2453
ParserWriteFunc の文字が現れるのは nsParser::OnDataAvailable() メソッドの中で nsIInputStream オブジェクトの ReadSegments() メソッドの引数としてだけ。
http://lxr.mozilla.org/mozilla/source/parser/htmlparser/src/nsParser.cpp#2564

ここから nsIInputStream オブジェクトと nsParser::OnDataAvailable() メソッドの使われ方を見るべきだけれど、今夜はもう眠い。
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする