特定のWebページにコンテンツを挿入するFirefoxMobile用の再起動不要のアドオンを作成しようとしています。アドオンを無効にしてから再度有効にしようとすると、ページの読み込みイベントに対して複数の応答が返され、それらを整理する方法がわかりません。
FennecはElectrolysisマルチプロセスプラットフォームを使用しているため、コードをchromeスクリプトとcontentスクリプトに分割する必要があることを私は知っています。私のbootstrap.jsは次のようになります(わかりやすくするためにトリミングされています)。
function startup(data, reason) {
mm = Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIChromeFrameMessageManager);
mm.loadFrameScript(getResourceURISpec('content.js'), true);
}
function shutdown(data, reason) {
let mm = Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIChromeFrameMessageManager);
mm.sendAsyncMessage("GeoMapEnh:Disable", {reason: reason});
}
function install(data, reason) {}
function uninstall(data, reason) {}
基本的に、bootstrap.jsはコンテンツスクリプトを起動し、シャットダウン時にクリーンアップするように指示するメッセージを送信します。content.jsは、ページの読み込みを監視するeventListenerを設定します。これは、次のようになります。
addMessageListener("GeoMapEnh:Disable", disableScript);
addEventListener("DOMContentLoaded", loadHandler, false );
function loadHandler(e) {
LOG("Page loaded");
// Do something cool with the web page.
}
function disableScript(aMessage) {
if (aMessage.name != "GeoMapEnh:Disable") {
return;
}
LOG("Disabling content script: " + aMessage.json.reason);
try {
removeEventListener("DOMContentLoaded", loadHandler, false );
removeMessageListener("GeoMapEnh:Disable", disableScript);
} catch(e) {
LOG("Remove failed: " + e);
}
}
function LOG(msg) {
dump(msg + "\n");
var consoleService = Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService);
consoleService.logStringMessage(msg);
}
私が最初に拡張機能を実行したとき、すべてが正常に機能します。content.jsのインスタンスは、ブラウザーのタブ(および開いた新しいタブ)ごとに実行され、eventListenerは、DOMContentLoadedイベントを介して想定されるページの読み込みを検出します。拡張機能を無効にしても、すべてが問題ないように見えます。ページの読み込みが検出されなくなります。
拡張機能を再度有効にすると、すべてがうまくいきません。開いているタブごとにcontent.jsのインスタンスが実行されますが、新しいタブを開くと、DOMContentLoadedが複数のeventListenersをトリガーし、どちらがイベントを処理するかを区別できません。さらに悪いことに、一部のeventListenerはアクティブですが、LOG関数を介してデバッグ情報を提供しません。また、拡張機能をもう一度無効にしても、すべてが削除されるわけではありません。
新しいタブを含むすべてのブラウザタブを監視したいのですが、拡張機能がコンテンツを挿入するのは、ページの読み込みごとに1回だけです。私は成功せずに次のことを試みました:
- e.stopPropagation()を呼び出して、イベントが他のリスナーに渡されるのを停止します。無効。
- e.preventDefault()を呼び出し、e.defaultPreventedをテストして、イベントがすでに処理されているかどうかを確認します。それは決してありません。
- (this === content.document)かどうかをテストして、eventListenerが独自のページコンテンツによってトリガーされているかどうかを確認します。複数の「真の」応答が返されるため、機能しません。
- eventListenerをキャプチャします。無効。
- DOMContentLoadedではなくloadイベントを使用します。
共有変数を設定して、イベントがElectrolysisの下で処理されたと言うことはできません。さまざまなeventListenersがさまざまなコンテキストで実行されます。また、同じページをロードしている複数のタブと、複数回検出されている1つのページのロードを区別することはできません。chromeブートストラップスクリプトに戻るIPCメッセージを介してこれを行うことはできますが、正しいブラウザタブに応答を返す方法がわかりません。
何か案は?これはFirefoxのバグですか、それともコードで何かばかげたことをしていますか?私は開発にFennecDesktopv4を使用しており、本番環境にはFennecAndroidv6をターゲットにします。