firefox обнаруживает идентификатор вкладки в api" sdk/system/events"


Добрый день. у меня есть проблема с переносом расширения chromium в firefox. мне нужно определить все исходящие запросы и идентификаторы вкладок, к которым они принадлежат. для обнаружения запросов я используюsystem/events api, но не могу найти способ, как определить id вкладки из входящих событий. Как я понимаю, эти события-объекты xpcom, и я должен использовать QueryInterface, чтобы получить какой-то интерфейс, чтобы получить какой-то другой интерфейс, чтобы получить какой-то другой интерфейс ..... чтобы получить какой-то другой интерфейс чтобы получить id вкладки из него (как и в реализации COM В windows), но я не могу найти, какой интерфейс мне нужен, не могу найти документацию об этих событиях вообще...

Код, который я использую в chromium:

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 docs несколько дней, но все еще не хватает информации, чтобы реализовать эту простую вещь... так что если у кого-то есть успех с этим, пожалуйста помощь.

2 3

2 ответа:

Я только что нашел фрагмент кода для получения браузера, который запускает уведомление http-on-modify-request. Код там, кажется, сломан, но я использовал некоторые из них, чтобы создать эту функцию, чтобы получить вкладку из канала.

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-каналов, запросы extension manager, запросы XHR от компонентов XPCOM и т. д.

Статья прослушивание событий на всех вкладках описывает, как настроить прослушиватели веб-прогресса для вкладок. С помощью этого прослушивателя вы можете получать запросы и перенаправления.

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_tabs и https://developer.mozilla.org/en-US/Add-ons/SDK/High-Level_APIs/windows#Converting_to_DOM_windows. я использовал эту функцию, чтобы получить окно chrome из окна sdk: 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;
}