Hatena::ブログ(Diary)

hogehoge @teramako RSSフィード

 | 

2012-02-15

Firefox拡張でHTTPリファラを弄る

昨日はwebRequest APIをざっくり理解する。(あるいはChrome拡張の作り方) | mzsm.meを参考に昨日はChrome拡張でWebRequestAPIを使ってRequestHeaderを弄った

今日は、お返しに、同じく「ITmediaの画像表示にリファラをくっ付けよう」ってことで、Firefoxでのやり方を書くよ。(DN: 1をセットするのはFirefoxだとオプションで出来るからね)

実はこの程度なら同じくらいのコード量で拡張は作れる。

用意するファイルは主に2つ。

  1. install.rdf
  2. bootstrap.js

install.rdf

これは、Chromeで言うところのmanifest.jsonにあたる、拡張機能のメタ情報を収めるRDF形式のXMLファイル。

<?xml version="1.0" encoding="UTF-8"?>
<RDF xmlns:em="http://www.mozilla.org/2004/em-rdf#" xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
  <Description about="urn:mozilla:install-manifest">
    <em:id>unfuckITMediaReferer@teramako.github.com</em:id>
    <em:type>2</em:type>
    <em:name>unfuckITMediaReferer</em:name>
    <em:version>0.1</em:version>
    <em:creator>teramako</em:creator>
    <em:description>Modify Http Referer</em:description>
    <em:bootstrap>true</em:bootstrap>

    <em:targetApplication>
      <Description>
        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
        <em:minVersion>10.0</em:minVersion>
        <em:maxVersion>13.0a1</em:maxVersion>
      </Description>
    </em:targetApplication>
  </Description>
</RDF>

まあ、こんな感じ。

詳しい情報は、Install Manifests - MDNを。

今回は再起動不要なアドオンとして作るので、<em:bootstrap>true</em:bootstrap>を付ける。

bootstrap.js

再起動不要なアドオンとして作ると、このファイルが自動で読み込まれる。

/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");

const TOPIC = "http-on-modify-request";
var ModHttpRefererObserver = {
  referer: Services.io.newURI("http://www.itmedia.co.jp/", null, null),
  observe: function MHRO_observe (aSubject, aTopic, aData) {
    if (aTopic !== TOPIC)
      return;

    var httpChannel = aSubject.QueryInterface(Ci.nsIHttpChannel);
    if (httpChannel.URI.host === "image.itmedia.co.jp") {
      httpChannel.referrer = this.referer;
    }
  },
  QueryInterface: XPCOMUtils.generateQI(["nsIObserver"])
};

function log() {
  Services.console.logStringMessage("[unfuckITmedia]:" + Array.join(arguments, " "));
}

function install (aData, aReason) { }

function startup (aData, aReason) {
  log("Start");
  Services.obs.addObserver(ModHttpRefererObserver, TOPIC, false);
}

function shutdown (aData, aReason) {
  log("Shutdown");
  Services.obs.removeObserver(ModHttpRefererObserver, TOPIC);
}

function uninstall (aData, aReason) { }

まず、下のほうにある、install,startup,shutdown,uninstallbootstrap.jsに必要な関数で、それぞれ:

install
インストールされると呼び出される
startup
有効化されると呼び出される
shutdown
無効化されると呼び出される
uninstall
アンインストールされると呼び出される

通常はインストールされれば、自動的に有効化されるので、install->startup の順に関数が呼ばれ、アンインストールすれば、shutdown->uninstall の順に呼ばれる。

今回は単純なアドオンなので、startupにHttpRequestに介入する準備, shutdownに介入を止めるコードを書いて、その他は空にしている。

HttpRequestに介入

HTTPのリクエストが発行される時、Firefox内部ではオブザーバによる通知がある。DOMで言えば、dispatchEventみたいなもので、この通知と共にネットワークのチャンネルオブジェクトが貰える。これを弄ってやればHTTPリクエストに介入ができる。

通知を受け取るには、DOMで言うところのaddEventListener的にオブザーバの登録が必要になる。登録にはオブザーバオブジェクト(nsIObserver)が必要で、これが上記コードのModHttpRefererObserverである。オブザーバオブジェクトに必要なのはobserveというメソッド一つ。後は自由に書いてよい。

オブザーバの登録にはnsIObserverService(コードでは楽チンをするためにServices.obsを使用)のaddObserverメソッドを使用する。まあこれがDOMのaddEventListenerに相当する。

第一引数にオブザーバオブジェクトを指定し、第二引数にHTTPリクエストを送る直前の通知を受け取る事を指定するトピック名"http-on-modify-request"を指定すれば良い。(参照:Observer Notifications - MDN)第三引数のfalseはDOM Eventのcapturingやbubblingの意味ではないので注意。今回はfalseで構わない。

さて、無事登録ができると、HTTPリクエスト時に通知がobserveメソッドに来る。今回は第一引数のaSubjectにチャンネルオブジェクトが渡ってくるのでコレを利用する...のだが、このチャンネルオブジェクトはそのままでは使い物にならない。var httpChannel = aSubject.QueryInterface(Ci.nsIHttpChannel)nsIHttpChannelに変換してやる必要がある。

これでお膳立ては終わり。あとは自由にやりたいことを書きましょう。

今回はITmediaの画像へアクセス時にリファラを変更することが目的なので、そのコードを書いて終了。

パッケージ化
zip unfuckITmediaImage.xpi instal.rdf bootstrap.js

して、Firefoxに放り込めば、即使える。

ね、簡単でしょ?(嘘

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/teramako/20120215/p1