P粉8072394162023-08-25 11:24:31
The only way to force the injection of a content script without refreshing the page is through programmatic injection.
You can use Chrome's Tag API to get all tags and inject code into them. For example, you could store a version number in local storage and every time you check if the version number in the background page is out of date (if it is), you could get all active tags and inject your code programmatically, or whatever Other solutions to ensure the extension is updated.
Use the following code to get all tags:
chrome.tabs.query
and inject your code into all pages
chrome.tabs.executeScript(tabId, {file: "content_script.js"});
P粉1584737802023-08-25 00:54:45
There is a way to make content script-heavy extensions continue to work properly after upgrading and have them take effect immediately after installation.
The way to install it is to simply loop through all tabs in all windows and programmatically inject some script in the tab with matching URL.
manifest.json:
"background": {"service_worker": "background.js"}, "permissions": ["scripting"], "host_permissions": ["<all_urls>"],
These host_permissions should be the same as the matches
of the content script.
background.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, }); } } });
This is a simplified example that does not deal with frames. You can use the getAllFrames API and match URLs yourself, see the matching patterns documentation.
Obviously you have to do this 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.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); } } } });
In ancient Chrome 26 and earlier, content scripts could restore connections to background scripts. This was fixed in 2013http://crbug.com/168263. You can see an example of this technique in an earlier version of this answer.