Chrome扩展内容脚本在升级或安装后重新注入 [英] Chrome extension content script re-injection after upgrade or install

查看:199
本文介绍了Chrome扩展内容脚本在升级或安装后重新注入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



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

解决方案

有一种方法可以允许内容脚本大量扩展安装完成后运行,并在安装后立即生效。安装安装

安装方法是只需遍历所有窗口中的所有选项卡,然后以编程方式将一些脚本插入到具有匹配URL的选项卡中。



显然,您必须在后台页面或在manifest.json中声明的活动页面脚本:

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


$ b

background.js:

$ c> //向`chrome`对象添加一个`manifest`属性。
chrome.manifest = chrome.app.getDetails();

var injectIntoTab = function(tab){
//你可以在这里迭代内容脚本
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]
});
}
}

//获取所有窗口
chrome.windows.getAll({
populate:true
},function(windows ){
var i = 0,w = windows.length,currentWindow;
for(; i currentWindow = windows [i];
var j = 0,t = currentWindow.tabs.length,currentTab;
for(; j currentTab = currentWindow.tabs [j];
//跳过chrome ://和https:// pages
if(!currentTab.url.match(/(chrome | https):\ / \ // gi)){
injectIntoTab(currentTab);
}
}
}
});



升级



升级方法依赖于在扩展被禁用,卸载或升级之后,内容脚本仍被注入。



当端口连接建立时,添加onDisconnect处理程序。这会在断开连接事件后等待一秒,然后尝试重新连接。如果失败,另一个onDisconnect将被触发,以便进程再次发生,直到建立连接。这不是完美的,但它的工作原理。



内容脚本:

  var port; 

尝试重新连接
var reconnectToExtension = function(){
//重置端口
port = null;
//尝试在1秒后重新连接
setTimeout(connectToExtension,1000 * 1);
};

尝试连接
var connectToExtension = function(){

//建立连接
port = chrome.runtime.connect({名称:my-port});

//当扩展名升级或禁用并且renabled时,内容脚本
//仍然会被注入,所以我们必须重新连接它们。
//我们监听一个onDisconnect事件,然后在
之前等待一秒钟//再次尝试连接。因为chrome.runtime.connect会触发一个onDisconnect
//事件,如果它没有连接,一个不成功的连接应该触发
//另一次尝试,1秒后。
port.onDisconnect.addListener(reconnectToExtension);

};

//首次连接
connectToExtension();


After the Chrome extension I'm working on is installed, or upgraded, the content scripts (specified in the manifest) are not re-injected so a page refresh is required to make the extension work. Is there a way to force the scripts to be injected again?

I believe I could inject them again programmatically by removing them from the manifest and then handling which pages to inject in the background page, but this is not a good solution.

I don't want to automatically refresh the user's tabs because that could lose some of their data. Safari automatically refreshes all pages when you install or upgrade an extension.

解决方案

There's a way to allow a content script heavy extension to continue functioning after an upgrade, and to make it work immediately upon installation.

Install

The install method is to simply iterate through all tabs in all windows, and inject some scripts programmatically into tabs with matching URLs.

Obviously, you have to do it in a background page or event page script declared in manifest.json:

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

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

Upgrade

The upgrade method relies on the fact that the content scripts are left injected after an extension is disabled, uninstalled or upgraded.

When the port connection is made, an onDisconnect handler is added. This waits a second after the disconnect event, then attempts to reconnect. If it fails, another onDisconnect is fired so the process happens again, until a connection is made. It's not perfect, but it works.

The content script:

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

这篇关于Chrome扩展内容脚本在升级或安装后重新注入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆