Add support for using declarativeNetRequest (#1127)
This commit is contained in:
parent
05d4049f16
commit
2fa9b91515
@ -154,8 +154,10 @@
|
||||
{"action": "move", "path": ["content_security_policy_old"], "newPath": ["content_security_policy", "extension_pages"]},
|
||||
{"action": "move", "path": ["sandbox", "content_security_policy"], "newPath": ["content_security_policy", "sandbox"]},
|
||||
{"action": "remove", "path": ["permissions"], "item": "<all_urls>"},
|
||||
{"action": "remove", "path": ["permissions"], "item": "webRequest"},
|
||||
{"action": "remove", "path": ["permissions"], "item": "webRequestBlocking"},
|
||||
{"action": "add", "path": ["permissions"], "items": ["declarativeNetRequest", "scripting"]},
|
||||
{"action": "set", "path": ["host_permissions"], "value": ["<all_urls>"], "after": "optional_permissions"},
|
||||
{"action": "add", "path": ["permissions"], "items": ["scripting"]},
|
||||
{"action": "move", "path": ["web_accessible_resources"], "newPath": ["web_accessible_resources_old"]},
|
||||
{"action": "set", "path": ["web_accessible_resources"], "value": [{"resources": [], "matches": ["<all_urls>"]}], "after": "web_accessible_resources_old"},
|
||||
{"action": "move", "path": ["web_accessible_resources_old"], "newPath": ["web_accessible_resources", 0, "resources"]}
|
||||
|
@ -187,6 +187,7 @@ class Backend {
|
||||
|
||||
yomichan.on('log', this._onLog.bind(this));
|
||||
|
||||
await this._requestBuilder.prepare();
|
||||
await this._environment.prepare();
|
||||
this._clipboardReader.browser = this._environment.getInfo().browser;
|
||||
|
||||
|
@ -19,9 +19,22 @@ class RequestBuilder {
|
||||
constructor() {
|
||||
this._extraHeadersSupported = null;
|
||||
this._onBeforeSendHeadersExtraInfoSpec = ['blocking', 'requestHeaders', 'extraHeaders'];
|
||||
this._textEncoder = new TextEncoder();
|
||||
this._ruleIds = new Set();
|
||||
}
|
||||
|
||||
async prepare() {
|
||||
try {
|
||||
await this._clearDynamicRules();
|
||||
} catch (e) {
|
||||
// NOP
|
||||
}
|
||||
}
|
||||
|
||||
async fetchAnonymous(url, init) {
|
||||
if (isObject(chrome.declarativeNetRequest)) {
|
||||
return await this._fetchAnonymousDeclarative(url, init);
|
||||
}
|
||||
const originURL = this._getOriginURL(url);
|
||||
const modifications = [
|
||||
['cookie', null],
|
||||
@ -130,4 +143,124 @@ class RequestBuilder {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async _clearDynamicRules() {
|
||||
if (!isObject(chrome.declarativeNetRequest)) { return; }
|
||||
|
||||
const rules = this._getDynamicRules();
|
||||
|
||||
if (rules.length === 0) { return; }
|
||||
|
||||
const removeRuleIds = [];
|
||||
for (const {id} of rules) {
|
||||
removeRuleIds.push(id);
|
||||
}
|
||||
|
||||
await this._updateDynamicRules({removeRuleIds});
|
||||
}
|
||||
|
||||
async _fetchAnonymousDeclarative(url, init) {
|
||||
const id = this._getNewRuleId();
|
||||
const originUrl = this._getOriginURL(url);
|
||||
url = encodeURI(decodeURI(url));
|
||||
|
||||
this._ruleIds.add(id);
|
||||
try {
|
||||
const addRules = [{
|
||||
id,
|
||||
priority: 1,
|
||||
condition: {
|
||||
urlFilter: `|${this._escapeDnrUrl(url)}|`,
|
||||
resourceTypes: ['xmlhttprequest']
|
||||
},
|
||||
action: {
|
||||
type: 'modifyHeaders',
|
||||
requestHeaders: [
|
||||
{
|
||||
operation: 'remove',
|
||||
header: 'Cookie'
|
||||
},
|
||||
{
|
||||
operation: 'set',
|
||||
header: 'Origin',
|
||||
value: originUrl
|
||||
}
|
||||
],
|
||||
responseHeaders: [
|
||||
{
|
||||
operation: 'remove',
|
||||
header: 'Set-Cookie'
|
||||
}
|
||||
]
|
||||
}
|
||||
}];
|
||||
|
||||
await this._updateDynamicRules({addRules});
|
||||
try {
|
||||
return await fetch(url, init);
|
||||
} finally {
|
||||
await this._tryUpdateDynamicRules({removeRuleIds: [id]});
|
||||
}
|
||||
} finally {
|
||||
this._ruleIds.delete(id);
|
||||
}
|
||||
}
|
||||
|
||||
_getDynamicRules() {
|
||||
return new Promise((resolve, reject) => {
|
||||
chrome.declarativeNetRequest.getDynamicRules((result) => {
|
||||
const e = chrome.runtime.lastError;
|
||||
if (e) {
|
||||
reject(new Error(e.message));
|
||||
} else {
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
_updateDynamicRules(options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
chrome.declarativeNetRequest.updateDynamicRules(options, () => {
|
||||
const e = chrome.runtime.lastError;
|
||||
if (e) {
|
||||
reject(new Error(e.message));
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async _tryUpdateDynamicRules(options) {
|
||||
try {
|
||||
await this._updateDynamicRules(options);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_getNewRuleId() {
|
||||
let id = 1;
|
||||
while (this._ruleIds.has(id)) {
|
||||
const pre = id;
|
||||
++id;
|
||||
if (id === pre) { throw new Error('Could not generate an id'); }
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
_escapeDnrUrl(url) {
|
||||
return url.replace(/[|*^]/g, (char) => this._urlEncodeUtf8(char));
|
||||
}
|
||||
|
||||
_urlEncodeUtf8(text) {
|
||||
const array = this._textEncoder.encode(text);
|
||||
let result = '';
|
||||
for (const byte of array) {
|
||||
result += `%${byte.toString(16).toUpperCase().padStart(2, '0')}`;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user