InternetExplorerの問題を切り分けする際に使えるもの

IEの障害切り分けする際に役に立つものを順に思いつくものをまとめてみました。
上にあるほど役に立つと思っているものです。ノンジャンル、雑多です。


■問題事象再現のための環境
各OSとIEバージョン環境の用意。apache/iis/sslサーバ。
問題事象再現・解析のためのプログラム能力。英語含む情報収集力。


■状況確認のためのツール
F12開発者ツール:HTML、CSSソース。ノード状態、通信の確認
ネットワークモニタツール:
IEHttpHeader、netstatwireshark(Network Monitor)、Fidder、straceなどを用途によって使い分ける。


■仕様確認
IE仕様:MSDNサイト/IEBlog
Webサイト仕様:HTML4/HTML5/CSS
その他仕様:JavaScript/Http/SSL/Flash/Windows/IME/Font/他ソフト
ライブラリ使用時はそのライブラリの仕様とソースコード


■ネット情報
google/bingなど検索エンジン
answers(日、英)/IE掲示板のログ(日、英)
同じ問題が上がっている場合があるのと、
レアケースと思ったことがレアかどうか、他の環境でも再現しているかのチェック用途です。


■Process Explorer
タブプロセス、フレームプロセスの識別。
メモリ使用量、スレッド状態、コールスタック、オブジェクト、DLLの確認など。


■起動オプション-extoff
プラグイン機能をオフにする。


■環境依存問題の確認
以下の操作が問題解消に有効であるケースが多い模様。
IEリセット。COMの登録しなおし(regsvr32)。再インストール。


デバッグ版wininet.dll
http://support.microsoft.com/kb/884931/ja
通信がオカシイや、通信時間、通信途中で発生しうる問題解決のため。
キャッシュ(index.dat)問題にも使える。


Internet Explorer Compatibility Test Tool
http://technet.microsoft.com/ja-jp/library/cc721845(WS.10).aspx
セキュリティに引っ掛かったかな?と思った時に、どのようなセキュリティに引っ掛かったかが分かる。


■Process Monitor
関数の呼び出しツリーを見ることが出来る。ETWのstackwalk。
http://msdn.microsoft.com/ja-jp/magazine/cc163437.aspx


■各種デバッガ
シンボルサーバ設定必須。
Visual Studio/WinDbg/Immunity Debugger/OllyDbg/IDA Pro
例外の補足、変数、フロー確認のために使用する。


■IEDiag.exe
IE9付属のIE診断ツール


■UI Spy
UIオートメーション。見た目で何かあれば。

各Webブラウザの開発者向けページ

メモです。忘れるっていうかどのリンク押したら飛べるかよく分からなくなるので!

拡張子pfxとp12(pkcs12)の違いについて

結論から言うと現在では違いがない模様。


こんな話題をするのはX.509証明書の拡張子.pfxとはなんぞやと思い調べていると、調べれば調べるほど、どんどん混乱していったからです。

というのも、


最初に確認した、現時点のWikipediaのX.509のページには

PFX (Personal inFormation eXchange) 標準から発展した PKCS #12 は、単一ファイルでの公開鍵と私有鍵の交換に使われる。

とあり、


一方、WikipediaのPKCSのページには

PFXは PKCS#12 の旧称である。

とあり、


また、RSA Laboratories - PKCS #12 : Personal Information Exchange Syntax Standardにある、PKCS#12のマニュアルの用語定義には

PFX: The top-level exchange PDU defined in this standard.
Protocol Data Unit (PDU): A sequence of bits in machine-independent format constituting a message in a protocol.

となっていて、つまりpkcs#12のマニュアルであってもpfxという用語が出てきていると。


さらに、Windowsの証明書のエクスポート画面は以下のようになっている。


上記のような状況でなんとなく分かったような分からないような微妙な気持ち悪さを感じていたのです。



が、
opensslの古いFAQのOpenSSL PKCS#12 Program FAQ v1.77を確認することで、疑問が解消されました。


Microsoftはファイルの中身がPKCS#12形式であってもPFXファイルと言っている。
・古いNetscapeブラウザでは、ファイルの中身が古いpfx規約で作られたものであってもPKCS#12と主張していたことがある。
pkcs#12のマニュアルに出てくるpfxは、あまり深い意味はなく、MSの言うPFX(つまりpkcs#12)形式で作られたデータのことを指したい時に使用している(よく見ていないけども、おそらく)


pfx仕様を実装したソースコードは上記FAQにあるようです。
仕様自体は相変わらずどこにあるか見つかっていないのですが、とりあえずはこれだけ分かれば十分かなぁ。
FAQにもありますが、pfxについてはあまり知らない方がむしろ良さそうですね。

Loosely-Coupled IE (LCIE)とTabProcGrowthとセッションについて

IE8ではLCIEという機能があります。
要はタブごとプロセスを分けることでプラグインの影響を最小限にします。ただし分けすぎてもメモリを食うので分けすぎないように動いてくれます。

IE8 と Loosely-Coupled IE (LCIE)
Opening a New Tab may launch a New Process with Internet Explorer 8.0
Clicking on the blue “e” in taskbar does not launch a new process in IE8

MSDNの記事はIEで保持しているオブジェクトがどーなっているかの図があって、
IEBlog/AskIE!の記事はレジストリ設定によってタブプロセス、フレームプロセスがどのような規則で別になるのかが書かれてあります。


InternetExplorerはLCIE導入によるデメリットを最小限にする努力はされていますが、問題点も発生しています。
・VisualStudioのブレークポイントが効かない。
・いくつかのプラグインが動作しない(IE7Pro等)。
・window.focus()がSetForegroundWindowの制限に引っ掛かることがある。


これらはレジストリTabProcGrowthを設定することで解除可能です。


が、


これからもお世話になるかもしれない機能であるため、もう少し掘り下げてみました。

タブプロセスとは、フレームプロセスとは

まず、「タブ」「タブプロセス」「フレーム」「フレームプロセス」を分けて考えることが必要です。
「タブ」と「フレーム」は見た目の部分、「タブプロセス」「フレームプロセス」とはWindowsでいうプロセスのこと。
どれがフレームプロセスか、どれがタブプロセスかを再整理をするために、ProcessExplorerSpy++で見ていきます。
※一律保護モードOFF(というかXPなので)


まずは、IEを全て閉じた状態で1つだけ新たなブラウザを立ち上げると以下のように出ます。


iexplore.exeが2つ存在し、親になっているのがフレームプロセスです。
WindowsというOSはあまりプロセスの親子関係は気にしないのですが、
IE8はコマンドライン引数を見る限りなにやら気にするようです。(詳細はこちら

起動済みのInternetExplorerのJavaScriptプログラムにブレークポイントをかけたい場合は、タブプロセス側にアタッチする必要があります(開発者ツールならその必要性はありませんが)。



フレームプロセス、タブプロセスのウィンドウとの関係はココにも書いてありますが、



となっていました。
「お気に入り(FavoritesBar)」「コマンドバー(CommandBar)」はフレームプロセスですが、「メニューバー」「Googleツールバー」はタブプロセスになっていました。
タブプロセスの吹き出しの部分は、タブが異なるとプロセスが異なることがあります。
もちろん、フレームプロセスとタブプロセスは別プロセスです。
タブごとにプロセスが異なっていたとしても、実際はツールバーJavaScriptオブジェクトは1つしかいません。


この状態のウィンドウハンドルの階層とプロセスの関係をSpy++で確認した所、以下のようになっていました。


次に、タブを増やしていくと以下のようになりました。


真ん中の3つがタブプロセスです。
タブプロセスが分かれる規則は、
Opening a New Tab may launch a New Process with Internet Explorer 8.0
にあるように空きメモリや現在のタブの数、整合性レベル、明示的に別セッション(Cookieの方)にしたいかで変わります。
私の環境の場合は、タブ3つだとタブプロセスが3つ。タブ4つ目はタブプロセスは増えない(1つ目のものを使いまわし)。以降緩やかにプロセス増加はしにくくなる。という動作でした。時によっても変わるでしょう。
なお、色が茶色いのは、Windowsの「ジョブ」と呼ばれるOSの機能の1つで、複数プロセスをグルーピングして一元管理したり相互通信するのに使用する機能です。タブプロセス同士がグループ化されてることが見て取れます。



次は、ウィンドウです。
一度IEをすべて閉じて、デスクトップのIEアイコンにて、IEを”2つ”起動します。ウィンドウが2つ表示されます。

先ほどと異なるのは、タブを増やしたのではなく、ウィンドウを増やしました。
にもかかわらず、タブプロセスしか増えませんでした。
これはフレーム結合(FrameMerging)が行われたためです。そのためフレームプロセスが1つのままになっています。
この場合、セッションCookieは共有されます。
メニューバーからの「新規ウィンドウ(CTRL+N)」や「window.open」でも同様です。



今度は、セッションを2つの場合を確認です。
一度IEをすべて閉じて、IEを1つ起動後に、「新規セッション」でIEをさらにもう1つ起動します。

先ほどと異なるのは、起動の仕方の違いです。ウィンドウの数は同じく2つです。
フレームプロセスが2つ、タブプロセス2つあります。吹き出しコメントが「新規セッション」で増えたプロセスです。
フレームプロセスか、タブプロセスかはコマンドライン引数を見れば分かります。
後で増やしたウィンドウは-noframemerging、-sessionmergingオプションが付与された状態で起動されています。
この場合、セッションCookieは共有されません。


セッションについて

IE8でセッション引き継ぎ条件も変わりました。
というより、フレームプロセスのマージ有無が変わったため条件が変わったように見えるだけのようですが。
画面UI上のどのボタンを押したらセッションはどうなるのかがあまり語られていない気がしたので、
まとめてみました(机上確認も含んじゃっていますが)。
注意したいのは、ウィンドウの起動の仕方によってセッションが共有されるかどうかが変わります(IE6,7でも同様ですが)。
例えば、Aタグのtarget=_blankのときと、デスクトップのIEアイコンをクリックでは異なる場合があります。

セッションを実現するにあたり、各種方法がありますが、ここではセッションCookieとsessionStorageに話を絞ります。セッションCookieとはexpires指定なし、永続Cookieとはexpires指定ありのCookieです。

空白は未調査。
レジストリ設定(TabProcGrowth)はデフォルト状態の定義なし状態で確認しています(つまりContext-based)。

操作内容 新規ウィンドウは起動元ウィンドウとは別のフレームプロセスか? 新規タブは起動元タブとは別のタブプロセスか?(可能性があるか?) セッションCookieは起動元ウィンドウ/タブとは別か? sessionStorageは起動元ウィンドウ/タブとは別か? 永続Cookie・localStorageは起動元ウィンドウ/タブとは別か?
新しいタブ(CTRL+T)
タブを複製(CTRL+K)
- 同じ 同じ
AタグをCTRL+クリック - 同じ コピーされた別もの(※2) 同じ
新規ウィンドウ(CTRL+N) 同じ - 同じ 同じ
新規セッション - 同じ
デスクトップのIEアイコンで起動
スタートメニューのIEアイコンで起動
ファイル名を指定して実行で「iexplore」
同じ(※1) - 同じ(※1) 同じ
window.open()
Aタグのtarget=_blank
SHIFT+クリック
同じ - 同じ コピーされた別もの(※2) 同じ
showModalDialog()
showModelessDialog()
  - 同じ 同じ 同じ
iframe/frameset/frame 同じ - 同じ 同じ 同じ
WSHからCreateObject("InternetExplorer") -    
ファイルエクスプローラーからのURL投入   -    


※1:VSのブレークポイントを有効にするために、TabProcGrowthを0にしていると、IE7と同じくセッションは共有されなくなります(また、フレームプロセスとタブプロセスは1つのプロセスになります)。
なお、TabProcGrowthを設定していなくても、セッションが共有されないことがあります(後述)。

※2:http://d.hatena.ne.jp/Syunpei/20090804/1249375857
   IE8 の セッション Cookie と sessionStorage



上記表のとおり、「タブを複製」は手元のマシンでは、セッションCookieは起動元ウィンドウと共有されますが、sessionStorageは起動元タブから引き継がれず新規タブでは空の状態となっていました(コピーもされない)。
このケースは、個人的には、消えるのではなく起動元タブからコピーされた別ものでもよいとも思っています。HTML5での指摘内容には該当しないと考えているためです(複製の意味をユーザがどのように捉えるのか次第かなと)
「window.open」の場合ですと、セッションCookieは同じく共有されますが、sessionStorageは値のコピーが行われ起動元ウィンドウとは別となっていました。



TabProcGrowth設定は、セッションへの影響もあります。値の意味はココにある通りですが、セッションについて補足すると、

0
タブプロセスとフレームプロセスが1つのプロセスになる。タブが増えてもタブプロセスが増えない。また、上に書いたように「デスクトップのIEアイコンで起動」時にセッション(Cookeie)が分かれるようになります。また、frames are not unified across MIC levels.です。
1
タブプロセスとフレームプロセスが1つづつになる(合計2つ)。タブが増えてもタブプロセスが増えない。「デスクトップのIEアイコンで起動」時にセッション(Cookie)は分かれない。all tabs for a given frame process run in a single tab process for a given MIC level.

上でTabProcGrowthを設定していなくても、セッションが共有されずに、別になってしまうことがあると書きました。フレームプロセスが別プロセスになってしまうためのようです。
なることが確認出来ているのは現在2つ。
IE起動→「新規セッション」→起動元ウィンドウを閉じる→IE起動
IE起動→ファイルエクスプローラーからIE起動

起動元プロセス単位でフレームプロセスをマージしているのでしょうか?
このことは、頭に留めておくとよいかもと思っています。

レジストリFrameMergingとSessionMergingについて

FrameMergingとは何と何をどのようなタイミングでマージするのかがIE8 の "フレーム結合" を抑止するを見てもいまひとつ分からなかったため、調査しました。


FrameMergingはデフォルト1(有効)。
デスクトップのIEボタンをクリックして立ち上げたときに、別ウィンドウになりますが、そのウィンドウと既存のウィンドウを結合するかどうかという指定。
結合した場合、フレームプロセスが共有されるが、セッションも共有される。
フレームプロセスとタブプロセスは別プロセスのままです(なので、VSのブレークポイントを有効にするための対策にはならないハズ)。
たとえ1(有効)であっても、メニューの「新規セッション」を選択などで、明示的に別セッションで立ち上げる場合は、フレームプロセスは別になり、セッションも別になります。
値を0(無効)にした場合、ウィンドウごとに別プロセス(ウィンドウ単位でフレームプロセス+タブプロセスが出来る)になる。

「新規ウィンドウ」やwindow.open時はこの設定には影響しない。
つまりマージしない設定(0)にしてもマージされるままです。
http://mp.i-revo.jp/user.php/hcflzamg/entry/1952.html
セッションCookieが共有される単位は、フレームプロセス単位であることはこのレジストリを弄っても変わらないし、IE7から変わっていないと考えています。


(SessionMergingはおいおい調査)

X509証明書について調査

以前より、SSLのためおれおれサーバ証明などを作成していましたが、
拡張子とか、中身がわけわかめだったため、整理のために調査をした。

拡張子

最初、ファイルの拡張子が沢山出てきて戸惑ったが、
どうやら重要なのは「秘密鍵(.key)」「証明書要求(.csr)」「証明書(.crt)」の3つ。
作成ステップは秘密鍵→証明書要求→証明書の順。

openssl genrsa で作成可能。
  • .csr - 証明書要求。ファイル中に要求元の公開鍵や作成してほしい内容が入っています。pkcs#10。
 openssl req -new -key .key
  秘密鍵から証明書要求を作成。
 perl ..\bin\CA.pl -newreq-nodes (CA.pl内ではopenssl req -new -nodes -keyout key.pem -out req.pemを実行)
  秘密鍵を作成しつつ、証明書要求も作成。
  • .crt - 証明書。公開鍵はこの中に含まれています。逆に秘密鍵は含まれていない。
 openssl x509 -in .csr -out .crt -signkey .ken -req
  秘密鍵と証明書要求から証明書を作成
 perl ..\bin\CA.pl -sign (-out cert.pem -infiles req.pem)
  裏で作成していた証明書要求から証明書を作成。
 perl ..\bin\CA.pl -newca  (openssl -req -new -keyout; openssl ca -out crt.pem -selfsign)
  CA証明書の作成のため、秘密鍵や自己署名(ルート)証明書を一気に作成。


後の拡張子は、複数ファイルを合体させるための入れ物だったり、中の形式を変えたい時(主にバイナリかbase64か)に使用する。

  • .pem - 秘密鍵や証明書、証明書要求の入れ物。Base64の形式。この形式(base64)でないと受け付けてくれないツールがある(例えば、パケットキャプチャソフトのWireShark)。
  • .derと.cer - 中身は証明書のみ。バイナリ形式。通常の.crtだとbase64形式のようで、古いブラウザ(今も?)などにインポートする際は、バイナリ形式しか対応していない場合がある。そういう時にこれらの形式を使用する。
  • .pfxと.p12 - 中身は秘密鍵+証明書。pkcs#12。1つのファイルになるので持ち運びが便利な形式。実際はインポートやエキスポート時に使われている模様。例えばapacheIISに持っていくときに使用。pfxはp12の前身。


pfxの仕様が見つからないためp12(pkcs12)との違いが分からないヘ(゚∀゚ヘ)

ASN.1解析

証明書系は(大抵?)ASN.1という形式になっている。
中身を確認したいときに以下のサイトやツールを使うと良い感じかも。

自堕落な技術者の日記 : オススメASN.1ビューアaatool - livedoor Blog(ブログ)
ASN.1 encoder/decoder on JavaScript (v0.3)
openssl asn1parseコマンド
mino's software

証明書作成ツール(オレオレ用)

証明書を作成するツール


makecert.exeはまだ、触ったことがないです。
どのツールを使うにせよCN(CommonName、一般名)と期限を自由に弄れないと、ブラウザが警告を出してくるなど後で困る羽目になります><

APIとか

プログラムで証明書を弄ることがどういうときなのか分かっていませんが、
検証ツールを自作するときとかに使えるかもと考えています。


Microsoft
http://www.trustss.co.jp/smnCrypt000.html
http://msdn.microsoft.com/ja-jp/library/system.security.cryptography.x509certificates.x509store(VS.80).aspx
Java
http://www9.atwiki.jp/kurushima/pages/47.html
LangEdge,Inc. [オープンソース暗号]
http://www.langedge.jp/pub/oss_security.html

各ブラウザのCSSパーサの実装方法

世の中でCSSの解析をどのように実装しているのか調査を行った。
理由はhttp://qune.cside.com/archives/001118.html辺りと同じです。

  • IE - 不明。ソース見つからず。
  • FireFox - 字句解析自作&再帰下降でゴリゴリ。

  \src\layout\style\nsCSSScanner.cpp
  \src\layout\style\nsCSSParser.cpp

  http://d.hatena.ne.jp/amachang/20080502/1209732467
  http://svn.webkit.org/repository/webkit/trunk/WebCore/css/tokenizer.flex
  http://svn.webkit.org/repository/webkit/trunk/WebCore/css/CSSGrammar.y

  • Chrome - Webkitのものと同じ。以下を見る際は複数ページに分かれているので注意。

  http://src.chromium.org/viewvc/chrome/trunk/deps/third_party/WebKit/WebCore/css/?pathrev=9900

  • Opera - 不明。ソースなし。
  • w3cCSS 検証サービス - JavaCC。ツールの都合上1つのモジュールで複数バージョンのCSSに対応

  http://dev.w3.org/cvsweb/2002/css-validator/org/w3c/css/parser/analyzer/

  • React OSのIE - I/Fだけ用意して未実装。shdocvw.dllやmshtml.dll、browseUI.dllはある模様。