Generic build of PDF.js library.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

707 lines
19 KiB

/**
* @licstart The following is the entire license notice for the
* Javascript code in this page
*
* Copyright 2019 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @licend The above is the entire license notice for the
* Javascript code in this page
*/
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.PDFNetworkStream = void 0;
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _util = require("../shared/util");
var _network_utils = require("./network_utils");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
;
var OK_RESPONSE = 200;
var PARTIAL_CONTENT_RESPONSE = 206;
function getArrayBuffer(xhr) {
var data = xhr.response;
if (typeof data !== 'string') {
return data;
}
var array = (0, _util.stringToBytes)(data);
return array.buffer;
}
var NetworkManager =
/*#__PURE__*/
function () {
function NetworkManager(url, args) {
_classCallCheck(this, NetworkManager);
this.url = url;
args = args || {};
this.isHttp = /^https?:/i.test(url);
this.httpHeaders = this.isHttp && args.httpHeaders || {};
this.withCredentials = args.withCredentials || false;
this.getXhr = args.getXhr || function NetworkManager_getXhr() {
return new XMLHttpRequest();
};
this.currXhrId = 0;
this.pendingRequests = Object.create(null);
}
_createClass(NetworkManager, [{
key: "requestRange",
value: function requestRange(begin, end, listeners) {
var args = {
begin: begin,
end: end
};
for (var prop in listeners) {
args[prop] = listeners[prop];
}
return this.request(args);
}
}, {
key: "requestFull",
value: function requestFull(listeners) {
return this.request(listeners);
}
}, {
key: "request",
value: function request(args) {
var xhr = this.getXhr();
var xhrId = this.currXhrId++;
var pendingRequest = this.pendingRequests[xhrId] = {
xhr: xhr
};
xhr.open('GET', this.url);
xhr.withCredentials = this.withCredentials;
for (var property in this.httpHeaders) {
var value = this.httpHeaders[property];
if (typeof value === 'undefined') {
continue;
}
xhr.setRequestHeader(property, value);
}
if (this.isHttp && 'begin' in args && 'end' in args) {
xhr.setRequestHeader('Range', "bytes=".concat(args.begin, "-").concat(args.end - 1));
pendingRequest.expectedStatus = PARTIAL_CONTENT_RESPONSE;
} else {
pendingRequest.expectedStatus = OK_RESPONSE;
}
xhr.responseType = 'arraybuffer';
if (args.onError) {
xhr.onerror = function (evt) {
args.onError(xhr.status);
};
}
xhr.onreadystatechange = this.onStateChange.bind(this, xhrId);
xhr.onprogress = this.onProgress.bind(this, xhrId);
pendingRequest.onHeadersReceived = args.onHeadersReceived;
pendingRequest.onDone = args.onDone;
pendingRequest.onError = args.onError;
pendingRequest.onProgress = args.onProgress;
xhr.send(null);
return xhrId;
}
}, {
key: "onProgress",
value: function onProgress(xhrId, evt) {
var pendingRequest = this.pendingRequests[xhrId];
if (!pendingRequest) {
return;
}
if (pendingRequest.onProgress) {
pendingRequest.onProgress(evt);
}
}
}, {
key: "onStateChange",
value: function onStateChange(xhrId, evt) {
var pendingRequest = this.pendingRequests[xhrId];
if (!pendingRequest) {
return;
}
var xhr = pendingRequest.xhr;
if (xhr.readyState >= 2 && pendingRequest.onHeadersReceived) {
pendingRequest.onHeadersReceived();
delete pendingRequest.onHeadersReceived;
}
if (xhr.readyState !== 4) {
return;
}
if (!(xhrId in this.pendingRequests)) {
return;
}
delete this.pendingRequests[xhrId];
if (xhr.status === 0 && this.isHttp) {
if (pendingRequest.onError) {
pendingRequest.onError(xhr.status);
}
return;
}
var xhrStatus = xhr.status || OK_RESPONSE;
var ok_response_on_range_request = xhrStatus === OK_RESPONSE && pendingRequest.expectedStatus === PARTIAL_CONTENT_RESPONSE;
if (!ok_response_on_range_request && xhrStatus !== pendingRequest.expectedStatus) {
if (pendingRequest.onError) {
pendingRequest.onError(xhr.status);
}
return;
}
var chunk = getArrayBuffer(xhr);
if (xhrStatus === PARTIAL_CONTENT_RESPONSE) {
var rangeHeader = xhr.getResponseHeader('Content-Range');
var matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader);
pendingRequest.onDone({
begin: parseInt(matches[1], 10),
chunk: chunk
});
} else if (chunk) {
pendingRequest.onDone({
begin: 0,
chunk: chunk
});
} else if (pendingRequest.onError) {
pendingRequest.onError(xhr.status);
}
}
}, {
key: "hasPendingRequests",
value: function hasPendingRequests() {
for (var xhrId in this.pendingRequests) {
return true;
}
return false;
}
}, {
key: "getRequestXhr",
value: function getRequestXhr(xhrId) {
return this.pendingRequests[xhrId].xhr;
}
}, {
key: "isPendingRequest",
value: function isPendingRequest(xhrId) {
return xhrId in this.pendingRequests;
}
}, {
key: "abortAllRequests",
value: function abortAllRequests() {
for (var xhrId in this.pendingRequests) {
this.abortRequest(xhrId | 0);
}
}
}, {
key: "abortRequest",
value: function abortRequest(xhrId) {
var xhr = this.pendingRequests[xhrId].xhr;
delete this.pendingRequests[xhrId];
xhr.abort();
}
}]);
return NetworkManager;
}();
var PDFNetworkStream =
/*#__PURE__*/
function () {
function PDFNetworkStream(source) {
_classCallCheck(this, PDFNetworkStream);
this._source = source;
this._manager = new NetworkManager(source.url, {
httpHeaders: source.httpHeaders,
withCredentials: source.withCredentials
});
this._rangeChunkSize = source.rangeChunkSize;
this._fullRequestReader = null;
this._rangeRequestReaders = [];
}
_createClass(PDFNetworkStream, [{
key: "_onRangeRequestReaderClosed",
value: function _onRangeRequestReaderClosed(reader) {
var i = this._rangeRequestReaders.indexOf(reader);
if (i >= 0) {
this._rangeRequestReaders.splice(i, 1);
}
}
}, {
key: "getFullReader",
value: function getFullReader() {
(0, _util.assert)(!this._fullRequestReader);
this._fullRequestReader = new PDFNetworkStreamFullRequestReader(this._manager, this._source);
return this._fullRequestReader;
}
}, {
key: "getRangeReader",
value: function getRangeReader(begin, end) {
var reader = new PDFNetworkStreamRangeRequestReader(this._manager, begin, end);
reader.onClosed = this._onRangeRequestReaderClosed.bind(this);
this._rangeRequestReaders.push(reader);
return reader;
}
}, {
key: "cancelAllRequests",
value: function cancelAllRequests(reason) {
if (this._fullRequestReader) {
this._fullRequestReader.cancel(reason);
}
var readers = this._rangeRequestReaders.slice(0);
readers.forEach(function (reader) {
reader.cancel(reason);
});
}
}]);
return PDFNetworkStream;
}();
exports.PDFNetworkStream = PDFNetworkStream;
var PDFNetworkStreamFullRequestReader =
/*#__PURE__*/
function () {
function PDFNetworkStreamFullRequestReader(manager, source) {
_classCallCheck(this, PDFNetworkStreamFullRequestReader);
this._manager = manager;
var args = {
onHeadersReceived: this._onHeadersReceived.bind(this),
onDone: this._onDone.bind(this),
onError: this._onError.bind(this),
onProgress: this._onProgress.bind(this)
};
this._url = source.url;
this._fullRequestId = manager.requestFull(args);
this._headersReceivedCapability = (0, _util.createPromiseCapability)();
this._disableRange = source.disableRange || false;
this._contentLength = source.length;
this._rangeChunkSize = source.rangeChunkSize;
if (!this._rangeChunkSize && !this._disableRange) {
this._disableRange = true;
}
this._isStreamingSupported = false;
this._isRangeSupported = false;
this._cachedChunks = [];
this._requests = [];
this._done = false;
this._storedError = undefined;
this._filename = null;
this.onProgress = null;
}
_createClass(PDFNetworkStreamFullRequestReader, [{
key: "_onHeadersReceived",
value: function _onHeadersReceived() {
var fullRequestXhrId = this._fullRequestId;
var fullRequestXhr = this._manager.getRequestXhr(fullRequestXhrId);
var getResponseHeader = function getResponseHeader(name) {
return fullRequestXhr.getResponseHeader(name);
};
var _validateRangeRequest = (0, _network_utils.validateRangeRequestCapabilities)({
getResponseHeader: getResponseHeader,
isHttp: this._manager.isHttp,
rangeChunkSize: this._rangeChunkSize,
disableRange: this._disableRange
}),
allowRangeRequests = _validateRangeRequest.allowRangeRequests,
suggestedLength = _validateRangeRequest.suggestedLength;
if (allowRangeRequests) {
this._isRangeSupported = true;
}
this._contentLength = suggestedLength || this._contentLength;
this._filename = (0, _network_utils.extractFilenameFromHeader)(getResponseHeader);
if (this._isRangeSupported) {
this._manager.abortRequest(fullRequestXhrId);
}
this._headersReceivedCapability.resolve();
}
}, {
key: "_onDone",
value: function _onDone(args) {
if (args) {
if (this._requests.length > 0) {
var requestCapability = this._requests.shift();
requestCapability.resolve({
value: args.chunk,
done: false
});
} else {
this._cachedChunks.push(args.chunk);
}
}
this._done = true;
if (this._cachedChunks.length > 0) {
return;
}
this._requests.forEach(function (requestCapability) {
requestCapability.resolve({
value: undefined,
done: true
});
});
this._requests = [];
}
}, {
key: "_onError",
value: function _onError(status) {
var url = this._url;
var exception = (0, _network_utils.createResponseStatusError)(status, url);
this._storedError = exception;
this._headersReceivedCapability.reject(exception);
this._requests.forEach(function (requestCapability) {
requestCapability.reject(exception);
});
this._requests = [];
this._cachedChunks = [];
}
}, {
key: "_onProgress",
value: function _onProgress(data) {
if (this.onProgress) {
this.onProgress({
loaded: data.loaded,
total: data.lengthComputable ? data.total : this._contentLength
});
}
}
}, {
key: "read",
value: function () {
var _read = _asyncToGenerator(
/*#__PURE__*/
_regenerator["default"].mark(function _callee() {
var chunk, requestCapability;
return _regenerator["default"].wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
if (!this._storedError) {
_context.next = 2;
break;
}
throw this._storedError;
case 2:
if (!(this._cachedChunks.length > 0)) {
_context.next = 5;
break;
}
chunk = this._cachedChunks.shift();
return _context.abrupt("return", {
value: chunk,
done: false
});
case 5:
if (!this._done) {
_context.next = 7;
break;
}
return _context.abrupt("return", {
value: undefined,
done: true
});
case 7:
requestCapability = (0, _util.createPromiseCapability)();
this._requests.push(requestCapability);
return _context.abrupt("return", requestCapability.promise);
case 10:
case "end":
return _context.stop();
}
}
}, _callee, this);
}));
function read() {
return _read.apply(this, arguments);
}
return read;
}()
}, {
key: "cancel",
value: function cancel(reason) {
this._done = true;
this._headersReceivedCapability.reject(reason);
this._requests.forEach(function (requestCapability) {
requestCapability.resolve({
value: undefined,
done: true
});
});
this._requests = [];
if (this._manager.isPendingRequest(this._fullRequestId)) {
this._manager.abortRequest(this._fullRequestId);
}
this._fullRequestReader = null;
}
}, {
key: "filename",
get: function get() {
return this._filename;
}
}, {
key: "isRangeSupported",
get: function get() {
return this._isRangeSupported;
}
}, {
key: "isStreamingSupported",
get: function get() {
return this._isStreamingSupported;
}
}, {
key: "contentLength",
get: function get() {
return this._contentLength;
}
}, {
key: "headersReady",
get: function get() {
return this._headersReceivedCapability.promise;
}
}]);
return PDFNetworkStreamFullRequestReader;
}();
var PDFNetworkStreamRangeRequestReader =
/*#__PURE__*/
function () {
function PDFNetworkStreamRangeRequestReader(manager, begin, end) {
_classCallCheck(this, PDFNetworkStreamRangeRequestReader);
this._manager = manager;
var args = {
onDone: this._onDone.bind(this),
onProgress: this._onProgress.bind(this)
};
this._requestId = manager.requestRange(begin, end, args);
this._requests = [];
this._queuedChunk = null;
this._done = false;
this.onProgress = null;
this.onClosed = null;
}
_createClass(PDFNetworkStreamRangeRequestReader, [{
key: "_close",
value: function _close() {
if (this.onClosed) {
this.onClosed(this);
}
}
}, {
key: "_onDone",
value: function _onDone(data) {
var chunk = data.chunk;
if (this._requests.length > 0) {
var requestCapability = this._requests.shift();
requestCapability.resolve({
value: chunk,
done: false
});
} else {
this._queuedChunk = chunk;
}
this._done = true;
this._requests.forEach(function (requestCapability) {
requestCapability.resolve({
value: undefined,
done: true
});
});
this._requests = [];
this._close();
}
}, {
key: "_onProgress",
value: function _onProgress(evt) {
if (!this.isStreamingSupported && this.onProgress) {
this.onProgress({
loaded: evt.loaded
});
}
}
}, {
key: "read",
value: function () {
var _read2 = _asyncToGenerator(
/*#__PURE__*/
_regenerator["default"].mark(function _callee2() {
var chunk, requestCapability;
return _regenerator["default"].wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
if (!(this._queuedChunk !== null)) {
_context2.next = 4;
break;
}
chunk = this._queuedChunk;
this._queuedChunk = null;
return _context2.abrupt("return", {
value: chunk,
done: false
});
case 4:
if (!this._done) {
_context2.next = 6;
break;
}
return _context2.abrupt("return", {
value: undefined,
done: true
});
case 6:
requestCapability = (0, _util.createPromiseCapability)();
this._requests.push(requestCapability);
return _context2.abrupt("return", requestCapability.promise);
case 9:
case "end":
return _context2.stop();
}
}
}, _callee2, this);
}));
function read() {
return _read2.apply(this, arguments);
}
return read;
}()
}, {
key: "cancel",
value: function cancel(reason) {
this._done = true;
this._requests.forEach(function (requestCapability) {
requestCapability.resolve({
value: undefined,
done: true
});
});
this._requests = [];
if (this._manager.isPendingRequest(this._requestId)) {
this._manager.abortRequest(this._requestId);
}
this._close();
}
}, {
key: "isStreamingSupported",
get: function get() {
return false;
}
}]);
return PDFNetworkStreamRangeRequestReader;
}();