55

在安装或升级我正在使用的 Chrome 扩展程序后,不会重新注入内容脚本(在清单中指定),因此需要刷新页面才能使扩展程序正常工作。有没有办法强制再次注入脚本?

我相信我可以通过从清单中删除它们然后处理要在后台页面中注入哪些页面以编程方式再次注入它们,但这不是一个好的解决方案。

我不想自动刷新用户的标签,因为这可能会丢失他们的一些数据。安装或升级扩展程序时,Safari 会自动刷新所有页面。

4

6 回答 6

39

有一种方法可以让内容脚本繁重的扩展在升级后继续运行,并使其在安装后立即运行。

安装/升级

install 方法是简单地遍历所有窗口中的所有选项卡,并以编程方式将一些脚本注入到具有匹配 URL 的选项卡中。

显然,您必须在 manifest.json 中声明的后台页面事件页面脚本中执行此操作:

"background": {
    "scripts": ["background.js"]
},

背景.js:

// Add a `manifest` property to the `chrome` object.
chrome.manifest = chrome.runtime.getManifest();

var injectIntoTab = function (tab) {
    // You could iterate through the content scripts here
    var scripts = chrome.manifest.content_scripts[0].js;
    var i = 0, s = scripts.length;
    for( ; i < s; i++ ) {
        chrome.tabs.executeScript(tab.id, {
            file: scripts[i]
        });
    }
}

// Get all windows
chrome.windows.getAll({
    populate: true
}, function (windows) {
    var i = 0, w = windows.length, currentWindow;
    for( ; i < w; i++ ) {
        currentWindow = windows[i];
        var j = 0, t = currentWindow.tabs.length, currentTab;
        for( ; j < t; j++ ) {
            currentTab = currentWindow.tabs[j];
            // Skip chrome:// and https:// pages
            if( ! currentTab.url.match(/(chrome|https):\/\//gi) ) {
                injectIntoTab(currentTab);
            }
        }
    }
});

清单V3

清单.json:

"background": {"service_worker": "background.js"},
"permissions": ["scripting"],
"host_permissions": ["<all_urls"],

这些 host_permissions 应该与内容脚本的matches.

背景.js:

chrome.runtime.onInstalled.addListener(async () => {
  for (const cs of chrome.runtime.getManifest().content_scripts) {
    for (const tab of await chrome.tabs.query({url: cs.matches})) {
      chrome.scripting.executeScript({
        target: {tabId: tab.id},
        files: cs.js,
      });
    }
  }
});

这是一个不处理帧的简化示例。您可以使用getAllFrames API 并自己匹配 URL,请参阅匹配模式的文档。

历史琐事

在古老的 Chrome 26 和更早的版本中,内容脚本可以恢复与后台脚本的连接。它已于 2013 年修复http://crbug.com/168263。您可以在此答案的早期版本中看到此技巧的示例。

于 2012-07-22T08:23:56.067 回答
24

强制注入内容脚本而不刷新页面的唯一方法是通过程序注入。

您可以使用 chrome tabs API 获取所有选项卡并将代码注入其中。例如,您可以将清单版本存储在本地存储中,并且每次检查清单版本是否是旧版本(在后台页面中),如果是,您可以获得所有活动选项卡并以编程方式注入您的代码,或者任何其他可以让您确保扩展已更新。

使用以下方式获取所有选项卡:
chrome.tabs.query

并将您的代码注入所有页面
chrome.tabs.executeScript(tabId, {file: "content_script.js"});

于 2012-06-20T18:11:05.613 回答
6

在你的后台脚本中试试这个。很多老方法现在已经被弃用了,所以我重构了代码。对于我的使用,我只安装单个 content_script 文件。如果需要,您可以遍历 chrome.runtime.getManifest().content_scripts数组以获取所有 .js 文件。

chrome.runtime.onInstalled.addListener(installScript);

function installScript(details){
    // console.log('Installing content script in all tabs.');
    let params = {
        currentWindow: true
    };
    chrome.tabs.query(params, function gotTabs(tabs){
        let contentjsFile = chrome.runtime.getManifest().content_scripts[0].js[0];
        for (let index = 0; index < tabs.length; index++) {
            chrome.tabs.executeScript(tabs[index].id, {
                file: contentjsFile
            },
            result => {
                const lastErr = chrome.runtime.lastError;
                if (lastErr) {
                    console.error('tab: ' + tabs[index].id + ' lastError: ' + JSON.stringify(lastErr));
                }
            })
        }
    });    
}
于 2020-04-07T06:31:49.803 回答
2

Chrome 添加了一种方法来监听扩展的安装或升级事件。当此类事件发生时,可以重新注入内容脚本。 https://developers.chrome.com/extensions/runtime#event-onInstalled

于 2019-05-04T20:45:13.657 回答
0

由于https://bugs.chromium.org/p/chromium/issues/detail?id=168263,您的内容脚本和后台脚本之间的连接被切断。正如其他人所提到的,解决此问题的一种方法是重新注入内容脚本。这个 StackOverflow 答案中详细介绍了粗略的概述。

主要的棘手部分是在注入新的内容脚本之前有必要“破坏”您当前的内容脚本。销毁可能非常棘手,因此减少必须销毁的状态量的一种方法是制作一个小的可重复注入脚本,该脚本通过 DOM 与您的主要内容脚本对话。

于 2020-06-28T04:52:09.050 回答
-13

你不能?ver=2.10在你升级的css或js末尾添加吗?

"content_scripts": [ {
      "css": [ "css/cs.css?ver=2.10" ],
      "js": [ "js/contentScript.js?ver=2.10" ],
      "matches": [ "http://*/*", "https://*/*" ],
      "run_at": "document_end"
   } ],
于 2012-10-31T17:34:06.430 回答