web-dev-qa-db-fra.com

Pourquoi chrome.tabs.query () ne retourne pas l'URL de l'onglet lorsqu'il est appelé à l'aide de RequireJS dans une extension Chrome?

J'ai une simple extension Chrome qui ajoute une action de navigateur. Lorsque la fenêtre contextuelle de l'extension est ouverte, elle doit accéder à l'URL de l'onglet actuel. Comme elle n'a pas besoin d'accéder à tous les onglets, je juste avoir l'autorisation activeTab spécifiée dans le manifeste:

{
    "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/*"
    ]
}

En théorie, cela devrait donner accès au popup à l'URL de l'onglet actif, mais l'URL n'est pas renvoyée lorsque j'interroge les onglets à partir d'un appel require() dans le fichier main.js Du popup:

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

La console affiche undefined pour l'URL. Cependant, si je fais le même appel à partir d'un fichier .js ordinaire qui n'utilise pas require(), cela fonctionne très bien:

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

Cela affiche l'URL correcte, et je peux accéder à cet appel global tabURL à l'intérieur de l'appel require() très bien. Lorsque je clique avec le bouton droit sur le bouton du navigateur et inspecte la fenêtre contextuelle, la sortie de la console ressemble à ceci:

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

Plus étrange encore, j'ai parfois vu l'URL disponible depuis cet appel à chrome.tabs.query() à l'intérieur de require() appel. Mais surtout cela ne fonctionne pas. Quelque chose sur la façon dont RequireJS charge les scripts semble confondre Chrome et supprimer l'accès URL pour le script chargé. C'est dans Chrome 40 sous Windows.

Évidemment, la solution de contournement consiste à récupérer l'URL dans un script séparé et à la stocker dans une variable, mais cela semble un peu délicat. Je voudrais voir s'il existe un moyen approprié de faire fonctionner cela avec RequireJS.

La source complète du plugin est ici si quelqu'un veut le tester sur sa machine: https://github.com/fwextensions/requirejs-url-test


Éditer

Comme l'explique Rob W. ci-dessous, cela n'a en fait rien à voir avec RequireJS. La seule raison pour laquelle le code dans mon fichier get-url.js Ci-dessus a renvoyé l'URL correcte est qu'il s'est produit avant l'exécution de la fenêtre devtools. Si je change ce fichier en ceci:

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

Il s'exécute ensuite après l'ouverture de la fenêtre devtools et échoue également. RequireJS n'est pas le coupable.

15
jdunning

Vous ne voyez pas d'URL car vous avez uniquement défini l'autorisation activeTab (et non tabs) ET la dernière fenêtre ciblée est constituée des outils de développement (pour lesquels vous n'avez pas activeTab access) (et puisque Chrome 41, devtools tabs/windows sont invisibles pour les extensions , donc tabs sera un tableau vide) ).

La bonne nouvelle est que ce problème est spécifique à la fenêtre devtools en cours d'ouverture pour votre page d'extension, donc le problème se produit uniquement pendant le développement et non lors de l'utilisation réelle par les utilisateurs.

Les popups d'extension sont associés à une fenêtre, vous pouvez donc utiliser chrome.tabs.query avec currentWindow:true pour obtenir la bonne réponse:

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

Pour surmonter le bogue devTools signalé par Rob W. dans son article, la solution de contournement getActiveTab suivante semble toujours fonctionner pour moi (même s'il y a plusieurs fenêtres devTools ouvertes). Cela fonctionne en enregistrant toujours une référence au activeTabId dans la page d'arrière-plan, chaque fois que le tabs.onActivated un événement se déclenche.

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

    }
  });
}
4
jake