LocalCDN-Firefox-Chrome-Brave/core/manipulate-dom.js

109 lines
3.4 KiB
JavaScript
Raw Normal View History

2020-05-02 13:56:49 +02:00
/**
* Remove integrity checks from embedded CSS and JavaScript files
* Belongs to LocalCDN.
*
* @author nobody42
* @since 2020-02-27
*
* @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';
/**
* Manipulate DOM
*/
var manipulateDOM = {};
/**
* Private Methods
*/
manipulateDOM._getEncoding = function (domain) {
let encodingByDomain = CharsetDomains[domain];
if(typeof encodingByDomain === 'undefined') {
return 'UTF-8';
}
return encodingByDomain;
};
2020-05-02 13:56:49 +02:00
manipulateDOM._removeCrossOriginAndIntegrityAttr = function (details) {
// by Jaap (https://gitlab.com/Jaaap)
// https://gitlab.com/nobody42/localcdn/-/issues/66
let header = details.responseHeaders.find(h => h.name.toLowerCase() === 'content-type');
if (header && BrowserType.FIREFOX) {
let mimeType, charset, initiatorDomain, isWhitelisted;
mimeType = header.value.replace(/;.*/, '').toLowerCase();
2020-05-17 08:43:27 +02:00
charset = /charset\s*=/.test(header.value) ? header.value.replace(/^.*?charset\s*=\s*/, '') : undefined;
2020-05-02 13:56:49 +02:00
initiatorDomain = helpers.extractDomainFromUrl(details.url, true) || Address.EXAMPLE;
isWhitelisted = stateManager._domainIsWhitelisted(initiatorDomain);
if (!isWhitelisted && mimeType === 'text/html') {
header.value = 'text/html; charset=UTF-8';
2020-05-17 08:43:27 +02:00
let decoder = new TextDecoder(charset === undefined ? manipulateDOM._getEncoding(initiatorDomain) : charset);
2020-05-02 13:56:49 +02:00
let encoder = new TextEncoder();
let filter = browser.webRequest.filterResponseData(details.requestId);
//Note that this will not work if the '<script crossorigin="anonymous" src="dfgsfgd.com">' string is divided into two chunks, but we want to flush this data asap.
filter.ondata = evt => {
//remove crossorigin and integrity attributes
let str = decoder.decode(evt.data, {stream: true}).replace(/<(link|script)[^>]+>/ig, m => {
if (cdnDomainsRE.test(m))
return m.replace(/\s+(integrity|crossorigin)(="[^"]*"|='[^']*'|=[^"'`=\s]+|)/ig, '');
return m;
});
filter.write(encoder.encode(str));
}
filter.onstop = evt => {
let str = decoder.decode(); //end-of-stream
filter.write(encoder.encode(str));
filter.close();
}
}
2020-05-03 07:32:08 +02:00
return {responseHeaders: details.responseHeaders};
2020-05-02 13:56:49 +02:00
} else if(BrowserType.CHROMIUM) {
// Chromium browsers do not support webRequest.filterResponseData
// https://bugs.chromium.org/p/chromium/issues/detail?id=487422
console.warn('[ LocalCDN ] browser.webRequest.filterResponseData not supported by your browser.');
}
};
/**
* Initializations
*/
let whitelistedDomains = {};
let cdnDomainsRE = new RegExp('//(' + Object.keys(mappings).map(m => m.replace(/\W/g, '\\$&')).join('|') + ')/');
/**
* Event Handlers
*/
chrome.webRequest.onHeadersReceived.addListener(
manipulateDOM._removeCrossOriginAndIntegrityAttr,
{'types': [WebRequestType.MAIN_FRAME], 'urls': [Address.ANY]},
[WebRequest.BLOCKING, WebRequest.RESPONSE_HEADERS]
);