mirror of https://github.com/gorhill/uBlock.git
238 lines
7.7 KiB
JavaScript
238 lines
7.7 KiB
JavaScript
/*******************************************************************************
|
|
|
|
uBlock Origin - a comprehensive, efficient content blocker
|
|
Copyright (C) 2019-present Raymond Hill
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
|
|
|
Home: https://github.com/gorhill/uBlock
|
|
|
|
The scriptlets below are meant to be injected only into a
|
|
web page context.
|
|
*/
|
|
|
|
import { getSafeCookieValuesFn } from './cookie.js';
|
|
import { registerScriptlet } from './base.js';
|
|
import { safeSelf } from './safe-self.js';
|
|
|
|
/******************************************************************************/
|
|
|
|
export function getAllLocalStorageFn(which = 'localStorage') {
|
|
const storage = self[which];
|
|
const out = [];
|
|
for ( let i = 0; i < storage.length; i++ ) {
|
|
const key = storage.key(i);
|
|
const value = storage.getItem(key);
|
|
return { key, value };
|
|
}
|
|
return out;
|
|
}
|
|
registerScriptlet(getAllLocalStorageFn, {
|
|
name: 'get-all-local-storage.fn',
|
|
});
|
|
|
|
/******************************************************************************/
|
|
|
|
export function setLocalStorageItemFn(
|
|
which = 'local',
|
|
trusted = false,
|
|
key = '',
|
|
value = '',
|
|
) {
|
|
if ( key === '' ) { return; }
|
|
|
|
// For increased compatibility with AdGuard
|
|
if ( value === 'emptyArr' ) {
|
|
value = '[]';
|
|
} else if ( value === 'emptyObj' ) {
|
|
value = '{}';
|
|
}
|
|
|
|
const trustedValues = [
|
|
'',
|
|
'undefined', 'null',
|
|
'{}', '[]', '""',
|
|
'$remove$',
|
|
...getSafeCookieValuesFn(),
|
|
];
|
|
|
|
if ( trusted ) {
|
|
if ( value.includes('$now$') ) {
|
|
value = value.replaceAll('$now$', Date.now());
|
|
}
|
|
if ( value.includes('$currentDate$') ) {
|
|
value = value.replaceAll('$currentDate$', `${Date()}`);
|
|
}
|
|
if ( value.includes('$currentISODate$') ) {
|
|
value = value.replaceAll('$currentISODate$', (new Date()).toISOString());
|
|
}
|
|
} else {
|
|
const normalized = value.toLowerCase();
|
|
const match = /^("?)(.+)\1$/.exec(normalized);
|
|
const unquoted = match && match[2] || normalized;
|
|
if ( trustedValues.includes(unquoted) === false ) {
|
|
if ( /^-?\d+$/.test(unquoted) === false ) { return; }
|
|
const n = parseInt(unquoted, 10) || 0;
|
|
if ( n < -32767 || n > 32767 ) { return; }
|
|
}
|
|
}
|
|
|
|
try {
|
|
const storage = self[`${which}Storage`];
|
|
if ( value === '$remove$' ) {
|
|
const safe = safeSelf();
|
|
const pattern = safe.patternToRegex(key, undefined, true );
|
|
const toRemove = [];
|
|
for ( let i = 0, n = storage.length; i < n; i++ ) {
|
|
const key = storage.key(i);
|
|
if ( pattern.test(key) ) { toRemove.push(key); }
|
|
}
|
|
for ( const key of toRemove ) {
|
|
storage.removeItem(key);
|
|
}
|
|
} else {
|
|
storage.setItem(key, `${value}`);
|
|
}
|
|
} catch(ex) {
|
|
}
|
|
}
|
|
registerScriptlet(setLocalStorageItemFn, {
|
|
name: 'set-local-storage-item.fn',
|
|
dependencies: [
|
|
getSafeCookieValuesFn,
|
|
safeSelf,
|
|
],
|
|
});
|
|
|
|
/******************************************************************************/
|
|
|
|
export function removeCacheStorageItem(
|
|
cacheNamePattern = '',
|
|
requestPattern = ''
|
|
) {
|
|
if ( cacheNamePattern === '' ) { return; }
|
|
const safe = safeSelf();
|
|
const logPrefix = safe.makeLogPrefix('remove-cache-storage-item', cacheNamePattern, requestPattern);
|
|
const cacheStorage = self.caches;
|
|
if ( cacheStorage instanceof Object === false ) { return; }
|
|
const reCache = safe.patternToRegex(cacheNamePattern, undefined, true);
|
|
const reRequest = safe.patternToRegex(requestPattern, undefined, true);
|
|
cacheStorage.keys().then(cacheNames => {
|
|
for ( const cacheName of cacheNames ) {
|
|
if ( reCache.test(cacheName) === false ) { continue; }
|
|
if ( requestPattern === '' ) {
|
|
cacheStorage.delete(cacheName).then(result => {
|
|
if ( safe.logLevel > 1 ) {
|
|
safe.uboLog(logPrefix, `Deleting ${cacheName}`);
|
|
}
|
|
if ( result !== true ) { return; }
|
|
safe.uboLog(logPrefix, `Deleted ${cacheName}: ${result}`);
|
|
});
|
|
continue;
|
|
}
|
|
cacheStorage.open(cacheName).then(cache => {
|
|
cache.keys().then(requests => {
|
|
for ( const request of requests ) {
|
|
if ( reRequest.test(request.url) === false ) { continue; }
|
|
if ( safe.logLevel > 1 ) {
|
|
safe.uboLog(logPrefix, `Deleting ${cacheName}/${request.url}`);
|
|
}
|
|
cache.delete(request).then(result => {
|
|
if ( result !== true ) { return; }
|
|
safe.uboLog(logPrefix, `Deleted ${cacheName}/${request.url}: ${result}`);
|
|
});
|
|
}
|
|
});
|
|
});
|
|
}
|
|
});
|
|
}
|
|
registerScriptlet(removeCacheStorageItem, {
|
|
name: 'remove-cache-storage-item.fn',
|
|
world: 'ISOLATED',
|
|
dependencies: [
|
|
safeSelf,
|
|
],
|
|
});
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* set-local-storage-item.js
|
|
* set-session-storage-item.js
|
|
*
|
|
* Set a local/session storage entry to a specific, allowed value.
|
|
*
|
|
* Reference:
|
|
* https://github.com/AdguardTeam/Scriptlets/blob/master/src/scriptlets/set-local-storage-item.js
|
|
* https://github.com/AdguardTeam/Scriptlets/blob/master/src/scriptlets/set-session-storage-item.js
|
|
*
|
|
**/
|
|
|
|
export function setLocalStorageItem(key = '', value = '') {
|
|
setLocalStorageItemFn('local', false, key, value);
|
|
}
|
|
registerScriptlet(setLocalStorageItem, {
|
|
name: 'set-local-storage-item.js',
|
|
world: 'ISOLATED',
|
|
dependencies: [
|
|
setLocalStorageItemFn,
|
|
],
|
|
});
|
|
|
|
export function setSessionStorageItem(key = '', value = '') {
|
|
setLocalStorageItemFn('session', false, key, value);
|
|
}
|
|
registerScriptlet(setSessionStorageItem, {
|
|
name: 'set-session-storage-item.js',
|
|
world: 'ISOLATED',
|
|
dependencies: [
|
|
setLocalStorageItemFn,
|
|
],
|
|
});
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* trusted-set-local-storage-item.js
|
|
*
|
|
* Set a local storage entry to an arbitrary value.
|
|
*
|
|
* Reference:
|
|
* https://github.com/AdguardTeam/Scriptlets/blob/master/src/scriptlets/trusted-set-local-storage-item.js
|
|
*
|
|
**/
|
|
|
|
export function trustedSetLocalStorageItem(key = '', value = '') {
|
|
setLocalStorageItemFn('local', true, key, value);
|
|
}
|
|
registerScriptlet(trustedSetLocalStorageItem, {
|
|
name: 'trusted-set-local-storage-item.js',
|
|
requiresTrust: true,
|
|
world: 'ISOLATED',
|
|
dependencies: [
|
|
setLocalStorageItemFn,
|
|
],
|
|
});
|
|
|
|
export function trustedSetSessionStorageItem(key = '', value = '') {
|
|
setLocalStorageItemFn('session', true, key, value);
|
|
}
|
|
registerScriptlet(trustedSetSessionStorageItem, {
|
|
name: 'trusted-set-session-storage-item.js',
|
|
requiresTrust: true,
|
|
world: 'ISOLATED',
|
|
dependencies: [
|
|
setLocalStorageItemFn,
|
|
],
|
|
});
|