summaryrefslogtreecommitdiff
path: root/ext/js/background/request-builder.js
diff options
context:
space:
mode:
Diffstat (limited to 'ext/js/background/request-builder.js')
-rw-r--r--ext/js/background/request-builder.js88
1 files changed, 68 insertions, 20 deletions
diff --git a/ext/js/background/request-builder.js b/ext/js/background/request-builder.js
index f4f685be..23f10ed3 100644
--- a/ext/js/background/request-builder.js
+++ b/ext/js/background/request-builder.js
@@ -22,16 +22,12 @@
*/
export class RequestBuilder {
/**
- * A progress callback for a fetch read.
- * @callback ProgressCallback
- * @param {boolean} complete Whether or not the data has been completely read.
- */
-
- /**
* Creates a new instance.
*/
constructor() {
+ /** @type {TextEncoder} */
this._textEncoder = new TextEncoder();
+ /** @type {Set<number>} */
this._ruleIds = new Set();
}
@@ -60,29 +56,32 @@ export class RequestBuilder {
this._ruleIds.add(id);
try {
+ /** @type {chrome.declarativeNetRequest.Rule[]} */
const addRules = [{
id,
priority: 1,
condition: {
urlFilter: `|${this._escapeDnrUrl(url)}|`,
- resourceTypes: ['xmlhttprequest']
+ resourceTypes: [
+ /** @type {chrome.declarativeNetRequest.ResourceType} */ ('xmlhttprequest')
+ ]
},
action: {
- type: 'modifyHeaders',
+ type: /** @type {chrome.declarativeNetRequest.RuleActionType} */ ('modifyHeaders'),
requestHeaders: [
{
- operation: 'remove',
+ operation: /** @type {chrome.declarativeNetRequest.HeaderOperation} */ ('remove'),
header: 'Cookie'
},
{
- operation: 'set',
+ operation: /** @type {chrome.declarativeNetRequest.HeaderOperation} */ ('set'),
header: 'Origin',
value: originUrl
}
],
responseHeaders: [
{
- operation: 'remove',
+ operation: /** @type {chrome.declarativeNetRequest.HeaderOperation} */ ('remove'),
header: 'Set-Cookie'
}
]
@@ -103,14 +102,18 @@ export class RequestBuilder {
/**
* Reads the array buffer body of a fetch response, with an optional `onProgress` callback.
* @param {Response} response The response of a `fetch` call.
- * @param {ProgressCallback} onProgress The progress callback
+ * @param {?(done: boolean) => void} onProgress The progress callback.
* @returns {Promise<Uint8Array>} The resulting binary data.
*/
static async readFetchResponseArrayBuffer(response, onProgress) {
+ /** @type {ReadableStreamDefaultReader<Uint8Array>|undefined} */
let reader;
try {
- if (typeof onProgress === 'function') {
- reader = response.body.getReader();
+ if (onProgress !== null) {
+ const {body} = response;
+ if (body !== null) {
+ reader = body.getReader();
+ }
}
} catch (e) {
// Not supported
@@ -118,15 +121,15 @@ export class RequestBuilder {
if (typeof reader === 'undefined') {
const result = await response.arrayBuffer();
- if (typeof onProgress === 'function') {
+ if (onProgress !== null) {
onProgress(true);
}
- return result;
+ return new Uint8Array(result);
}
const contentLengthString = response.headers.get('Content-Length');
const contentLength = contentLengthString !== null ? Number.parseInt(contentLengthString, 10) : null;
- let target = Number.isFinite(contentLength) ? new Uint8Array(contentLength) : null;
+ let target = contentLength !== null && Number.isFinite(contentLength) ? new Uint8Array(contentLength) : null;
let targetPosition = 0;
let totalLength = 0;
const targets = [];
@@ -134,7 +137,9 @@ export class RequestBuilder {
while (true) {
const {done, value} = await reader.read();
if (done) { break; }
- onProgress(false);
+ if (onProgress !== null) {
+ onProgress(false);
+ }
if (target === null) {
targets.push({array: value, length: value.length});
} else if (targetPosition + value.length > target.length) {
@@ -153,13 +158,16 @@ export class RequestBuilder {
target = target.slice(0, totalLength);
}
- onProgress(true);
+ if (onProgress !== null) {
+ onProgress(true);
+ }
- return target;
+ return /** @type {Uint8Array} */ (target);
}
// Private
+ /** */
async _clearSessionRules() {
const rules = await this._getSessionRules();
@@ -173,6 +181,9 @@ export class RequestBuilder {
await this._updateSessionRules({removeRuleIds});
}
+ /**
+ * @returns {Promise<chrome.declarativeNetRequest.Rule[]>}
+ */
_getSessionRules() {
return new Promise((resolve, reject) => {
chrome.declarativeNetRequest.getSessionRules((result) => {
@@ -186,6 +197,10 @@ export class RequestBuilder {
});
}
+ /**
+ * @param {chrome.declarativeNetRequest.UpdateRuleOptions} options
+ * @returns {Promise<void>}
+ */
_updateSessionRules(options) {
return new Promise((resolve, reject) => {
chrome.declarativeNetRequest.updateSessionRules(options, () => {
@@ -199,6 +214,10 @@ export class RequestBuilder {
});
}
+ /**
+ * @param {chrome.declarativeNetRequest.UpdateRuleOptions} options
+ * @returns {Promise<boolean>}
+ */
async _tryUpdateSessionRules(options) {
try {
await this._updateSessionRules(options);
@@ -208,6 +227,7 @@ export class RequestBuilder {
}
}
+ /** */
async _clearDynamicRules() {
const rules = await this._getDynamicRules();
@@ -221,6 +241,9 @@ export class RequestBuilder {
await this._updateDynamicRules({removeRuleIds});
}
+ /**
+ * @returns {Promise<chrome.declarativeNetRequest.Rule[]>}
+ */
_getDynamicRules() {
return new Promise((resolve, reject) => {
chrome.declarativeNetRequest.getDynamicRules((result) => {
@@ -234,6 +257,10 @@ export class RequestBuilder {
});
}
+ /**
+ * @param {chrome.declarativeNetRequest.UpdateRuleOptions} options
+ * @returns {Promise<void>}
+ */
_updateDynamicRules(options) {
return new Promise((resolve, reject) => {
chrome.declarativeNetRequest.updateDynamicRules(options, () => {
@@ -247,6 +274,10 @@ export class RequestBuilder {
});
}
+ /**
+ * @returns {number}
+ * @throws {Error}
+ */
_getNewRuleId() {
let id = 1;
while (this._ruleIds.has(id)) {
@@ -257,15 +288,27 @@ export class RequestBuilder {
return id;
}
+ /**
+ * @param {string} url
+ * @returns {string}
+ */
_getOriginURL(url) {
const url2 = new URL(url);
return `${url2.protocol}//${url2.host}`;
}
+ /**
+ * @param {string} url
+ * @returns {string}
+ */
_escapeDnrUrl(url) {
return url.replace(/[|*^]/g, (char) => this._urlEncodeUtf8(char));
}
+ /**
+ * @param {string} text
+ * @returns {string}
+ */
_urlEncodeUtf8(text) {
const array = this._textEncoder.encode(text);
let result = '';
@@ -275,6 +318,11 @@ export class RequestBuilder {
return result;
}
+ /**
+ * @param {{array: Uint8Array, length: number}[]} items
+ * @param {number} totalLength
+ * @returns {Uint8Array}
+ */
static _joinUint8Arrays(items, totalLength) {
if (items.length === 1) {
const {array, length} = items[0];