blob: bdf256a903df0adfc37734059409298373b1138d [file] [log] [blame]
import * as _DEFAULT_RULES from '../data/rules.json';
export const DEFAULT_RULES: Rule[] = _DEFAULT_RULES as Rule[];
// Returns the content of the file `data/rules.json` as an object.
export function getDefaultRules() {
return [...DEFAULT_RULES];
}
export function isValidRule(rule: Rule) {
return (
Object.values(Operator).includes(rule.operator) &&
((rule.operator === Operator.BLOCK && rule.target) ||
(rule.operator === Operator.REDIRECT &&
rule.target &&
rule.destination) ||
!!rule.destination)
);
}
export function isInjectRule(rule: Rule) {
return [
Operator.INJECT_JS_MODULE_PLUGIN,
Operator.INJECT_JS_PLUGIN,
Operator.INJECT_HTML_CODE,
Operator.INJECT_EXP,
].some(op => op === rule.operator);
}
export function getStaticRules(
tabIds: number[]
): chrome.declarativeNetRequest.Rule[] {
if (tabIds.length === 0) return [];
return [
{
action: {
requestHeaders: [
{
header: 'cache-control',
value: 'max-age=0, no-cache, no-store, must-revalidate',
operation: chrome.declarativeNetRequest.HeaderOperation.SET,
},
{
header: 'x-google-cache-control',
value: 'max-age=0, no-cache, no-store, must-revalidate',
operation: chrome.declarativeNetRequest.HeaderOperation.SET,
},
],
type: chrome.declarativeNetRequest.RuleActionType.MODIFY_HEADERS,
},
condition: {
urlFilter: '*',
tabIds,
},
// We just don't want to conflict with dynamic rule ids. They start counting from 1.
id: 314159,
},
];
}
export function toChromeRule(
rule: Rule,
tabIds: number[],
ruleId: number
): chrome.declarativeNetRequest.Rule | undefined {
if (rule.disabled) return undefined;
if (tabIds.length === 0) return undefined;
const action = convertRuleToAction(rule);
if (!action) return undefined;
return {
action,
condition: {
regexFilter: rule.target,
tabIds,
},
id: ruleId,
};
}
function convertRuleToAction(
rule: Rule
): chrome.declarativeNetRequest.RuleAction | undefined {
switch (rule.operator) {
case Operator.BLOCK:
return {
type: chrome.declarativeNetRequest.RuleActionType.BLOCK,
};
case Operator.ADD_RESPONSE_HEADER:
case Operator.REMOVE_RESPONSE_HEADER:
return {
responseHeaders: headerInfos(rule),
type: chrome.declarativeNetRequest.RuleActionType.MODIFY_HEADERS,
};
case Operator.ADD_REQUEST_HEADER:
return {
requestHeaders: headerInfos(rule),
type: chrome.declarativeNetRequest.RuleActionType.MODIFY_HEADERS,
};
case Operator.REDIRECT:
return {
type: chrome.declarativeNetRequest.RuleActionType.REDIRECT,
redirect: {regexSubstitution: rule.destination},
};
default:
return undefined;
}
}
function headerInfos(
rule: Rule
): chrome.declarativeNetRequest.ModifyHeaderInfo[] | undefined {
const operation =
rule.operator === Operator.REMOVE_RESPONSE_HEADER
? chrome.declarativeNetRequest.HeaderOperation.REMOVE
: chrome.declarativeNetRequest.HeaderOperation.SET;
const headerInfos: chrome.declarativeNetRequest.ModifyHeaderInfo[] = [];
const ruleHeaders = rule.destination.split('|');
for (const header of ruleHeaders) {
const partial = header.split('=');
headerInfos.push({
header: partial[0],
operation,
value: partial[1],
});
}
return headerInfos;
}
/**
* Supported operators.
*/
export enum Operator {
BLOCK = 'block',
REDIRECT = 'redirect',
INJECT_HTML_CODE = 'injectHtmlCode',
INJECT_JS_PLUGIN = 'injectJSPlugin',
INJECT_JS_MODULE_PLUGIN = 'injectJSModule',
REMOVE_RESPONSE_HEADER = 'rRespHeader',
ADD_RESPONSE_HEADER = 'addRespHeader',
ADD_REQUEST_HEADER = 'addReqHeader',
INJECT_EXP = 'injectExp',
}
/**
* Rule type.
*/
export interface Rule {
disabled: boolean;
target: string;
operator: Operator;
destination: string;
}
/**
* Util to get url parameters
*/
export function getUrlParameter(param: string) {
const qs = window.location.search.substring(1);
const partials = qs.split('&');
const res = [];
for (let i = 0; i < partials.length; i++) {
const name = partials[i].split('=');
if (name[0] == param) {
res.push(name[1]);
}
}
return res;
}
// Note that this does not work from a content script. It does not have access
// to the `chrome.tabs` API.
export async function getActiveTab(): Promise<chrome.tabs.Tab | undefined> {
const activeTabs = await chrome.tabs.query({
active: true,
currentWindow: true,
});
const activeTab = activeTabs[0];
if (!activeTab?.id || !activeTab?.url) return undefined;
return activeTab;
}