blob: 5d196dc7ab9f6971d75b044af33e0bc91518b86e [file] [log] [blame]
import { isInjectRule, Operator, Rule } from './utils';
function nextTick(ts: number) {
return new Promise(resolve => {
setTimeout(resolve, ts);
});
}
// Since content-script can not access window.Gerrit,
// here checks the readiness based on #mainHeader element
const onGerritReady = async () => {
let header;
try {
header = document.querySelector("#app").shadowRoot.querySelector("#app-element").shadowRoot.querySelector("#mainHeader");
} catch (e) { }
while (!header) {
await nextTick(1000);
try {
header = document.querySelector("#app").shadowRoot.querySelector("#app-element").shadowRoot.querySelector("#mainHeader");
} catch (e) { }
}
return true;
}
let numOfSnackBars = 0;
function createSnackBar(message: string) {
const errorSnack = document.createElement('div');
errorSnack.style.position = 'absolute';
errorSnack.style.top = `${numOfSnackBars * 40}px`;
errorSnack.style.right = '10px';
errorSnack.style.backgroundColor = 'black';
errorSnack.style.color = 'white';
errorSnack.style.padding = '10px';
errorSnack.style.zIndex = '100';
errorSnack.innerHTML = message;
document.body.appendChild(errorSnack);
numOfSnackBars++;
return errorSnack;
}
// Apply injection rules to Gerrit sites if enabled
chrome.runtime.sendMessage({ type: 'isEnabled' }, (isEnabled) => {
if (!isEnabled) return;
chrome.storage.sync.get(['rules'], (result) => {
if (!result['rules']) return;
const rules = result['rules'] as Rule[];
// load
rules.filter(isInjectRule).forEach(rule => {
if (rule.disabled) return;
if (rule.operator === Operator.INJECT_HTML_PLUGIN) {
onGerritReady().then(() => {
const link = document.createElement('link');
link.href = rule.destination;
link.rel = 'import';
document.head.appendChild(link);
});
} else if (rule.operator === Operator.INJECT_HTML_CODE) {
const el = document.createElement('div');
el.innerHTML = rule.destination;
document.body.appendChild(el);
} else if (rule.operator === Operator.INJECT_JS_PLUGIN) {
onGerritReady().then(() => {
const link = document.createElement('script');
link.setAttribute('src', rule.destination);
link.setAttribute('crossorigin', 'anonymous');
document.head.appendChild(link);
});
} else if (rule.operator === Operator.INJECT_JS_MODULE_PLUGIN) {
onGerritReady().then(() => {
const link = document.createElement('script');
link.setAttribute('type', 'module');
link.setAttribute('src', rule.destination);
link.setAttribute('crossorigin', 'anonymous');
document.head.appendChild(link);
});
} else if (rule.operator === Operator.INJECT_JS_CODE) {
const link = document.createElement('script');
link.innerHTML = rule.destination;
document.head.appendChild(link);
}
});
// test redirect rules
rules.filter(rule => !isInjectRule(rule)).forEach(rule => {
if (rule.operator === Operator.REDIRECT
&& !rule.disabled
// only test for js/html
&& /\.(js|html)+$/.test(rule.destination)
) {
fetch(rule.destination).then(res => {
if (res.status < 200 || res.status >= 300) throw new Error("Resource not found");
}).catch(e => {
const errorSnack = createSnackBar(
`You may have an invalid redirect rule from ${rule.target} to ${rule.destination}`
);
// in case body is unresolved
document.body.style.display = "block";
document.body.style.opacity = "1";
setTimeout(() => {
errorSnack.remove();
numOfSnackBars--;
}, 10 * 1000);
});
}
});
});
});