diff options
Diffstat (limited to 'ext/js/background/request-builder.js')
-rw-r--r-- | ext/js/background/request-builder.js | 88 |
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]; |