読者です 読者をやめる 読者になる 読者になる

遥かへのスピードランナー

シリコンバレーでAndroidアプリの開発してます。コンピュータービジョン・3D・アルゴリズム界隈にもたまに出現します。

FirefoxでHTTPリクエストのURLを書き換えるアドオンを作成する

IT Firefox

2.予め指定されたhostに対するHTTPリクエストに対し、独自に作成したHTMLを返す。
について、いろいろ試してみたことの記録。

http-on-modify-requestイベントを捕捉して、nsIHttpChannelのURIを書き換えてみよう

HTTPリクエスト送信直前のイベントを捕捉するやり方は、
Setting HTTP request headers MDCあたりが参考になるけど、ここに書いてあるやり方では、送信しようとしているHTTPリクエストのHTTPヘッダを追加・変更するのが精一杯で、リクエスト先のURLを書き換えるところまでは記述されていない。そこで、

observe: function(subject, topic, data){
 if (topic == "http-on-modify-request") {
  var ios = Cc["@mozilla.org/network/io-service;1"].getService(Components.
  var newLocation = ios.newURI("http://example.com/", null, null);
  var httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);

  httpChannel.URI = newLocation;
 }
}

みたいないやり方を試してみたがどうもうまくいかない。
ロックスターになりたい-fx internal request proxyにも書いてあるように、「httpRequestがinitされた時点でscriptableじゃないメンバにURIはコピーされていて、このタイミングで書き換えてもリクエスト先は変わらない」ようだ。

http-on-modify-requestイベントを捕捉して、document.location.hrefで新しいURLを指定してみよう

これも、前にエントリーしたとおり、document is not definedエラーが出て、documentオブジェクトを取得することがどうしてもできなかったので断念。

ひとまず解決

これを解決する為に、proconモジュールでやってることを参考にした。

procon\content\procon\proconOverlay.jsより

  19:      if (aTopic != 'http-on-modify-request') return;
  20:      aSubject.QueryInterface(Components.interfaces.nsIHttpChannel);
  21:      var a = aSubject.loadFlags;
  22:      switch(a) {
  23:         case 2686976 : break;
  24:         case 2687232 : break;
  25:         case 2689024 : break;
  26:         default : return;
  27:         }
  28:
  29:	  if (proconpvPrefBranch.getBoolPref("enableWhiteList")){
  30:	  whiteList_regex = getWhiteListRegex();
  31:	  if(whiteList_regex.test(aSubject.URI.host)){
  32:      nprefs.setIntPref("nglayout.initialpaint.delay", 0);
  33:			return;
  34:		}
  35:	  }
  36:
  37:      if(proconpvPrefBranch.getBoolPref("bat")){
  38:            var webNav = aSubject.notificationCallbacks.getInterface(Components.interfaces.nsIWebNav
  39:igation);
  40:            aSubject.loadFlags = Components.interfaces.nsICachingChannel.LOAD_ONLY_FROM_CACHE;
  41:            aSubject.cancel(Components.results.NS_ERROR_FAILURE);
  42:            remove_content(webNav, 1);
  43:			return;
  44:        }

38行目がポイントで、nsIHttpChannelを実装するコンポーネントからnsIWebNavigationを実装するコンポーネントを取得できるので、その後、別URLに遷移させたければ、

webNav.loadURI("http://example.com/", Components.interfaces.nsIWebNavigation.LOAD_FLAGS_NONE, null, null, null);

みたいにやればうまくいく。

不満

でも、一つ不満なのが、アドレスバーのURLが書き換えられてしまうこと。
アドレスバーのURLはそのままに、内部でURLを書き換えることってできないもんだろうか?
うーん。。。