worker.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. /**
  2. * @licstart The following is the entire license notice for the
  3. * Javascript code in this page
  4. *
  5. * Copyright 2019 Mozilla Foundation
  6. *
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. *
  19. * @licend The above is the entire license notice for the
  20. * Javascript code in this page
  21. */
  22. "use strict";
  23. Object.defineProperty(exports, "__esModule", {
  24. value: true
  25. });
  26. exports.WorkerMessageHandler = exports.WorkerTask = void 0;
  27. var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
  28. var _util = require("../shared/util");
  29. var _primitives = require("./primitives");
  30. var _pdf_manager = require("./pdf_manager");
  31. var _is_node = _interopRequireDefault(require("../shared/is_node"));
  32. var _message_handler = require("../shared/message_handler");
  33. var _worker_stream = require("./worker_stream");
  34. var _core_utils = require("./core_utils");
  35. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
  36. function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
  37. function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
  38. function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
  39. function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
  40. 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); } }
  41. 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); }); }; }
  42. var WorkerTask = function WorkerTaskClosure() {
  43. function WorkerTask(name) {
  44. this.name = name;
  45. this.terminated = false;
  46. this._capability = (0, _util.createPromiseCapability)();
  47. }
  48. WorkerTask.prototype = {
  49. get finished() {
  50. return this._capability.promise;
  51. },
  52. finish: function finish() {
  53. this._capability.resolve();
  54. },
  55. terminate: function terminate() {
  56. this.terminated = true;
  57. },
  58. ensureNotTerminated: function ensureNotTerminated() {
  59. if (this.terminated) {
  60. throw new Error('Worker task was terminated');
  61. }
  62. }
  63. };
  64. return WorkerTask;
  65. }();
  66. exports.WorkerTask = WorkerTask;
  67. var WorkerMessageHandler = {
  68. setup: function setup(handler, port) {
  69. var testMessageProcessed = false;
  70. handler.on('test', function wphSetupTest(data) {
  71. if (testMessageProcessed) {
  72. return;
  73. }
  74. testMessageProcessed = true;
  75. if (!(data instanceof Uint8Array)) {
  76. handler.send('test', null);
  77. return;
  78. }
  79. var supportTransfers = data[0] === 255;
  80. handler.postMessageTransfers = supportTransfers;
  81. handler.send('test', {
  82. supportTransfers: supportTransfers
  83. });
  84. });
  85. handler.on('configure', function wphConfigure(data) {
  86. (0, _util.setVerbosityLevel)(data.verbosity);
  87. });
  88. handler.on('GetDocRequest', function wphSetupDoc(data) {
  89. return WorkerMessageHandler.createDocumentHandler(data, port);
  90. });
  91. },
  92. createDocumentHandler: function createDocumentHandler(docParams, port) {
  93. var pdfManager;
  94. var terminated = false;
  95. var cancelXHRs = null;
  96. var WorkerTasks = [];
  97. var verbosity = (0, _util.getVerbosityLevel)();
  98. var apiVersion = docParams.apiVersion;
  99. var workerVersion = '2.3.200';
  100. if (apiVersion !== workerVersion) {
  101. throw new Error("The API version \"".concat(apiVersion, "\" does not match ") + "the Worker version \"".concat(workerVersion, "\"."));
  102. }
  103. var docId = docParams.docId;
  104. var docBaseUrl = docParams.docBaseUrl;
  105. var workerHandlerName = docParams.docId + '_worker';
  106. var handler = new _message_handler.MessageHandler(workerHandlerName, docId, port);
  107. handler.postMessageTransfers = docParams.postMessageTransfers;
  108. function ensureNotTerminated() {
  109. if (terminated) {
  110. throw new Error('Worker was terminated');
  111. }
  112. }
  113. function startWorkerTask(task) {
  114. WorkerTasks.push(task);
  115. }
  116. function finishWorkerTask(task) {
  117. task.finish();
  118. var i = WorkerTasks.indexOf(task);
  119. WorkerTasks.splice(i, 1);
  120. }
  121. function loadDocument(_x) {
  122. return _loadDocument.apply(this, arguments);
  123. }
  124. function _loadDocument() {
  125. _loadDocument = _asyncToGenerator(
  126. /*#__PURE__*/
  127. _regenerator["default"].mark(function _callee(recoveryMode) {
  128. var _ref4, _ref5, numPages, fingerprint;
  129. return _regenerator["default"].wrap(function _callee$(_context) {
  130. while (1) {
  131. switch (_context.prev = _context.next) {
  132. case 0:
  133. _context.next = 2;
  134. return pdfManager.ensureDoc('checkHeader');
  135. case 2:
  136. _context.next = 4;
  137. return pdfManager.ensureDoc('parseStartXRef');
  138. case 4:
  139. _context.next = 6;
  140. return pdfManager.ensureDoc('parse', [recoveryMode]);
  141. case 6:
  142. if (recoveryMode) {
  143. _context.next = 9;
  144. break;
  145. }
  146. _context.next = 9;
  147. return pdfManager.ensureDoc('checkFirstPage');
  148. case 9:
  149. _context.next = 11;
  150. return Promise.all([pdfManager.ensureDoc('numPages'), pdfManager.ensureDoc('fingerprint')]);
  151. case 11:
  152. _ref4 = _context.sent;
  153. _ref5 = _slicedToArray(_ref4, 2);
  154. numPages = _ref5[0];
  155. fingerprint = _ref5[1];
  156. return _context.abrupt("return", {
  157. numPages: numPages,
  158. fingerprint: fingerprint
  159. });
  160. case 16:
  161. case "end":
  162. return _context.stop();
  163. }
  164. }
  165. }, _callee);
  166. }));
  167. return _loadDocument.apply(this, arguments);
  168. }
  169. function getPdfManager(data, evaluatorOptions) {
  170. var pdfManagerCapability = (0, _util.createPromiseCapability)();
  171. var pdfManager;
  172. var source = data.source;
  173. if (source.data) {
  174. try {
  175. pdfManager = new _pdf_manager.LocalPdfManager(docId, source.data, source.password, evaluatorOptions, docBaseUrl);
  176. pdfManagerCapability.resolve(pdfManager);
  177. } catch (ex) {
  178. pdfManagerCapability.reject(ex);
  179. }
  180. return pdfManagerCapability.promise;
  181. }
  182. var pdfStream,
  183. cachedChunks = [];
  184. try {
  185. pdfStream = new _worker_stream.PDFWorkerStream(handler);
  186. } catch (ex) {
  187. pdfManagerCapability.reject(ex);
  188. return pdfManagerCapability.promise;
  189. }
  190. var fullRequest = pdfStream.getFullReader();
  191. fullRequest.headersReady.then(function () {
  192. if (!fullRequest.isRangeSupported) {
  193. return;
  194. }
  195. var disableAutoFetch = source.disableAutoFetch || fullRequest.isStreamingSupported;
  196. pdfManager = new _pdf_manager.NetworkPdfManager(docId, pdfStream, {
  197. msgHandler: handler,
  198. password: source.password,
  199. length: fullRequest.contentLength,
  200. disableAutoFetch: disableAutoFetch,
  201. rangeChunkSize: source.rangeChunkSize
  202. }, evaluatorOptions, docBaseUrl);
  203. for (var i = 0; i < cachedChunks.length; i++) {
  204. pdfManager.sendProgressiveData(cachedChunks[i]);
  205. }
  206. cachedChunks = [];
  207. pdfManagerCapability.resolve(pdfManager);
  208. cancelXHRs = null;
  209. })["catch"](function (reason) {
  210. pdfManagerCapability.reject(reason);
  211. cancelXHRs = null;
  212. });
  213. var loaded = 0;
  214. var flushChunks = function flushChunks() {
  215. var pdfFile = (0, _util.arraysToBytes)(cachedChunks);
  216. if (source.length && pdfFile.length !== source.length) {
  217. (0, _util.warn)('reported HTTP length is different from actual');
  218. }
  219. try {
  220. pdfManager = new _pdf_manager.LocalPdfManager(docId, pdfFile, source.password, evaluatorOptions, docBaseUrl);
  221. pdfManagerCapability.resolve(pdfManager);
  222. } catch (ex) {
  223. pdfManagerCapability.reject(ex);
  224. }
  225. cachedChunks = [];
  226. };
  227. var readPromise = new Promise(function (resolve, reject) {
  228. var readChunk = function readChunk(chunk) {
  229. try {
  230. ensureNotTerminated();
  231. if (chunk.done) {
  232. if (!pdfManager) {
  233. flushChunks();
  234. }
  235. cancelXHRs = null;
  236. return;
  237. }
  238. var data = chunk.value;
  239. loaded += (0, _util.arrayByteLength)(data);
  240. if (!fullRequest.isStreamingSupported) {
  241. handler.send('DocProgress', {
  242. loaded: loaded,
  243. total: Math.max(loaded, fullRequest.contentLength || 0)
  244. });
  245. }
  246. if (pdfManager) {
  247. pdfManager.sendProgressiveData(data);
  248. } else {
  249. cachedChunks.push(data);
  250. }
  251. fullRequest.read().then(readChunk, reject);
  252. } catch (e) {
  253. reject(e);
  254. }
  255. };
  256. fullRequest.read().then(readChunk, reject);
  257. });
  258. readPromise["catch"](function (e) {
  259. pdfManagerCapability.reject(e);
  260. cancelXHRs = null;
  261. });
  262. cancelXHRs = function cancelXHRs(reason) {
  263. pdfStream.cancelAllRequests(reason);
  264. };
  265. return pdfManagerCapability.promise;
  266. }
  267. function setupDoc(data) {
  268. function onSuccess(doc) {
  269. ensureNotTerminated();
  270. handler.send('GetDoc', {
  271. pdfInfo: doc
  272. });
  273. }
  274. function onFailure(e) {
  275. ensureNotTerminated();
  276. if (e instanceof _util.PasswordException) {
  277. var task = new WorkerTask('PasswordException: response ' + e.code);
  278. startWorkerTask(task);
  279. handler.sendWithPromise('PasswordRequest', e).then(function (data) {
  280. finishWorkerTask(task);
  281. pdfManager.updatePassword(data.password);
  282. pdfManagerReady();
  283. })["catch"](function (boundException) {
  284. finishWorkerTask(task);
  285. handler.send('PasswordException', boundException);
  286. }.bind(null, e));
  287. } else if (e instanceof _util.InvalidPDFException) {
  288. handler.send('InvalidPDF', e);
  289. } else if (e instanceof _util.MissingPDFException) {
  290. handler.send('MissingPDF', e);
  291. } else if (e instanceof _util.UnexpectedResponseException) {
  292. handler.send('UnexpectedResponse', e);
  293. } else {
  294. handler.send('UnknownError', new _util.UnknownErrorException(e.message, e.toString()));
  295. }
  296. }
  297. function pdfManagerReady() {
  298. ensureNotTerminated();
  299. loadDocument(false).then(onSuccess, function loadFailure(ex) {
  300. ensureNotTerminated();
  301. if (!(ex instanceof _core_utils.XRefParseException)) {
  302. onFailure(ex);
  303. return;
  304. }
  305. pdfManager.requestLoadedStream();
  306. pdfManager.onLoadedStream().then(function () {
  307. ensureNotTerminated();
  308. loadDocument(true).then(onSuccess, onFailure);
  309. });
  310. }, onFailure);
  311. }
  312. ensureNotTerminated();
  313. var evaluatorOptions = {
  314. forceDataSchema: data.disableCreateObjectURL,
  315. maxImageSize: data.maxImageSize,
  316. disableFontFace: data.disableFontFace,
  317. nativeImageDecoderSupport: data.nativeImageDecoderSupport,
  318. ignoreErrors: data.ignoreErrors,
  319. isEvalSupported: data.isEvalSupported
  320. };
  321. getPdfManager(data, evaluatorOptions).then(function (newPdfManager) {
  322. if (terminated) {
  323. newPdfManager.terminate(new _util.AbortException('Worker was terminated.'));
  324. throw new Error('Worker was terminated');
  325. }
  326. pdfManager = newPdfManager;
  327. pdfManager.onLoadedStream().then(function (stream) {
  328. handler.send('DataLoaded', {
  329. length: stream.bytes.byteLength
  330. });
  331. });
  332. }).then(pdfManagerReady, onFailure);
  333. }
  334. handler.on('GetPage', function wphSetupGetPage(data) {
  335. return pdfManager.getPage(data.pageIndex).then(function (page) {
  336. return Promise.all([pdfManager.ensure(page, 'rotate'), pdfManager.ensure(page, 'ref'), pdfManager.ensure(page, 'userUnit'), pdfManager.ensure(page, 'view')]).then(function (_ref) {
  337. var _ref2 = _slicedToArray(_ref, 4),
  338. rotate = _ref2[0],
  339. ref = _ref2[1],
  340. userUnit = _ref2[2],
  341. view = _ref2[3];
  342. return {
  343. rotate: rotate,
  344. ref: ref,
  345. userUnit: userUnit,
  346. view: view
  347. };
  348. });
  349. });
  350. });
  351. handler.on('GetPageIndex', function wphSetupGetPageIndex(data) {
  352. var ref = _primitives.Ref.get(data.ref.num, data.ref.gen);
  353. var catalog = pdfManager.pdfDocument.catalog;
  354. return catalog.getPageIndex(ref);
  355. });
  356. handler.on('GetDestinations', function wphSetupGetDestinations(data) {
  357. return pdfManager.ensureCatalog('destinations');
  358. });
  359. handler.on('GetDestination', function wphSetupGetDestination(data) {
  360. return pdfManager.ensureCatalog('getDestination', [data.id]);
  361. });
  362. handler.on('GetPageLabels', function wphSetupGetPageLabels(data) {
  363. return pdfManager.ensureCatalog('pageLabels');
  364. });
  365. handler.on('GetPageLayout', function wphSetupGetPageLayout(data) {
  366. return pdfManager.ensureCatalog('pageLayout');
  367. });
  368. handler.on('GetPageMode', function wphSetupGetPageMode(data) {
  369. return pdfManager.ensureCatalog('pageMode');
  370. });
  371. handler.on('GetViewerPreferences', function (data) {
  372. return pdfManager.ensureCatalog('viewerPreferences');
  373. });
  374. handler.on('GetOpenActionDestination', function (data) {
  375. return pdfManager.ensureCatalog('openActionDestination');
  376. });
  377. handler.on('GetAttachments', function wphSetupGetAttachments(data) {
  378. return pdfManager.ensureCatalog('attachments');
  379. });
  380. handler.on('GetJavaScript', function wphSetupGetJavaScript(data) {
  381. return pdfManager.ensureCatalog('javaScript');
  382. });
  383. handler.on('GetOutline', function wphSetupGetOutline(data) {
  384. return pdfManager.ensureCatalog('documentOutline');
  385. });
  386. handler.on('GetPermissions', function (data) {
  387. return pdfManager.ensureCatalog('permissions');
  388. });
  389. handler.on('GetMetadata', function wphSetupGetMetadata(data) {
  390. return Promise.all([pdfManager.ensureDoc('documentInfo'), pdfManager.ensureCatalog('metadata')]);
  391. });
  392. handler.on('GetData', function wphSetupGetData(data) {
  393. pdfManager.requestLoadedStream();
  394. return pdfManager.onLoadedStream().then(function (stream) {
  395. return stream.bytes;
  396. });
  397. });
  398. handler.on('GetStats', function wphSetupGetStats(data) {
  399. return pdfManager.pdfDocument.xref.stats;
  400. });
  401. handler.on('GetAnnotations', function (_ref3) {
  402. var pageIndex = _ref3.pageIndex,
  403. intent = _ref3.intent;
  404. return pdfManager.getPage(pageIndex).then(function (page) {
  405. return page.getAnnotationsData(intent);
  406. });
  407. });
  408. handler.on('GetOperatorList', function wphSetupRenderPage(data, sink) {
  409. var pageIndex = data.pageIndex;
  410. pdfManager.getPage(pageIndex).then(function (page) {
  411. var task = new WorkerTask("GetOperatorList: page ".concat(pageIndex));
  412. startWorkerTask(task);
  413. var start = verbosity >= _util.VerbosityLevel.INFOS ? Date.now() : 0;
  414. page.getOperatorList({
  415. handler: handler,
  416. sink: sink,
  417. task: task,
  418. intent: data.intent,
  419. renderInteractiveForms: data.renderInteractiveForms
  420. }).then(function (operatorListInfo) {
  421. finishWorkerTask(task);
  422. if (start) {
  423. (0, _util.info)("page=".concat(pageIndex + 1, " - getOperatorList: time=") + "".concat(Date.now() - start, "ms, len=").concat(operatorListInfo.length));
  424. }
  425. sink.close();
  426. }, function (reason) {
  427. finishWorkerTask(task);
  428. if (task.terminated) {
  429. return;
  430. }
  431. handler.send('UnsupportedFeature', {
  432. featureId: _util.UNSUPPORTED_FEATURES.unknown
  433. });
  434. sink.error(reason);
  435. });
  436. });
  437. }, this);
  438. handler.on('GetTextContent', function wphExtractText(data, sink) {
  439. var pageIndex = data.pageIndex;
  440. sink.onPull = function (desiredSize) {};
  441. sink.onCancel = function (reason) {};
  442. pdfManager.getPage(pageIndex).then(function (page) {
  443. var task = new WorkerTask('GetTextContent: page ' + pageIndex);
  444. startWorkerTask(task);
  445. var start = verbosity >= _util.VerbosityLevel.INFOS ? Date.now() : 0;
  446. page.extractTextContent({
  447. handler: handler,
  448. task: task,
  449. sink: sink,
  450. normalizeWhitespace: data.normalizeWhitespace,
  451. combineTextItems: data.combineTextItems
  452. }).then(function () {
  453. finishWorkerTask(task);
  454. if (start) {
  455. (0, _util.info)("page=".concat(pageIndex + 1, " - getTextContent: time=") + "".concat(Date.now() - start, "ms"));
  456. }
  457. sink.close();
  458. }, function (reason) {
  459. finishWorkerTask(task);
  460. if (task.terminated) {
  461. return;
  462. }
  463. sink.error(reason);
  464. });
  465. });
  466. });
  467. handler.on('FontFallback', function (data) {
  468. return pdfManager.fontFallback(data.id, handler);
  469. });
  470. handler.on('Cleanup', function wphCleanup(data) {
  471. return pdfManager.cleanup();
  472. });
  473. handler.on('Terminate', function wphTerminate(data) {
  474. terminated = true;
  475. if (pdfManager) {
  476. pdfManager.terminate(new _util.AbortException('Worker was terminated.'));
  477. pdfManager = null;
  478. }
  479. if (cancelXHRs) {
  480. cancelXHRs(new _util.AbortException('Worker was terminated.'));
  481. }
  482. (0, _primitives.clearPrimitiveCaches)();
  483. var waitOn = [];
  484. WorkerTasks.forEach(function (task) {
  485. waitOn.push(task.finished);
  486. task.terminate();
  487. });
  488. return Promise.all(waitOn).then(function () {
  489. handler.destroy();
  490. handler = null;
  491. });
  492. });
  493. handler.on('Ready', function wphReady(data) {
  494. setupDoc(docParams);
  495. docParams = null;
  496. });
  497. return workerHandlerName;
  498. },
  499. initializeFromPort: function initializeFromPort(port) {
  500. var handler = new _message_handler.MessageHandler('worker', 'main', port);
  501. WorkerMessageHandler.setup(handler, port);
  502. handler.send('ready', null);
  503. }
  504. };
  505. exports.WorkerMessageHandler = WorkerMessageHandler;
  506. function isMessagePort(maybePort) {
  507. return typeof maybePort.postMessage === 'function' && 'onmessage' in maybePort;
  508. }
  509. if (typeof window === 'undefined' && !(0, _is_node["default"])() && typeof self !== 'undefined' && isMessagePort(self)) {
  510. WorkerMessageHandler.initializeFromPort(self);
  511. }