e658255c36
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.
135 lines
4.5 KiB
JavaScript
135 lines
4.5 KiB
JavaScript
// keep message channel open for sendResponse in chrome.runtime.onMessage listener
|
|
const KEEP_CHANNEL_OPEN = true;
|
|
const OWN_ORIGIN = chrome.runtime.getURL('');
|
|
|
|
function notifyAllTabs(request) {
|
|
chrome.windows.getAll({populate: true}, windows => {
|
|
windows.forEach(win => {
|
|
win.tabs.forEach(tab => {
|
|
if (request.codeIsUpdated !== false || tab.url.startsWith(OWN_ORIGIN)) {
|
|
chrome.tabs.sendMessage(tab.id, request);
|
|
updateIcon(tab);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
// notify all open popups
|
|
const reqPopup = Object.assign({}, request, {method: 'updatePopup', reason: request.method});
|
|
chrome.runtime.sendMessage(reqPopup);
|
|
// notify self: the message no longer is sent to the origin in new Chrome
|
|
if (typeof applyOnMessage !== 'undefined') {
|
|
applyOnMessage(reqPopup);
|
|
}
|
|
}
|
|
|
|
function refreshAllTabs() {
|
|
return new Promise(resolve => {
|
|
chrome.windows.getAll({populate: true}, windows => {
|
|
windows.forEach((win, winIndex) => {
|
|
win.tabs.forEach((tab, tabIndex) => {
|
|
getStyles({matchUrl: tab.url, enabled: true, asHash: true}, styles => {
|
|
const message = {method: 'styleReplaceAll', styles};
|
|
if (tab.url == location.href && typeof applyOnMessage !== 'undefined') {
|
|
applyOnMessage(message);
|
|
} else {
|
|
chrome.tabs.sendMessage(tab.id, message);
|
|
}
|
|
updateIcon(tab, styles);
|
|
if (winIndex == windows.length - 1 && tabIndex == win.tabs.length - 1) {
|
|
resolve();
|
|
}
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
function updateIcon(tab, styles) {
|
|
// while NTP is still loading only process the request for its main frame with a real url
|
|
// (but when it's loaded we should process style toggle requests from popups, for example)
|
|
if (tab.url == "chrome://newtab/" && tab.status != "complete") {
|
|
return;
|
|
}
|
|
if (styles) {
|
|
// check for not-yet-existing tabs e.g. omnibox instant search
|
|
chrome.tabs.get(tab.id, function() {
|
|
if (!chrome.runtime.lastError) {
|
|
// for 'styles' asHash:true fake the length by counting numeric ids manually
|
|
if (styles.length === undefined) {
|
|
styles.length = 0;
|
|
for (var id in styles) {
|
|
styles.length += id.match(/^\d+$/) ? 1 : 0;
|
|
}
|
|
}
|
|
stylesReceived(styles);
|
|
}
|
|
});
|
|
return;
|
|
}
|
|
getTabRealURL(tab, function(url) {
|
|
// if we have access to this, call directly. a page sending a message to itself doesn't seem to work right.
|
|
if (typeof getStyles != "undefined") {
|
|
getStyles({matchUrl: url, enabled: true}, stylesReceived);
|
|
} else {
|
|
chrome.runtime.sendMessage({method: "getStyles", matchUrl: url, enabled: true}, stylesReceived);
|
|
}
|
|
});
|
|
|
|
function stylesReceived(styles) {
|
|
var disableAll = "disableAll" in styles ? styles.disableAll : prefs.get("disableAll");
|
|
var postfix = disableAll ? "x" : "" || styles.length == 0 ? "w" : "";
|
|
chrome.browserAction.setIcon({
|
|
path: {
|
|
// Material Design 2016 new size is 16px
|
|
16: "16" + postfix + ".png", 32: "32" + postfix + ".png",
|
|
// Chromium forks or non-chromium browsers may still use the traditional 19px
|
|
19: "19" + postfix + ".png", 38: "38" + postfix + ".png",
|
|
},
|
|
tabId: tab.id
|
|
}, function() {
|
|
// if the tab was just closed an error may occur,
|
|
// e.g. 'windowPosition' pref updated in edit.js::window.onbeforeunload
|
|
if (!chrome.runtime.lastError) {
|
|
var t = prefs.get("show-badge") && styles.length ? ("" + styles.length) : "";
|
|
chrome.browserAction.setBadgeText({text: t, tabId: tab.id});
|
|
chrome.browserAction.setBadgeBackgroundColor({
|
|
color: prefs.get(disableAll ? 'badgeDisabled' : 'badgeNormal')
|
|
});
|
|
}
|
|
});
|
|
//console.log("Tab " + tab.id + " (" + tab.url + ") badge text set to '" + t + "'.");
|
|
}
|
|
}
|
|
|
|
function getActiveTab(callback) {
|
|
chrome.tabs.query({currentWindow: true, active: true}, function(tabs) {
|
|
callback(tabs[0]);
|
|
});
|
|
}
|
|
|
|
function getActiveTabRealURL(callback) {
|
|
getActiveTab(function(tab) {
|
|
getTabRealURL(tab, callback);
|
|
});
|
|
}
|
|
|
|
function getTabRealURL(tab, callback) {
|
|
if (tab.url != "chrome://newtab/") {
|
|
callback(tab.url);
|
|
} else {
|
|
chrome.webNavigation.getFrame({tabId: tab.id, frameId: 0, processId: -1}, function(frame) {
|
|
frame && callback(frame.url);
|
|
});
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|