FirefoxのlivehttpheadersでHTTPリクエストの中身が見られるしくみ

サーバに送っているHTTPリクエストのヘッダやレスポンスのヘッダが見られるFirefoxのextension livehttpheaders がどうやってこの機能を実現しているのか調べてみました。

HTTPリクエストを送るタイミングでイベントを捕まえることができるんだろうと予想して探してみるとLiveHTTPHeaders.jsの43行めからのaddToListener()に
function addToListener(obj)
{
  ... snip ...
    // Should be a new version of  Mozilla/Phoenix (after september 15, 2003)
    var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
    observerService.addObserver(obj, "http-on-modify-request", false);
    observerService.addObserver(obj, "http-on-examine-response", false);
  }
}
という記述がありました。

調べるとnsIObserverServiceでaddObserverを使ってnsIObserverのオブジェクトを登録しておくと、登録したオブジェクトのobserveメソッドでaddObserverの二番目の引数で指定したトピック(firefoxではnotificationの種類をtopicと呼ぶそうです)の通知をうけとることができるそうです。

nsIObserverServiceのテスト

Developer Guide - Global Notifications に組み込みのnotification(の一部)のリストがあるので、javascriptを拡張機能のコンテキストで実行できる Execute JSを使ってちょこっとどんなかんじなのか試してみましょう。メニューの[ファイル][オフライン作業]で通知を発生させられるので network:offline-status-changed で試してみます。Execute JSで
var offlineObserver = {
    observe: function (aSubject, aTopic, aState) {
        Firebug.Console.log( [aSubject, aTopic, aState] );
    }
};

var observerService = Components.classes["@mozilla.org/observer-service;1"]
                            .getService(Components.interfaces.nsIObserverService);
observerService.addObserver(offlineObserver, "network:offline-status-changed", false);

を実行すると、メニューの[ファイル][オフライン作業]でオンライン/オフラインを切り替えたときに
offlineObserverのobserveが呼び出されてtopicとonline/offlineのステータス情報を受け取ることができます。addObserverに通知を受け取るように登録するのはnsIOberverのオブジェクトと書きましたが、実際にはQueryInterfaceは呼ばれないようなのでobserveメソッドさえ持っていれば何でもかまいません。

livehttpheadersのobserveメソッド

observeメソッドの中でnotificationを受け取れるということがわかったのでlivehttpheadersのコードに戻ってきてobserveを探すと
  // This is the observerService's observe listener.
  observe: function(aSubject, aTopic, aData) {
    if (aTopic == 'http-on-modify-request') {
      aSubject.QueryInterface(Components.interfaces.nsIHttpChannel);
      this.onModifyRequest(aSubject);
    } else if (aTopic == 'http-on-examine-response') {
      aSubject.QueryInterface(Components.interfaces.nsIHttpChannel);
      this.onExamineResponse(aSubject);
    }
  },
となっていてtopicをifで場合分けして処理しています。Google Code Searchで類似のコードを探してみると、ひとつのインスタンスで複数のtopicを受け取るようにしてtopicに応じて処理を分けるのが一般的みたいです。 ここから先はちょっと複雑なのでHTTPリクエストを読み出しかただけまとめます。 コールバックでobserveが呼び出されるとき、aSubjectにnsIHttpChannelを持つオブジェクトが渡されます。リクエストヘッダ/レスポンスヘッダはこのオブジェクトを使ってvisitRequestHeaders/visitResponseHeadersで読み出します。 HTTPリクエストのメソッドがPOSTのときにpostする内容は、
  channel.QueryInterface(Components.interfaces.nsIUploadChannel);
  var us = channel.uploadStream;
  us.QueryInterface(Components.interfaces.nsISeekableStream);
  
  var ss = Components.classes["@mozilla.org/scriptableinputstream;1"]
                            .createInstance(Components.interfaces. nsIScriptableInputStream);
  ss.init(us);
  us.seek(0, 0);
  var n = ss.available();
  var data = ss.read(n);
  ss.close();
  us.close();
として読み出していました。HTTPレスポンスの内容も基本的には同様の方法で読み出しています。


というわけでlivehttpheadersはnsIObserverServiceを使ってnsIHttpChannelでリクエストが送られるときとレスポンスが帰ってきたときにnotifyされるhttp-on-modify-requestとhttp-on-examine-responseをobserveすることでHTTPリクエストの内容をのぞいていることがわかりました。

まとめ

このlivehttpheadersで使われているhttp-on-modify-requestとhttp-on-examine-responseはFirefoxでふつうにHTTPのリクエストを出すときに必ず使われるnsIHttpChannelがnotifyしてくれるものなので、これをobserveできるのは非常に強力です。

nsIHttpChannelは、ふつうにFirefoxがHTMLのページを表示したときに生じるHTTPリクエストだけでなく、Firefoxのextensionが生成するHTTPリクエストからも利用されています。その結果、このnotificationをobserveするとjavascriptから呼び出すことができるXMLHttpRequestやGM_xmlhttpRequestはもちろん、Google Toolbarのようなextensionがサーバに送っているリクエストも捕捉できますし、Flashのプラグインも中でnsIHttpChannelを使っているようでFlashがリモートのファイルをHTTPで読みこむのも捕捉することができます。

逆に捕捉されたくないときにはnsISocketTransportServiceを用いて自分でソケットを作成してHTTPリクエストを送ることも可能ですが、その場合FirefoxのProxy設定やキャッシュやクッキー、すべて自分で面倒を見る必要があります。

蛇足

本題と関係ないけど調べている途中でわかったのでいっしょに書いておきます。 Developer Guide - Global Notifications に書いてあるnsIHttpChannelに関するnotificationは2つですが、ほかにもnotifyしてくれることはないのかなーと思って Google Code Search で探してみるともうひとつありました。 mozilla/netwerk/protocol/http/public/nsIHttpProtocolHandler.idl - Google Code Search の一番最後に
/**
 * The observer of this topic is notified after the received HTTP response
 * is merged with data from the browser cache.  This means that, among other
 * things, the Content-Type header will be set correctly.
 */
#define NS_HTTP_ON_EXAMINE_MERGED_RESPONSE_TOPIC "http-on-examine-merged-response"
というのが定義されています。 ブラウザキャッシュのデータとHTTPレスポンスがマージされるときに呼ばれるとコメントに書かれていますが、何のことかさっぱりわかりません。さらにGoogle Code Searchで調べるとmozilla/netwerk/protocol/http/src/nsHttpHandler.hのOnExamineMergedResponseでしか参照されておらず、このメソッドは mozilla/netwerk/protocol/http/src/nsHttpChannel.cppの中で呼び出されていて、このメソッドのはじめに
    // ok, we've just received a 206
    //
    // we need to stream whatever data is in the cache out first, and then
    // pick up whatever data is on the wire, writing it into the cache.
と書かれていました。http-on-examine-merged-responseは 206 Partial Content を受け取ったときに呼ばれるものみたいです。

使い方のわからないメソッドやインターフェイスはGoogle Code Searchで調べるとわかることがあります。(少なくともC++でどう実装されているかは見ることはできます)
ソースコード検索エンジンにはほかにも Codase - Source Code Search Engine や Koders - Source Code Search Engine がありますが、以前に(半年くらい前)使ってみた感じでは Google Code Search がヒット数が多くレスポンスもよかったためGoogle Code Searchを利用しています。

tags

  • Firefox
  • extension
  • javascript
  • 「FirefoxのlivehttpheadersでHTTPリクエストの中身が見られるしくみ」のはてなブックマーク数
  • 「FirefoxのlivehttpheadersでHTTPリクエストの中身が見られるしくみ」deliciousブックマーク数
  • 「FirefoxのlivehttpheadersでHTTPリクエストの中身が見られるしくみ」をはてなブックマークに追加
  • save "FirefoxのlivehttpheadersでHTTPリクエストの中身が見られるしくみ" to del.icio.us
  • 「FirefoxのlivehttpheadersでHTTPリクエストの中身が見られるしくみ」をリアルタイムブログ検索
  • permalink
  • Firefoxのsqliteデータベースの中身を表示する Storage Inspector
  • FirefoxのE4XはXPathより便利?

comments

TypeKey Enabled
スタイル用のHTMLタグが使えます。
*required

trackbacks

トラックバック元エントリにこのエントリへのリンクがない場合はトラックバックを受け付けません。

http://labs.gmo.jp/mt/mt-tb.cgi/156
©2010 Kentaro Kumagai, GMO Internet Labs., GMO Internet, inc.
bits and bytes
2007 .08. 17 13:40

tagcloud

  • API1
  • C/C++2
  • E4X1
  • FUSE2
  • Firefox18
  • HTML4
  • IE1
  • MySQL1
  • OSX4
  • Opera2
  • PHP4
  • XML1
  • XPCOM4
  • XPath3
  • apache2
  • binary2
  • book1
  • data11
  • debug4
  • design1
  • experiments3
  • extension10
  • google gears1
  • google maps API1
  • greasemonkey3
  • httpd5
  • javascript17
  • linux1
  • logging2
  • mobile3
  • perl4
  • tips4
  • tool11
  • vim2
  • visualization2
  • widget1
  • wii1
  • windows7
  • サービス6
  • 和訳1

Archives

  • 2008.02 (6)
  • 2008.01 (3)
  • 2007.12 (4)
  • 2007.11 (5)
  • 2007.10 (4)
  • 2007.09 (4)
  • 2007.08 (4)
  • 2007.07 (8)
  • 2007.06 (7)
  • 2007.05 (4)
  • 2007.04 (5)
  • 2007.03 (6)
  • 2007.02 (4)
  • 2007.01 (6)

about

  • bits and bytesのXML
  • 「bits and bytes」のCreative Commons
  • Powered by Movable Type
  • イベントと地図 - モグ
  • Use ecto to blog!
  • bits and bytesのはてなブックマーク数
  • bits and bytesをMy Yahoo!に追加
  • Subscribe with Bloglines