【问题标题】:Firefox add-on pageMod, catch ajax done in contentScriptFileFirefox 插件 pageMod,在 contentScriptFile 中捕获 ajax
【发布时间】:2014-08-07 22:40:08
【问题描述】:

我的问题是我需要知道 AJAX 何时在页面上完成。我需要在我通过 pageMod 加载的 contentScriptFile 中知道这一点。每次修改页面时,我的插件都需要运行:所以基本上是在加载时以及每次有 AJAX 调用时。

我试过这个:

$(document).ajaxComplete(function() {
     alert("AJAX call completed");
});

但它不起作用。

有没有办法做到这一点?

编辑:来自 main.js 的我的页面 mod 代码:

pageMod.PageMod({
     include: "*",
     contentScriptFile: [self.data.url("jquery-1.9.1.min.js"), 
     self.data.url("script.js")],

     onAttach: function(worker){

      var apiKey = require("sdk/simple-prefs").prefs.apiKey;
      var ignoreList = require("sdk/simple-prefs").prefs.ignoreList;

      worker.port.emit("prefSet", [ignoreList, apiKey]);

      }

});

【问题讨论】:

  • 我不确定jQuery的方法,但是你想要XPCOM方法,它监听浏览器中的所有HTTP请求,然后你可以测试HTTP请求的loadContext是否是您的contentScriptFilewindow
  • @Noitidart 我对任何可行的方法持开放态度:) 所以如果你能提供一个例子?

标签: javascript jquery ajax firefox-addon firefox-addon-sdk


【解决方案1】:

不要把它放在内容脚本中: 我不确定您将如何识别脚本的内容窗口。我不太了解sdk。不过看区CONTENT_WINDOW_OF_CONTENT_SCRIPT

const { Ci, Cu, Cc, Cr } = require('chrome'); //const {interfaces: Ci, utils: Cu, classes: Cc, results: Cr } = Components;
Cu.import('resource://gre/modules/Services.jsm');
Cu.import('resource://gre/modules/devtools/Console.jsm');

var observers = {
    'http-on-modify-request': {
        observe: function (aSubject, aTopic, aData) {
            console.info('http-on-modify-request: aSubject = ' + aSubject + ' | aTopic = ' + aTopic + ' | aData = ' + aData);
            var httpChannel = aSubject.QueryInterface(Ci.nsIHttpChannel);
            var requestUrl = httpChannel.URI.spec
            var goodies = loadContextAndGoodies(aSubject, true);
            if (goodies.contentWindow) {
               if (goodies.contentWindow == CONTENT_WINDOW_OF_CONTENT_SCRIPT) {
                    //do something here
               }
            }
        },
        reg: function () {
            Services.obs.addObserver(observers['http-on-modify-request'], 'http-on-modify-request', false);
        },
        unreg: function () {
            Services.obs.removeObserver(observers['http-on-modify-request'], 'http-on-modify-request');
        }
    }
};

然后在同一个范围内添加这个辅助函数:

function loadContextAndGoodies(request, return_goodies) {
  var loadContext = null;

  if (request instanceof Ci.nsIRequest) {
      try {
          if (request.loadGroup && request.loadGroup.notificationCallbacks) {
              loadContext = request.loadGroup.notificationCallbacks.getInterface(Ci.nsILoadContext);
          }
      } catch (ex) {
        console.exception('request loadGroup with notificationCallbacks but oculd not get nsIloadContext', ex);
      }
      if (!loadContext) {
        try {
            if (request.notificationCallbacks) {
                loadContext = request.notificationCallbacks.getInterface(Ci.nsILoadContext);
            }
        } catch (ex) {
          console.exception('request has notificationCallbacks but could not get nsILoadContext', ex);
          /* start - noit's backup try, it might be redundant (im not sure) as Wladamir Palant didn't have this way*/
          try {
            var interfaceRequestor = httpChannel.notificationCallbacks.QueryInterface(Ci.nsIInterfaceRequestor);
            loadContext = interfaceRequestor.getInterface(Ci.nsILoadContext);
          } catch (ex) {
            console.exception('backup method failed:' ex);
          }
          /* end - my backup try, it might be redundant as Wladamir Palant didn't have this way*/
        }
      }
  } else {
    console.warn('request argument is not instance of nsIRequest')
  }

  if (return_goodies) {
    if (!loadContext) {
      return null;
    }

    var contentWindow = loadContext.associatedWindow;
    var DOMWindow = contentWindow.top.QueryInterface(Ci.nsIInterfaceRequestor)
                                     .getInterface(Ci.nsIWebNavigation)
                                     .QueryInterface(Ci.nsIDocShellTreeItem)
                                     .rootTreeItem
                                     .QueryInterface(Ci.nsIInterfaceRequestor)
                                     .getInterface(Ci.nsIDOMWindow);
    var gBrowser = DOMWindow.gBrowser;
    if (gBrowser) {
      var tab = gBrowser._getTabForContentWindow(contentWindow.top);
      var browser = tab.linkedBrowser;
    } else {
      var tab, browser = null;
    }
    var goodies = {
      loadContext: loadContext,
      DOMWindow: DOMWindow,
      gBrowser: gBrowser,
      contentWindow: contentWindow,
      browser: browser,
      tab: tab
    };

    return goodies;
  } else {
    return loadContext;
  }
}

开始观察

要开始观察所有请求,请执行此操作(例如在您的插件启动时)

for (var o in observers) {
    observers[o].reg();
}

停止观察

停止观察很重要(确保至少在插件关闭时运行它,你不想因为内存原因让观察者注册)

for (var o in observers) {
    observers[o].unreg();
}

【讨论】:

  • 这是一个很好的例子,谢谢!不过有一个问题:即使我注释掉CONTENT_WINDOW_OF_CONTENT_SCRIPT if 语句,我仍然无法从代码中得到任何响应。我应该将代码放在 pageMod 中还是完全放在 main.js 的某个位置之外?
  • 哦,废话,我忘了给你添加观察者的代码。所有这些代码都应该在 pagemod 之外。所以它应该在 main.js 中的任何地方。我刚刚编辑了如何开始观察和停止观察。
  • 这一行 Services.obs.addObserver(observers['http-on-modify-request'], 'http-on-modify-request', false); 返回错误 NS_ERROR_ILLEGAL_VALUE filename = undefined 如果你能指出我做错了什么?谢谢
  • 非常感谢您的帮助!我设法使用您的示例编写了自己的函数:)
  • 很棒的人请链接/分享其他人的未来参考。更快乐!
猜你喜欢
  • 1970-01-01
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多