firefox检测标签ID" sdk / system / events" API

时间:2014-08-08 01:49:09

标签: javascript firefox firefox-addon-sdk xpcom

美好的一天。 我有将chrome扩展移植到firefox的问题。 我需要检测它所属的所有传出请求和标签的ID。 使用system/events api检测请求,但我找不到如何从incomming事件中检测tab的id的方法。据我所知,这个事件是xpcom对象,我应该使用QueryInterface获取一些接口来获取一些其他接口以获得一些其他接口以获得一些其他接口来获取其中的tab的id(就像在Windows中的COM实现一样),但是我找不到我需要的接口,找不到关于这个事件的文档...

我在铬中使用的代码:

chrome.webRequest.onBeforeRequest.addListener(
 function(info) {
     if(info.tabId)
         //do stuff here
 }

所以这就是我想从firefox中实现的......

我目前为firefox编写的代码:

exports.main = function(options)
{
    //stuf here ....
    ........
    function listener(event)
    {
        var channel = event.subject.QueryInterface(Ci.nsIHttpChannel);
        console.log(channel);
        //TODO: get tab here somehow
    }
    events.on("http-on-opening-request", listener);
}

我已经看了几天的xpcom文档,但仍然没有足够的信息来实现这个简单的事情......所以如果有人成功了,请帮忙。

2 个答案:

答案 0 :(得分:4)

我刚刚找到了getting the browser that fires the http-on-modify-request notification的代码段。那里的代码似乎已被破坏,但我使用其中一些来创建此函数以从频道中获取选项卡。

const getTabFromChannel = (aChannel) => {
  try {
    let notificationCallbacks = aChannel.notificationCallbacks || aChannel.loadGroup.notificationCallbacks;
    if (!notificationCallbacks)
      return null;

    let domWin = notificationCallbacks.getInterface(Ci.nsIDOMWindow);
    let chromeTab = tabsUtils.getTabForContentWindow(domWin);
    return getSdkTabFromChromeTab(chromeTab);
  }
  catch (e) {
    // some type errors happen here, not sure how to handle them
    console.log(e);
    return null;
  }
} 

此功能可将低级选项卡转换为高级选项卡。根据您需要的那个,当然可以跳过这个功能。同样,在最新的SDK中,您可以将其替换为tabs.viewFor(chromeTab)

const tabs = require("sdk/tabs");
const tabsUtils = require("sdk/tabs/utils");

const getSdkTabFromChromeTab = (chromeTab) => {
  const tabId = tabsUtils.getTabId(chromeTab);
  for each (let sdkTab in tabs){
    if (sdkTab.id === tabId) {
      return sdkTab;
    }
  }
  return null;
};

使用system/events时,在窗口之间切换时,监听器似乎出现了问题。请改用Services.obs.addObserver

const httpRequestObserver = {
    observe: function (subject, topic, data) {
        var channel = subject.QueryInterface(Ci.nsIHttpChannel);
        console.log("channel");
        var tab = getTabFromChannel(channel);
        if(tab) {
          console.log("request by tab", tab.id);
        }
    }
}

exports.main = function() {
  Cu.import('resource://gre/modules/Services.jsm');
  Services.obs.addObserver(httpRequestObserver, 'http-on-opening-request', false);
}

我只能希望它适用于您需要检测的所有请求。该文档已经提到了一些不起作用的情况:

  

请注意,某些HTTP请求与选项卡无关;例如,RSS提要更新,扩展管理器请求,来自XPCOM组件的XHR请求等

答案 1 :(得分:3)

文章 Listening to events on all tabs 介绍了如何为标签设置网络进度监听器。有了这个监听器,您就可以获得请求和重定向。

const tabsUtils = require("sdk/tabs/utils");
const listener = {
  QueryInterface: XPCOMUtils.generateQI(["nsIWebProgressListener", "nsISupportsWeakReference"]),
  onLocationChange: (browser, progress, request, uri) => {
    let tab = tabsUtils.getTabForContentWindow(progress.DOMWindow);
    // ...
  },
  onStateChange: (browser, progress, request, state) => {
    let tab = tabsUtils.getTabForContentWindow(progress.DOMWindow);
    // ...
  } 
  // ...
};
getChromeWindow(sdkWindow).getBrowser().addTabsProgressListener(listener);

在某些时候,您可能需要在低级别和高级别选项卡或chrome / dom / sdk窗口之间进行转换,这实际上是非常糟糕和令人困惑的。在这种情况下,sdk窗口是windows.browserWindows获得的窗口,chrome窗口引用了gBrowser。如果您使用的是最新的sdk,这可能会有所帮助:https://developer.mozilla.org/en-US/Add-ons/SDK/High-Level_API/tabs#Converting_to_XUL_tabshttps://developer.mozilla.org/en-US/Add-ons/SDK/High-Level_APIs/windows#Converting_to_DOM_windows。我使用此函数从sdk窗口获取chrome窗口:https://bugzilla.mozilla.org/show_bug.cgi?id=695143#c15

const { BrowserWindow } = require('sdk/windows');
const { windows } = require('sdk/window/utils');

function getChromeWindow(sdkWindow) {
  // to include private window use the as second argument
  // { includePrivate: true }
  for (let window of windows('navigator:browser'))
    if (BrowserWindow({window: window}) === sdkWindow)
      return window;

  return null;
}