Javascript 为什么在 Chrome 扩展程序中使用 RequireJS 调用时 chrome.tabs.query() 不返回选项卡的 URL?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28786723/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 02:25:04  来源:igfitidea点击:

Why doesn't chrome.tabs.query() return the tab's URL when called using RequireJS in a Chrome extension?

javascriptgoogle-chromegoogle-chrome-extensionrequirejs

提问by jdunning

I have a simple Chrome extension that adds a browser action. When the extension's popup is opened, it needs to access the current tab's URL. Since it doesn't need access to all the tabs, I just have the activeTabpermission specified in the manifest:

我有一个简单的 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/*"
    ]
}

In theory, that should give the popup access to the active tab's URL, but the URL is not returned when I query the tabs from within a require()call in the popup's main.jsfile:

从理论上讲,这应该使弹出窗口可以访问活动选项卡的 URL,但是当我从require()弹出窗口main.js文件的调用中查询选项卡时,不会返回 URL :

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

The console shows undefinedfor the URL. However, if I make the same call from a plain .js file that doesn't use require(), it works fine:

控制台显示undefinedURL。但是,如果我从不使用 的普通 .js 文件进行相同的调用require(),则它工作正常:

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

That displays the correct URL, and I can access that global tabURLinside the require()call just fine. When I right-click the browser button and inspect the popup, the console output looks like this:

这显示了正确的 URL,我可以tabURLrequire()调用中访问该全局变量就好了。当我右键单击浏览器按钮并检查弹出窗口时,控制台输出如下所示:

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

Even stranger is that I've sometimesseen the URL available from within that call to chrome.tabs.query()inside the require()call. But mostly it doesn't work. Something about how RequireJS loads scripts seems to confuse Chrome and take away the URL access for the loaded script. This is in Chrome 40 on Windows.

更奇怪的是,我有时会看到从该调用chrome.tabs.query()内部到该调用内部可用的 URL require()。但大多数情况下它不起作用。关于 RequireJS 如何加载脚本的一些事情似乎让 Chrome 感到困惑并剥夺了加载脚本的 URL 访问权限。这是在 Windows 上的 Chrome 40 中。

Obviously, the workaround is to grab the URL in a separate script and store it in a variable, but that feels a bit kludgy. I'd like to see if there's a proper way of getting this to work with RequireJS.

显然,解决方法是在单独的脚本中获取 URL 并将其存储在变量中,但这感觉有点笨拙。我想看看是否有一种正确的方法可以让它与 RequireJS 一起使用。

The full plugin source is here if anyone wants to test it on their machine: https://github.com/fwextensions/requirejs-url-test

如果有人想在他们的机器上测试它,完整的插件源在这里:https: //github.com/fwextensions/requirejs-url-test



Edit

编辑

As Rob W. explains below, this actually has nothing to do with RequireJS. The only reason that the code in my get-url.jsfile above returned the correct URL was that it happened to run before the devtools window opened. If I change that file to this:

正如 Rob W. 在下面解释的,这实际上与 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);

Then it runs after the devtools window is open and fails as well. RequireJS isn't the culprit.

然后它在 devtools 窗口打开后运行并且也失败了。RequireJS 不是罪魁祸首。

回答by Rob W

You don't see a URL because you've only set the activeTabpermission (not the tabs) permission AND the last focused window is the developer tools (for which you don't have activeTabaccess) (and since Chrome 41, devtools tabs/windows are invisible to extensions, so tabswill be an empty array).

您看不到 URL,因为您只设置了activeTab权限(而不是tabs)权限,并且最后一个聚焦窗口是开发人员工具(您无权activeTab访问)(从 Chrome 41 开始,devtools 选项卡/窗口是对 extensions 不可见,因此tabs将是一个空数组)。

The good news is that this problem is specific to the devtools window being opened for your extension page, so the issue only occurs during development and not during actual use by users.

好消息是,此问题特定于为您的扩展页面打开的 devtools 窗口,因此该问题仅发生在开发期间,而不是用户实际使用期间。

Extension popups are associated with a window, so you can use chrome.tabs.querywith currentWindow:trueto get the correct answer:

扩展弹出窗口与一个窗口相关联,因此您可以使用chrome.tabs.querywithcurrentWindow:true来获得正确的答案:

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

回答by jake

To overcome the devTools bug that Rob W. reported in his post, the following getActiveTabworkaround seems to consistently work for me (even when there are multiple devTools windows open). It works by always saving a reference to the activeTabIdin the background page, whenever the tabs.onActivatedevent fires.

为了克服 Rob W. 在他的帖子中报告的 devTools 错误,以下getActiveTab解决方法似乎对我始终有效(即使打开了多个 devTools 窗口)。它的工作原理是activeTabIdtabs.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.');
        }
      });

    }
  });
}