4

特定の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をターゲットにします。

4

0 に答える 0