昨日はwebRequest APIをざっくり理解する。(あるいはChrome拡張の作り方) | mzsm.meを参考に昨日はChrome拡張でWebRequestAPIを使ってRequestHeaderを弄った。
今日は、お返しに、同じく「ITmediaの画像表示にリファラをくっ付けよう」ってことで、Firefoxでのやり方を書くよ。(DN: 1をセットするのはFirefoxだとオプションで出来るからね)
実はこの程度なら同じくらいのコード量で拡張は作れる。
用意するファイルは主に2つ。
これは、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>
を付ける。
再起動不要なアドオンとして作ると、このファイルが自動で読み込まれる。
/* * 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
,uninstall
はbootstrap.jsに必要な関数で、それぞれ:
通常はインストールされれば、自動的に有効化されるので、install->startup の順に関数が呼ばれ、アンインストールすれば、shutdown->uninstall の順に呼ばれる。
今回は単純なアドオンなので、startup
にHttpRequestに介入する準備,
shutdown
に介入を止めるコードを書いて、その他は空にしている。
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に放り込めば、即使える。
ね、簡単でしょ?(嘘