【问题标题】:chrome extension - getting the last url instead of currentchrome 扩展 - 获取最后一个 url 而不是当前
【发布时间】:2013-11-16 14:31:13
【问题描述】:

我得到的是上次访问的 url,而不是当前的。 (当我访问 site.com 并随后访问 site2.com 时,我得到的网址是“site.com”,在我刷新 site2.com 后,我得到了正确的网址。

根据这里的答案:
Google Chrome Extension get page information
Display current URL in a chrome extension

我想出了这个代码:

manifest.json

{
  "manifest_version": 2,

  "browser_action": {
    "default_popup": "action.html"
  },
  "content_scripts": [
    {
      "matches": ["http://*/*", "https://*/*"],
      "js": ["content.js"],
      "run_at": "document_end"
    }
  ],
  "background": {
    "scripts": ["background.js"]
  },
  "permissions": [
    "tabs",
    "unlimitedStorage",
  ]
}

content.js

chrome.extension.sendRequest({method: "getUrl"}, function(response) {
  console.log(response.data);
});

background.js

chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
    if(request.method == "getUrl") {
      chrome.tabs.query({ currentWindow: true, active: true }, function (tabs) {
        currentUrl = tabs[0].url;
      });
      sendResponse({data: currentUrl});
    }
    else
      sendResponse({}); // snub them.
});

我还尝试将此代码直接放在 content.js 中,但在 background.js 中出现错误,并且 URL 设置为 chrome://extensions/

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

这样做的正确方法是什么?

【问题讨论】:

  • 你试过强制你的内容脚本在document loads之后运行吗?
  • 也发布您的清单。
  • @hiattp 我添加了"run_at": "document_end",但没有任何改变。
  • 为什么要使用内容脚本?仅背景页面就足以达到此目的。此外,在使用背景/事件页面时,您可以看到所有 URL 的导航,包括 chrome:// URL。查看chrome.webNavigation API,尤其是onCommitted 事件。

标签: google-chrome-extension


【解决方案1】:

首先: chrome.extension.sendRequest/onRequest 已弃用。请改用 chrome.runtime.sendMessage/onMessage
此外,尽可能选择 event pages 而不是背景页面。大多数情况下,将背景页面转换为事件页面几乎不需要任何时间,但可以节省大量资源。

问题:
chrome.tabs.query 是异步的。这意味着,当被调用时,它会初始化请求,然后完成其执行,以便执行脚本的下一部分。一旦请求完成,注册的回调函数就会被执行。所以,这就是你的情况:

  1. 您访问http://www.site1.com
  2. chrome.tabs.query({...}, callback) 被执行(注意回调尚未执行)。
  3. sendResponse({data: currentUrl}) 被执行(注意此时 currentUrl 没有定义)。
  4. chrome.tabs.query的请求完成并执行回调函数,设置currentUrl = "http://www.site1.com"(但只有在为时已晚)。
  5. 您访问http://www.site2.com
  6. chrome.tabs.query({...}, callback) 被执行(注意回调尚未执行)。
  7. sendResponse({data: currentUrl}) 被执行(注意此时 currentUrl 仍然等于第 4 步中的 http://www.site1.com)。
  8. chrome.tabs.query 的请求完成并执行回调函数,设置currentUrl = "http://www.site2.com"(再次只是在为时已晚)。

解决方案:
(A)
移动回调内部的逻辑。
注意:每当异步调用回调(即sendResponse)时,onMessage 侦听器必须返回true。)

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    if(request.method && (request.method == "getURL")) {
        if (sendResponse) {
            chrome.tabs.query({
                currentWindow: true,
                active: true
            }, function(tabs) {
                if (tabs.length > 0) {
                    sendResponse({ data: tabs[0].url });
                }
            });
            /* Since 'sendResponse' is to going be called
             * asynchronously, it is necessary to return 'true' */
            return true;
        }
    } else {
        // Do not talk to strangers !!!
    }
});

(B)
在您的情况下更简单,onMessage 侦听器的 sender 参数包含包含 URL 信息的字段 tab。例如:

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    if(request.method && (request.method == "getURL") && sendResponse) {
        sendResponse({ data: sender.tab.url });
    }
});

(C)
如果您只需要内容脚本上下文中的 URL,为什么不在内容脚本中使用location.href

【讨论】:

  • 我必须可耻地承认我确实需要解决方案(C)。但是无论我刷新多少次,(A)和(B)都返回未定义。 PS。我在background.js 中替换了 A、B 中的代码
  • 这很奇怪,因为我使用了完全相同的代码并且它有效。确保您已将内容脚本的 chrome.extension.sendRequest(...) 替换为 chrome.runtime.sendMessage(msg, function(response) {...});。您在控制台日志中看到任何错误吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-27
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
相关资源
最近更新 更多