升级或安装后重新注入Chrome扩展程序内容脚本

Tom*_*rth 48 browser-extension google-chrome-extension content-script

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

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

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

Tom*_*rth 31

有一种方法可以让内容脚本在扩展后继续运行,并在安装后立即使用它.

安装

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

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

"background": {
    "scripts": ["background.js"]
},
Run Code Online (Sandbox Code Playgroud)

background.js:

// Add a `manifest` property to the `chrome` object.
chrome.manifest = chrome.app.getDetails();

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);
            }
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

升级

升级方法依赖于在禁用,卸载或升级扩展后注入内容脚本的事实.

建立端口连接时,会添加onDisconnect处理程序.这在断开连接事件后等待一秒钟,然后尝试重新连接.如果失败,则会触发另一个onDisconnect,以便再次进行该过程,直到建立连接.它并不完美,但它确实有效.

内容脚本:

var port;

// Attempt to reconnect
var reconnectToExtension = function () {
    // Reset port
    port = null;
    // Attempt to reconnect after 1 second
    setTimeout(connectToExtension, 1000 * 1);
};

// Attempt to connect
var connectToExtension = function () {

    // Make the connection
    port = chrome.runtime.connect({name: "my-port"});

    // When extension is upgraded or disabled and renabled, the content scripts
    // will still be injected, so we have to reconnect them.
    // We listen for an onDisconnect event, and then wait for a second before
    // trying to connect again. Becuase chrome.runtime.connect fires an onDisconnect
    // event if it does not connect, an unsuccessful connection should trigger
    // another attempt, 1 second later.
    port.onDisconnect.addListener(reconnectToExtension);

};

// Connect for the first time
connectToExtension();
Run Code Online (Sandbox Code Playgroud)

  • 由于http://crbug.com/168263(不要让孤立的内容脚本与其扩展进行通信,我不确定这是否会起作用.).`chrome.runtime.sendMessage`没有.我可能错了,但如果人们遇到麻烦,改变可能就是原因. (6认同)
  • 在chrome 46中你需要使用`chrome.runtime.getManifest()`而不是`chrome.manifest`. (2认同)
  • 要执行 chrome.tabs.executeScript,您必须将权限“tabs”、“http://*/*”、“https://*/*”添加到您的manifest.json (2认同)

小智 21

不刷新页面的情况下强制注入内容脚本的唯一方法是通过编程注入.

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

使用以下命令获取所有标签:
chrome.tabs.query

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

  • 我很确定这是唯一的方法.我使用清单注入和编程注入实现了类似的操作,因此注入了首次加载后台脚本时打开的所有选项卡,并且所有新选项卡都由正常的清单注入处理.但是,你需要注意的是你在DOM或页面上下文留下的任何东西,例如重新加载或升级,所以你应该有一个功能来撤消你已经完成的所有事情,但也需要获得新的上下文和老人谈谈. (3认同)

Pra*_*Jha 9

在您的后台脚本中尝试此操作。许多旧方法现在已被弃用,因此我重构了代码。对于我的使用,我只安装单个 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));
                }
            })
        }
    });    
}
Run Code Online (Sandbox Code Playgroud)