Chrome 扩展程序 - 获取最后一个网址而不是当前网址



我得到的是上次访问的网址,而不是当前的网址。(当我转到 site.com 然后转到 site2.com 时,我得到的URL是"site.com",刷新 site2.com 后,我得到了正确的网址。

基于这里的答案:
谷歌浏览器扩展程序获取页面信息
在镶边扩展程序中
显示当前网址

我想出了这个代码:

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",
  ]
}

内容.js

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

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

我还尝试将此代码直接放在内容中.js并且我收到错误并在后台.js并且 url 设置为 chrome://extensions/ .

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

正确的方法是什么?

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

问题:
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"(再次设置为时已晚)。

解决方案:
(一)
在回调内移动逻辑。
注意:每当回调(即 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 !!!
    }
});

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

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

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

最新更新