Reinject content scripts on install/update/enabling the extension

The injection code also runs outside of onInstalled event so we check first if a content script belonging to our execution context "generation" is already injected. This can happen on browser startup: the background page is loaded in several seconds after the normal web page tabs are loaded with our content script(s) already injected. The check itself is simply a "ping" message to each tab that should return true if the content script is alive and kicking.
This commit is contained in:
tophf 2017-03-15 15:41:39 +03:00
parent 34cd025487
commit e658255c36
4 changed files with 53 additions and 4 deletions

View File

@ -52,6 +52,9 @@ function applyOnMessage(request, sender, sendResponse) {
case "styleDisableAll":
disableAll(request.disableAll);
break;
case "ping":
sendResponse(true);
break;
}
}

View File

@ -1,3 +1,5 @@
/* globals wildcardAsRegExp, KEEP_CHANNEL_OPEN */
var frameIdMessageable;
runTryCatch(function() {
chrome.tabs.sendMessage(0, {}, {frameId: 0}, function() {
@ -202,3 +204,41 @@ chrome.storage.local.get('version', prefs => {
}
}
});
// after the extension was enabled or just installed
injectContentScripts({reason: 'update'});
// after an actual update
chrome.runtime.onInstalled.addListener(injectContentScripts);
function injectContentScripts({reason, previousVersion, id, checkFirst} = {}) {
// reason: install, update, chrome_update, shared_module_update
// the "install" case is ignored because it was already handled by explicit invocation of this function
if (!/update/.test(reason)) {
return;
}
const contentScripts = chrome.app.getDetails().content_scripts;
for (let cs of contentScripts) {
cs.matches = cs.matches.map(m => m == '<all_urls>' ? m : wildcardAsRegExp(m));
}
chrome.tabs.query({url: '*://*/*'}, tabs => {
for (let tab of tabs) {
for (let cs of contentScripts) {
for (let m of cs.matches) {
if (m == '<all_urls>' || tab.url.match(m)) {
chrome.tabs.sendMessage(tab.id, {method: 'ping'}, pong => {
if (!pong) {
chrome.tabs.executeScript(tab.id, {
file: cs.js[0],
runAt: cs.run_at,
allFrames: cs.all_frames,
}, result => chrome.runtime.lastError); // ignore lastError just in case
}
});
// inject the content script just once
break;
}
}
}
}
});
}

View File

@ -1,3 +1,4 @@
/* globals stringAsRegExp */
"use strict";
var styleId = null;
@ -1643,10 +1644,6 @@ chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
}
});
function stringAsRegExp(s, flags) {
return new RegExp(s.replace(/[{}()\[\]\/\\.+?^$:=*!|]/g, "\\$&"), flags);
}
function getComputedHeight(el) {
var compStyle = getComputedStyle(el);
return el.getBoundingClientRect().height +

View File

@ -123,3 +123,12 @@ function getTabRealURL(tab, callback) {
});
}
}
function stringAsRegExp(s, flags) {
return new RegExp(s.replace(/[{}()\[\]\/\\.+?^$:=*!|]/g, "\\$&"), flags);
}
// expands * as .*?
function wildcardAsRegExp(s, flags) {
return new RegExp(s.replace(/[{}()\[\]\/\\.+?^$:=!|]/g, "\\$&").replace(/\*/g, '.*?'), flags);
}