mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-08-02 04:17:24 +02:00
Move the NetworkManager functionality into the PDFNetworkStream class
The `NetworkManager` is very old code at this point, and it predates the introduction of the streaming functionality by many years. To simplify things, especially with upcoming re-factoring patches, let's move this functionality into private (and semi-private) methods in the `PDFNetworkStream` class to avoid having to deal with too many different scopes.
This commit is contained in:
parent
4d9301fceb
commit
eaf605d720
@ -35,19 +35,27 @@ function getArrayBuffer(val) {
|
|||||||
return typeof val !== "string" ? val : stringToBytes(val).buffer;
|
return typeof val !== "string" ? val : stringToBytes(val).buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
class NetworkManager {
|
/** @implements {IPDFStream} */
|
||||||
|
class PDFNetworkStream {
|
||||||
#pendingRequests = new WeakMap();
|
#pendingRequests = new WeakMap();
|
||||||
|
|
||||||
|
_fullRequestReader = null;
|
||||||
|
|
||||||
|
_rangeRequestReaders = [];
|
||||||
|
|
||||||
_responseOrigin = null;
|
_responseOrigin = null;
|
||||||
|
|
||||||
constructor({ url, httpHeaders, withCredentials }) {
|
constructor(source) {
|
||||||
this.url = url;
|
this._source = source;
|
||||||
this.isHttp = /^https?:/i.test(url);
|
this.url = source.url;
|
||||||
this.headers = createHeaders(this.isHttp, httpHeaders);
|
this.isHttp = /^https?:/i.test(this.url);
|
||||||
this.withCredentials = withCredentials || false;
|
this.headers = createHeaders(this.isHttp, source.httpHeaders);
|
||||||
}
|
}
|
||||||
|
|
||||||
request(args) {
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
_request(args) {
|
||||||
const xhr = new XMLHttpRequest();
|
const xhr = new XMLHttpRequest();
|
||||||
const pendingRequest = {
|
const pendingRequest = {
|
||||||
validateStatus: null,
|
validateStatus: null,
|
||||||
@ -59,7 +67,7 @@ class NetworkManager {
|
|||||||
this.#pendingRequests.set(xhr, pendingRequest);
|
this.#pendingRequests.set(xhr, pendingRequest);
|
||||||
|
|
||||||
xhr.open("GET", this.url);
|
xhr.open("GET", this.url);
|
||||||
xhr.withCredentials = this.withCredentials;
|
xhr.withCredentials = this._source.withCredentials;
|
||||||
for (const [key, val] of this.headers) {
|
for (const [key, val] of this.headers) {
|
||||||
xhr.setRequestHeader(key, val);
|
xhr.setRequestHeader(key, val);
|
||||||
}
|
}
|
||||||
@ -141,51 +149,34 @@ class NetworkManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Abort the request, if it's pending.
|
/**
|
||||||
abortRequest(xhr) {
|
* Abort the request, if it's pending.
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
_abortRequest(xhr) {
|
||||||
if (this.#pendingRequests.has(xhr)) {
|
if (this.#pendingRequests.has(xhr)) {
|
||||||
this.#pendingRequests.delete(xhr);
|
this.#pendingRequests.delete(xhr);
|
||||||
xhr.abort();
|
xhr.abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/** @implements {IPDFStream} */
|
|
||||||
class PDFNetworkStream {
|
|
||||||
constructor(source) {
|
|
||||||
this._source = source;
|
|
||||||
this._manager = new NetworkManager(source);
|
|
||||||
this._rangeChunkSize = source.rangeChunkSize;
|
|
||||||
this._fullRequestReader = null;
|
|
||||||
this._rangeRequestReaders = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
_onRangeRequestReaderClosed(reader) {
|
|
||||||
const i = this._rangeRequestReaders.indexOf(reader);
|
|
||||||
if (i >= 0) {
|
|
||||||
this._rangeRequestReaders.splice(i, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getFullReader() {
|
getFullReader() {
|
||||||
assert(
|
assert(
|
||||||
!this._fullRequestReader,
|
!this._fullRequestReader,
|
||||||
"PDFNetworkStream.getFullReader can only be called once."
|
"PDFNetworkStream.getFullReader can only be called once."
|
||||||
);
|
);
|
||||||
this._fullRequestReader = new PDFNetworkStreamFullRequestReader(
|
this._fullRequestReader = new PDFNetworkStreamFullRequestReader(this);
|
||||||
this._manager,
|
|
||||||
this._source
|
|
||||||
);
|
|
||||||
return this._fullRequestReader;
|
return this._fullRequestReader;
|
||||||
}
|
}
|
||||||
|
|
||||||
getRangeReader(begin, end) {
|
getRangeReader(begin, end) {
|
||||||
const reader = new PDFNetworkStreamRangeRequestReader(
|
const reader = new PDFNetworkStreamRangeRequestReader(this, begin, end);
|
||||||
this._manager,
|
reader.onClosed = () => {
|
||||||
begin,
|
const i = this._rangeRequestReaders.indexOf(reader);
|
||||||
end
|
if (i >= 0) {
|
||||||
);
|
this._rangeRequestReaders.splice(i, 1);
|
||||||
reader.onClosed = this._onRangeRequestReaderClosed.bind(this);
|
}
|
||||||
|
};
|
||||||
this._rangeRequestReaders.push(reader);
|
this._rangeRequestReaders.push(reader);
|
||||||
return reader;
|
return reader;
|
||||||
}
|
}
|
||||||
@ -201,20 +192,20 @@ class PDFNetworkStream {
|
|||||||
|
|
||||||
/** @implements {IPDFStreamReader} */
|
/** @implements {IPDFStreamReader} */
|
||||||
class PDFNetworkStreamFullRequestReader {
|
class PDFNetworkStreamFullRequestReader {
|
||||||
constructor(manager, source) {
|
constructor(stream) {
|
||||||
this._manager = manager;
|
this._stream = stream;
|
||||||
|
const { disableRange, length, rangeChunkSize } = stream._source;
|
||||||
|
|
||||||
this._url = source.url;
|
this._fullRequestXhr = stream._request({
|
||||||
this._fullRequestXhr = manager.request({
|
|
||||||
onHeadersReceived: this._onHeadersReceived.bind(this),
|
onHeadersReceived: this._onHeadersReceived.bind(this),
|
||||||
onDone: this._onDone.bind(this),
|
onDone: this._onDone.bind(this),
|
||||||
onError: this._onError.bind(this),
|
onError: this._onError.bind(this),
|
||||||
onProgress: this._onProgress.bind(this),
|
onProgress: this._onProgress.bind(this),
|
||||||
});
|
});
|
||||||
this._headersCapability = Promise.withResolvers();
|
this._headersCapability = Promise.withResolvers();
|
||||||
this._disableRange = source.disableRange || false;
|
this._disableRange = disableRange || false;
|
||||||
this._contentLength = source.length; // Optional
|
this._contentLength = length; // Optional
|
||||||
this._rangeChunkSize = source.rangeChunkSize;
|
this._rangeChunkSize = rangeChunkSize;
|
||||||
if (!this._rangeChunkSize && !this._disableRange) {
|
if (!this._rangeChunkSize && !this._disableRange) {
|
||||||
this._disableRange = true;
|
this._disableRange = true;
|
||||||
}
|
}
|
||||||
@ -232,11 +223,10 @@ class PDFNetworkStreamFullRequestReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_onHeadersReceived() {
|
_onHeadersReceived() {
|
||||||
|
const stream = this._stream;
|
||||||
const fullRequestXhr = this._fullRequestXhr;
|
const fullRequestXhr = this._fullRequestXhr;
|
||||||
|
|
||||||
this._manager._responseOrigin = getResponseOrigin(
|
stream._responseOrigin = getResponseOrigin(fullRequestXhr.responseURL);
|
||||||
fullRequestXhr.responseURL
|
|
||||||
);
|
|
||||||
|
|
||||||
const rawResponseHeaders = fullRequestXhr.getAllResponseHeaders();
|
const rawResponseHeaders = fullRequestXhr.getAllResponseHeaders();
|
||||||
const responseHeaders = new Headers(
|
const responseHeaders = new Headers(
|
||||||
@ -255,7 +245,7 @@ class PDFNetworkStreamFullRequestReader {
|
|||||||
const { allowRangeRequests, suggestedLength } =
|
const { allowRangeRequests, suggestedLength } =
|
||||||
validateRangeRequestCapabilities({
|
validateRangeRequestCapabilities({
|
||||||
responseHeaders,
|
responseHeaders,
|
||||||
isHttp: this._manager.isHttp,
|
isHttp: stream.isHttp,
|
||||||
rangeChunkSize: this._rangeChunkSize,
|
rangeChunkSize: this._rangeChunkSize,
|
||||||
disableRange: this._disableRange,
|
disableRange: this._disableRange,
|
||||||
});
|
});
|
||||||
@ -273,7 +263,7 @@ class PDFNetworkStreamFullRequestReader {
|
|||||||
// requests, there will be an issue for sites where you can only
|
// requests, there will be an issue for sites where you can only
|
||||||
// request the pdf once. However, if this is the case, then the
|
// request the pdf once. However, if this is the case, then the
|
||||||
// server should not be returning that it can support range requests.
|
// server should not be returning that it can support range requests.
|
||||||
this._manager.abortRequest(fullRequestXhr);
|
stream._abortRequest(fullRequestXhr);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._headersCapability.resolve();
|
this._headersCapability.resolve();
|
||||||
@ -297,7 +287,7 @@ class PDFNetworkStreamFullRequestReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_onError(status) {
|
_onError(status) {
|
||||||
this._storedError = createResponseError(status, this._url);
|
this._storedError = createResponseError(status, this._stream.url);
|
||||||
this._headersCapability.reject(this._storedError);
|
this._headersCapability.reject(this._storedError);
|
||||||
for (const requestCapability of this._requests) {
|
for (const requestCapability of this._requests) {
|
||||||
requestCapability.reject(this._storedError);
|
requestCapability.reject(this._storedError);
|
||||||
@ -359,18 +349,19 @@ class PDFNetworkStreamFullRequestReader {
|
|||||||
}
|
}
|
||||||
this._requests.length = 0;
|
this._requests.length = 0;
|
||||||
|
|
||||||
this._manager.abortRequest(this._fullRequestXhr);
|
this._stream._abortRequest(this._fullRequestXhr);
|
||||||
this._fullRequestXhr = null;
|
this._fullRequestXhr = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @implements {IPDFStreamRangeReader} */
|
/** @implements {IPDFStreamRangeReader} */
|
||||||
class PDFNetworkStreamRangeRequestReader {
|
class PDFNetworkStreamRangeRequestReader {
|
||||||
constructor(manager, begin, end) {
|
onClosed = null;
|
||||||
this._manager = manager;
|
|
||||||
|
|
||||||
this._url = manager.url;
|
constructor(stream, begin, end) {
|
||||||
this._requestXhr = manager.request({
|
this._stream = stream;
|
||||||
|
|
||||||
|
this._requestXhr = stream._request({
|
||||||
begin,
|
begin,
|
||||||
end,
|
end,
|
||||||
onHeadersReceived: this._onHeadersReceived.bind(this),
|
onHeadersReceived: this._onHeadersReceived.bind(this),
|
||||||
@ -384,24 +375,19 @@ class PDFNetworkStreamRangeRequestReader {
|
|||||||
this._storedError = undefined;
|
this._storedError = undefined;
|
||||||
|
|
||||||
this.onProgress = null;
|
this.onProgress = null;
|
||||||
this.onClosed = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_onHeadersReceived() {
|
_onHeadersReceived() {
|
||||||
const responseOrigin = getResponseOrigin(this._requestXhr?.responseURL);
|
const responseOrigin = getResponseOrigin(this._requestXhr?.responseURL);
|
||||||
|
|
||||||
if (responseOrigin !== this._manager._responseOrigin) {
|
if (responseOrigin !== this._stream._responseOrigin) {
|
||||||
this._storedError = new Error(
|
this._storedError = new Error(
|
||||||
`Expected range response-origin "${responseOrigin}" to match "${this._manager._responseOrigin}".`
|
`Expected range response-origin "${responseOrigin}" to match "${this._stream._responseOrigin}".`
|
||||||
);
|
);
|
||||||
this._onError(0);
|
this._onError(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_close() {
|
|
||||||
this.onClosed?.(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
_onDone(chunk) {
|
_onDone(chunk) {
|
||||||
if (this._requests.length > 0) {
|
if (this._requests.length > 0) {
|
||||||
const requestCapability = this._requests.shift();
|
const requestCapability = this._requests.shift();
|
||||||
@ -414,11 +400,11 @@ class PDFNetworkStreamRangeRequestReader {
|
|||||||
requestCapability.resolve({ value: undefined, done: true });
|
requestCapability.resolve({ value: undefined, done: true });
|
||||||
}
|
}
|
||||||
this._requests.length = 0;
|
this._requests.length = 0;
|
||||||
this._close();
|
this.onClosed?.(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onError(status) {
|
_onError(status) {
|
||||||
this._storedError ??= createResponseError(status, this._url);
|
this._storedError ??= createResponseError(status, this._stream.url);
|
||||||
for (const requestCapability of this._requests) {
|
for (const requestCapability of this._requests) {
|
||||||
requestCapability.reject(this._storedError);
|
requestCapability.reject(this._storedError);
|
||||||
}
|
}
|
||||||
@ -460,8 +446,8 @@ class PDFNetworkStreamRangeRequestReader {
|
|||||||
}
|
}
|
||||||
this._requests.length = 0;
|
this._requests.length = 0;
|
||||||
|
|
||||||
this._manager.abortRequest(this._requestXhr);
|
this._stream._abortRequest(this._requestXhr);
|
||||||
this._close();
|
this.onClosed?.(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user