Почему chrome.tabs.query() не возвращает URL-адрес вкладки при вызове с использованием RequireJS в расширении Chrome?

У меня есть простое расширение Chrome, которое добавляет действие браузера. Когда всплывающее окно расширения открывается, ему необходимо получить доступ к текущему URL-адресу закладки. Поскольку ему не нужен доступ ко всем вкладкам, у меня есть только разрешение activeTab, указанное в манифесте:

{
    "manifest_version": 2,
    "name": "RequireJS Test",
    "version": "0.0.1",
    "description": "Test RequireJS and the activeTab permission.",
    "permissions": [
        "activeTab"
    ],
    "browser_action": {
        "default_popup": "popup.html"
    },
    "web_accessible_resources": [
        "js/*",
        "html/*",
        "css/*",
        "img/*"
    ]
}

В теории, это должно дать всплывающему доступу доступ к активному URL-адресу табуляции, но URL-адрес не возвращается, когда я запрашиваю вкладки из вызова require() в всплывающем файле main.js:

require([], function() {
    chrome.tabs.query({"active": true, "lastFocusedWindow": true}, function (tabs) {
        var url = tabs[0].url;
        console.log("URL from main.js", url);
    });

    console.log("URL from global var accessed in main.js", tabURL);
});

Консоль показывает undefined для URL. Однако, если я делаю тот же вызов из простого .js файла, который не использует require(), он отлично работает:

chrome.tabs.query({"active": true, "lastFocusedWindow": true}, function (tabs) {
    tabURL = tabs[0].url;
    console.log("URL from get-url.js", tabURL);
});

Это отображает правильный URL-адрес, и я могу получить доступ к этому глобальному tabURL внутри вызова require() просто отлично. Когда я нажимаю правой кнопкой мыши кнопку браузера и просматриваю всплывающее окно, вывод консоли выглядит следующим образом:

URL from get-url.js http://stackoverflow.com/info/ask
URL from global var accessed in main.js http://stackoverflow.com/info/ask
URL from main.js undefined

Еще страннее то, что я иногда видел URL-адрес из этого вызова chrome.tabs.query() внутри вызова require(). Но в основном это не работает. Что-то о том, как LoadJS загружает скрипты, похоже, путает Chrome и убирает URL-адрес для загруженного script. Это в Chrome 40 на Windows.

Очевидно, что обходной путь заключается в том, чтобы захватить URL-адрес в отдельном script и сохранить его в переменной, но это немного неприятно. Я хотел бы посмотреть, есть ли способ заставить это работать с RequireJS.

Полный источник плагина находится здесь, если кто-то хочет протестировать его на своей машине: https://github.com/fwextensions/requirejs-url-test


Изменить

Как объясняет Роб У., это не имеет никакого отношения к RequireJS. Единственная причина, по которой код в моем get-url.js файле выше вернул правильный URL-адрес, состоял в том, что он запускался до открытия окна devtools. Если я изменю этот файл на это:

setTimeout(function() {
chrome.tabs.query({"active": true, "lastFocusedWindow": true}, function (tabs) {
    tabURL = tabs[0].url;
    console.log("URL from get-url.js", tabURL);
});
}, 5000);

Затем он запускается после открытия окна devtools и сбоя. RequireJS не является виновником.

Ответ 1

Вы не видите URL-адрес, потому что вы только установили разрешение activeTab (а не tabs). И последнее сфокусированное окно - это инструменты разработчика (для которых у вас нет доступа activeTab) (и поскольку Chrome 41, вкладки devtools/windows невидимы для расширений, поэтому tabs будет пустым массивом).

Хорошей новостью является то, что эта проблема специфична для окна devtools, которое открывается для вашей страницы расширения, поэтому проблема возникает только во время разработки, а не при фактическом использовании пользователями.

Всплывающие окна расширения связаны с окном, поэтому вы можете использовать chrome.tabs.query с currentWindow:true, чтобы получить правильный ответ:

chrome.tabs.query({
    active: true,
    currentWindow: true
}, function(tabs) {
    var tabURL = tabs[0].url;
    console.log(tabURL);
});

Ответ 2

Чтобы преодолеть ошибку devTools, о которой сообщил Rob W. в своем сообщении, следующее обходное решение getActiveTab, как представляется, постоянно работает для меня (даже при открытии нескольких окон devTools). Он работает, всегда сохраняя ссылку на activeTabId на фоновой странице, всякий раз, когда срабатывает событие tabs.onActivated.

var activeTabId;

chrome.tabs.onActivated.addListener(function(activeInfo) {
  activeTabId = activeInfo.tabId;
});

function getActiveTab(callback) {
  chrome.tabs.query({ currentWindow: true, active: true }, function (tabs) {
    var tab = tabs[0];

    if (tab) {
      callback(tab);
    } else {
      chrome.tabs.get(activeTabId, function (tab) {
        if (tab) {
          callback(tab);
        } else {
          console.log('No active tab identified.');
        }
      });

    }
  });
}