LocalCDN-Firefox-Chrome-Brave/core/state-manager.js

389 lines
13 KiB
JavaScript
Raw Normal View History

2020-02-27 13:45:29 +01:00
/**
* State Manager
2020-06-30 18:41:58 +02:00
* Belongs to LocalCDN (since 2020-02-26)
* (Origin: Decentraleyes)
2020-02-27 13:45:29 +01:00
*
* @author Thomas Rientjes
* @since 2017-03-10
*
2020-06-30 18:41:58 +02:00
* @author nobody
* @since 2020-02-26
*
2020-02-27 13:45:29 +01:00
* @license MPL 2.0
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
'use strict';
2021-02-17 07:01:08 +01:00
2020-02-27 13:45:29 +01:00
/**
* State Manager
*/
let stateManager = {};
2020-02-27 13:45:29 +01:00
2021-02-17 07:01:08 +01:00
2020-02-27 13:45:29 +01:00
/**
* Public Methods
*/
stateManager.registerInjection = function (tabIdentifier, injection, url) {
let injectionIdentifier, registeredTab, injectionCount, missingCount, blockedCount,
initiatorDomain, htmlFilterIsActive;
2020-02-27 13:45:29 +01:00
if (injection['result'] !== false) {
injectionIdentifier = injection.source + injection.path;
registeredTab = stateManager.tabs[tabIdentifier];
registeredTab.injections[injectionIdentifier] = injection;
}
initiatorDomain = helpers.extractDomainFromUrl(url, true) || Address.EXAMPLE;
2022-07-10 07:10:26 +02:00
htmlFilterIsActive = manipulateDOM.checkHtmlFilterEnabled(initiatorDomain);
if (registeredTab !== undefined) {
injectionCount = Object.keys(registeredTab.injections).length || 0;
missingCount = registeredTab.missing || 0;
blockedCount = registeredTab.blocked || 0;
} else {
return;
}
2020-02-27 13:45:29 +01:00
if (injectionCount > 0) {
chrome.browserAction.setTitle({
'tabId': tabIdentifier,
'title': `LocalCDN (${injectionCount})`
});
}
2021-03-13 06:55:20 +01:00
if (stateManager.showIconBadge === true) {
if ((missingCount > 0 || blockedCount > 0) && stateManager.changeBadgeColorMissingResources) {
wrappers.setBadgeColoring(tabIdentifier, BadgeSettingMissingResource.TYPE);
2022-07-10 07:10:26 +02:00
} else if (htmlFilterIsActive) {
wrappers.setBadgeColoring(tabIdentifier, BadgeSettingHTMLFilter.TYPE);
2021-03-13 06:55:20 +01:00
} else {
wrappers.setBadgeColoring(tabIdentifier, BadgeSetting.TYPE);
2021-03-13 06:55:20 +01:00
}
2023-07-13 09:07:02 +02:00
wrappers.setBadgeText(tabIdentifier, (injectionCount + missingCount + blockedCount));
}
if (isNaN(storageManager.amountInjected)) {
2020-08-30 18:56:36 +02:00
storageManager.type.get(Setting.AMOUNT_INJECTED, function (items) {
storageManager.amountInjected = items.amountInjected;
2020-08-30 18:56:36 +02:00
storageManager.type.set({
[Setting.AMOUNT_INJECTED]: ++storageManager.amountInjected
2020-02-27 13:45:29 +01:00
});
});
} else {
2020-08-30 18:56:36 +02:00
chrome.storage.local.set({
[Setting.AMOUNT_INJECTED]: ++storageManager.amountInjected
2020-02-27 13:45:29 +01:00
});
}
2021-02-19 07:22:14 +01:00
2020-08-08 07:30:04 +02:00
if (stateManager.internalStatistics) {
stats.setStats(injection);
}
2020-02-27 13:45:29 +01:00
};
2020-10-17 07:09:30 +02:00
stateManager.addDomainToAllowlist = function (domain) {
2020-02-27 13:45:29 +01:00
return new Promise((resolve) => {
2020-10-17 07:09:30 +02:00
let allowlistedDomains = requestAnalyzer.allowlistedDomains;
2020-02-27 13:45:29 +01:00
2021-02-19 07:22:14 +01:00
allowlistedDomains[domain] = true;
2020-10-17 07:09:30 +02:00
storageManager.type.set({allowlistedDomains}, resolve);
2020-02-27 13:45:29 +01:00
});
};
2020-10-17 07:09:30 +02:00
stateManager.removeDomainFromAllowlist = function (domain) {
2020-02-27 13:45:29 +01:00
return new Promise((resolve) => {
let allowlistedDomains;
2021-01-17 09:52:49 +01:00
allowlistedDomains = requestAnalyzer.allowlistedDomains;
if (allowlistedDomains[domain]) {
delete allowlistedDomains[domain];
} else {
for (const key in allowlistedDomains) {
if (key.startsWith('*.') && domain.endsWith(key.substring(2))) {
delete allowlistedDomains[key];
break;
}
}
2021-01-17 09:52:49 +01:00
}
2020-02-27 13:45:29 +01:00
2020-10-17 07:09:30 +02:00
storageManager.type.set({allowlistedDomains}, resolve);
2020-02-27 13:45:29 +01:00
});
};
stateManager.addDomainToManipulateDOMlist = function (domain) {
return new Promise((resolve) => {
let domainsManipulateDOM = requestAnalyzer.domainsManipulateDOM;
2021-02-19 07:22:14 +01:00
domainsManipulateDOM[domain] = true;
2020-08-30 18:56:36 +02:00
storageManager.type.set({domainsManipulateDOM}, resolve);
});
};
stateManager.removeDomainFromManipulateDOMlist = function (domain) {
return new Promise((resolve) => {
let domainsManipulateDOM = requestAnalyzer.domainsManipulateDOM;
2021-02-19 07:22:14 +01:00
delete domainsManipulateDOM[domain];
2020-08-30 18:56:36 +02:00
storageManager.type.set({domainsManipulateDOM}, resolve);
});
};
2021-08-13 06:15:10 +02:00
stateManager.addDomainToGoogleFontsList = function (domain) {
return new Promise((resolve) => {
let allowedDomainsGoogleFonts = interceptor.allowedDomainsGoogleFonts;
allowedDomainsGoogleFonts[domain] = true;
storageManager.type.set({allowedDomainsGoogleFonts}, resolve);
});
};
stateManager.removeDomainFromGoogleFontsList = function (domain) {
return new Promise((resolve) => {
let allowedDomainsGoogleFonts = interceptor.allowedDomainsGoogleFonts;
delete allowedDomainsGoogleFonts[domain];
storageManager.type.set({allowedDomainsGoogleFonts}, resolve);
});
};
2020-02-27 13:45:29 +01:00
/**
* Private Methods
*/
stateManager._createTab = function (tab) {
let tabIdentifier, requestFilters;
tabIdentifier = tab.id;
stateManager.tabs[tabIdentifier] = {
'injections': {},
'missing': 0,
'blocked': 0
2020-02-27 13:45:29 +01:00
};
requestFilters = {
'tabId': tabIdentifier,
'urls': stateManager.validHosts
};
chrome.webRequest.onBeforeRequest.addListener(function (requestDetails) {
2020-06-21 08:18:18 +02:00
tab = stateManager.tabs[tabIdentifier].details || {};
2020-02-27 13:45:29 +01:00
return interceptor.handleRequest(requestDetails, tabIdentifier, tab);
}, requestFilters, [WebRequest.BLOCKING]);
};
stateManager._removeTab = function (tabIdentifier) {
delete stateManager.tabs[tabIdentifier];
};
stateManager._updateTab = function (details) {
2020-10-17 07:09:30 +02:00
let tabDomain, domainIsAllowlisted, frameIdentifier, tabIdentifier;
2020-02-27 13:45:29 +01:00
tabDomain = helpers.extractDomainFromUrl(details.url, true);
2020-10-17 07:09:30 +02:00
domainIsAllowlisted = stateManager._domainIsListed(tabDomain);
2020-02-27 13:45:29 +01:00
frameIdentifier = details.frameId;
tabIdentifier = details.tabId;
if (frameIdentifier !== 0 || tabIdentifier === -1) {
return;
}
chrome.browserAction.setTitle({
'tabId': tabIdentifier,
'title': 'LocalCDN (0)'
});
2020-10-17 07:09:30 +02:00
if (domainIsAllowlisted) {
2020-02-27 13:45:29 +01:00
stateManager._setIconDisabled(tabIdentifier);
chrome.browserAction.setTitle({
'tabId': tabIdentifier,
'title': 'LocalCDN ()'
});
}
if (stateManager.showIconBadge === true) {
stateManager._clearBadgeText(tabIdentifier);
}
if (stateManager.tabs[tabIdentifier]) {
stateManager.tabs[tabIdentifier].injections = {};
stateManager.tabs[tabIdentifier].missing = 0;
stateManager.tabs[tabIdentifier].blocked = 0;
2020-02-27 13:45:29 +01:00
}
};
stateManager._handleStorageChanged = function (changes) {
if (Setting.SHOW_ICON_BADGE in changes) {
stateManager.showIconBadge = changes.showIconBadge.newValue;
if (changes.showIconBadge.newValue !== true) {
chrome.tabs.query({}, function (tabs) {
tabs.forEach(stateManager._removeIconBadgeFromTab);
});
}
2021-02-19 07:22:14 +01:00
} else if (Setting.STRIP_METADATA in changes) {
2020-02-27 13:45:29 +01:00
requestSanitizer.disable();
if (changes.stripMetadata.newValue !== false) {
requestSanitizer.enable();
}
2021-02-19 07:22:14 +01:00
} else if (Setting.NEGATE_HTML_FILTER_LIST in changes) {
stateManager.getInvertOption = changes.negateHtmlFilterList.newValue;
2021-02-19 07:22:14 +01:00
} else if (Setting.SELECTED_ICON in changes) {
stateManager.selectedIcon = changes.selectedIcon.newValue;
2021-02-19 07:22:14 +01:00
} else if (Setting.INTERNAL_STATISTICS in changes) {
2020-08-08 07:30:04 +02:00
stateManager.internalStatistics = changes.internalStatistics.newValue;
2021-02-19 07:22:14 +01:00
} else if (Setting.INTERNAL_STATISTICS_DATA in changes) {
stats.data = changes.internalStatisticsData.newValue;
2021-02-21 19:56:13 +01:00
} else if (Setting.HIDE_DONATION_BUTTON in changes) {
stateManager.hideDonationButton = changes.hideDonationButton.newValue;
2021-03-13 06:55:20 +01:00
} else if (Setting.CHANGE_BADGE_COLOR_MISSING_RESOURCES in changes) {
stateManager.changeBadgeColorMissingResources = changes.changeBadgeColorMissingResources.newValue;
} else if (Setting.LOGGING in changes) {
stateManager.logging = changes.enableLogging.newValue;
} else if (Setting.BADGE_DEFAULT_TEXT_COLOR in changes) {
wrappers.badgeDefaultTextColor = changes.badgeDefaultTextColor.newValue;
} else if (Setting.BADGE_DEFAULT_BACKGROUND_COLOR in changes) {
wrappers.badgeDefaultBackgroundColor = changes.badgeDefaultBackgroundColor.newValue;
} else if (Setting.BADGE_HTML_FILTER_TEXT_COLOR in changes) {
wrappers.badgeHTMLfilterTextColor = changes.badgeHTMLfilterTextColor.newValue;
} else if (Setting.BADGE_HTML_FILTER_BACKGROUND_COLOR in changes) {
wrappers.badgeHTMLFilterBackgroundColor = changes.badgeHTMLFilterBackgroundColor.newValue;
}
2020-02-27 13:45:29 +01:00
};
stateManager._clearBadgeText = function (tabIdentifier) {
wrappers.setBadgeText(tabIdentifier, '');
2020-02-27 13:45:29 +01:00
};
stateManager._removeIconBadgeFromTab = function (tab) {
stateManager._clearBadgeText(tab.id);
};
stateManager._domainIsListed = function (domain, listname) {
2020-02-27 13:45:29 +01:00
if (domain !== null) {
2020-10-17 07:09:30 +02:00
let allowlistRecord, isAllowlisted;
2020-02-27 13:45:29 +01:00
2021-02-17 07:01:08 +01:00
if (listname === 'manipulate-dom') {
allowlistRecord = helpers.checkAllowlisted(domain, requestAnalyzer.domainsManipulateDOM);
2020-10-17 07:09:30 +02:00
isAllowlisted = Boolean(allowlistRecord);
} else {
allowlistRecord = helpers.checkAllowlisted(domain, requestAnalyzer.allowlistedDomains);
2020-10-17 07:09:30 +02:00
isAllowlisted = Boolean(allowlistRecord);
}
2020-10-17 07:09:30 +02:00
return isAllowlisted;
2020-02-27 13:45:29 +01:00
}
return false;
};
stateManager._setIconDisabled = function (tabIdentifier) {
wrappers.setIcon({
'path': stateManager.selectedIcon || 'Default',
2020-02-27 13:45:29 +01:00
'tabId': tabIdentifier
}, 'Disabled');
2020-02-27 13:45:29 +01:00
};
2020-04-30 19:13:27 +02:00
2020-02-27 13:45:29 +01:00
/**
* Initializations
*/
stateManager.requests = {};
stateManager.tabs = {};
2022-12-13 06:08:31 +01:00
stateManager.getInvertOption = true;
2020-02-27 13:45:29 +01:00
stateManager.validHosts = [];
stateManager.selectedIcon = 'Default';
2020-08-08 07:30:04 +02:00
stateManager.internalStatistics = false;
2021-02-21 19:56:13 +01:00
stateManager.hideDonationButton = false;
2021-03-13 06:55:20 +01:00
stateManager.changeBadgeColorMissingResources = false;
stateManager.logging = false;
2020-02-27 13:45:29 +01:00
for (let mapping in mappings.cdn) {
2020-02-27 13:45:29 +01:00
let supportedHost = Address.ANY_PROTOCOL + mapping + Address.ANY_PATH;
stateManager.validHosts.push(supportedHost);
}
chrome.tabs.query({}, function (tabs) {
tabs.forEach(stateManager._createTab);
});
2021-03-13 06:55:20 +01:00
storageManager.type.get([
Setting.SHOW_ICON_BADGE,
Setting.NEGATE_HTML_FILTER_LIST,
2021-03-13 06:55:20 +01:00
Setting.SELECTED_ICON,
Setting.INTERNAL_STATISTICS,
Setting.HIDE_DONATION_BUTTON,
Setting.CHANGE_BADGE_COLOR_MISSING_RESOURCES,
Setting.LOGGING,
Setting.AMOUNT_INJECTED
2021-03-13 06:55:20 +01:00
], function (items) {
2020-02-27 13:45:29 +01:00
if (items.showIconBadge === undefined) {
items.showIconBadge = true;
}
if (items.selectedIcon === undefined) {
stateManager.selectedIcon = 'Default';
}
2022-12-13 06:08:31 +01:00
if (items.negateHtmlFilterList === undefined) {
stateManager.getInvertOption = true;
} else {
stateManager.getInvertOption = items.negateHtmlFilterList;
}
2020-02-27 13:45:29 +01:00
stateManager.showIconBadge = items.showIconBadge;
stateManager.selectedIcon = items.selectedIcon;
stateManager.internalStatistics = items.internalStatistics;
stateManager.hideDonationButton = items.hideDonationButton;
2021-03-13 06:55:20 +01:00
stateManager.changeBadgeColorMissingResources = items.changeBadgeColorMissingResources;
stateManager.logging = items.enableLogging;
stateManager.amountInjected = items.amountInjected;
2020-02-27 13:45:29 +01:00
});
2020-08-08 07:30:04 +02:00
chrome.storage.local.get([Setting.INTERNAL_STATISTICS], function (items) {
stateManager.internalStatistics = items.internalStatistics;
});
2020-02-27 13:45:29 +01:00
/**
* Event Handlers
*/
chrome.tabs.onCreated.addListener(stateManager._createTab);
chrome.tabs.onRemoved.addListener(stateManager._removeTab);
chrome.webRequest.onBeforeRequest.addListener(function (requestDetails) {
if (requestDetails.tabId !== -1 && stateManager.tabs[requestDetails.tabId]) {
stateManager.tabs[requestDetails.tabId].details = {
'url': requestDetails.url
};
}
}, {'types': [WebRequestType.MAIN_FRAME], 'urls': [Address.ANY]}, [WebRequest.BLOCKING]);
2020-02-27 13:45:29 +01:00
chrome.webNavigation.onCommitted.addListener(stateManager._updateTab, {
'url': [{'urlContains': ':'}]
});
chrome.webRequest.onErrorOccurred.addListener(function (requestDetails) {
if (stateManager.requests[requestDetails.requestId]) {
delete stateManager.requests[requestDetails.requestId];
}
}, {'urls': [Address.ANY]});
chrome.webRequest.onBeforeRedirect.addListener(function (requestDetails) {
let knownRequest = stateManager.requests[requestDetails.requestId];
if (knownRequest) {
stateManager.registerInjection(
knownRequest.tabIdentifier,
knownRequest.targetDetails,
requestDetails.originUrl
);
2020-02-27 13:45:29 +01:00
delete stateManager.requests[requestDetails.requestId];
}
}, {'urls': [Address.ANY]});
chrome.storage.onChanged.addListener(stateManager._handleStorageChanged);