Firefox tab id to define "sdk / system / events" api

Good day. I have a problem porting a chrome extension to firefox. I need to identify the entire outgoing request and the ID of the tabs it belongs to. I am using the system / events api to detect requests , but I cannot find a way to determine the tab id from the incoming events. As I understand these events are xpcom objects and I have to use QueryInterface to get some interface, to get some other interface, to get some other interface, to get some other interface ..... get another interface to get the tab id from it (as in the COM implementation on Windows), but I can't find which interface I need, can't find any documentation about these events at all ...

the code i am using in chrome:

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

      

so what i want to achieve from firefox ...

which I am currently writing for 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);
}

      

I have looked at the xpcom docs for a few days, but there is still not enough information to implement this simple thing ... so if anyone has any success with this please help.

+3


source to share


2 answers


I just found a snippet of code to get the browser that triggers the http-on-modify-request notification . The code there seems to be broken, but I used it to create this function to get the tab from the feed.

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;
  }
} 

      

This function converts a low-level tab to a high-level tab. Depending on which one you want, you can skip this feature of course. Again, in the latest SDK, you can probably replace it with 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;
};

      



The problem seems to be that the listener is not working when switching between windows when in use system/events

. Use instead 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);
}

      

I can only hope it works for all the requests you need to detect. The documentation already mentions some cases where they won't work:

Note that some HTTP requests are not tab-related; for example, RSS feed updates, extension manager requests, XHR requests from XPCOM components, etc.

+4


source


The article Listening for events on all tabs describes how to set up web progress listeners for tabs. With this listener, you can receive requests and redirect.

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);

      



At some point you may need to convert low and high level tabs or chrome / dom / sdk windows which are very poorly implemented and confusing. The sdk window in this case is the one you get with windows.browserWindows

, the chrome window has a link to gBrowser

. If you are using the latest sdk, maybe this will help: https://developer.mozilla.org/en-US/Add-ons/SDK/High-Level_API/tabs#Converting_to_XUL_tabs and https://developer.mozilla.org/ en-US / Add-ons / SDK / High-Level_APIs / windows # Converting_to_DOM_windows . I used this function to get chrome window from sdk window: 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;
}

      

+3


source







All Articles