api_spec.js 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065
  1. /* Copyright 2017 Mozilla Foundation
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. 'use strict';
  16. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
  17. var sharedUtil = require('../../shared/util.js');
  18. var displayDOMUtils = require('../../display/dom_utils.js');
  19. var displayGlobal = require('../../display/global.js');
  20. var displayApi = require('../../display/api.js');
  21. var PDFJS = displayGlobal.PDFJS;
  22. var createPromiseCapability = sharedUtil.createPromiseCapability;
  23. var DOMCanvasFactory = displayDOMUtils.DOMCanvasFactory;
  24. var RenderingCancelledException = displayDOMUtils.RenderingCancelledException;
  25. var PDFDocumentProxy = displayApi.PDFDocumentProxy;
  26. var InvalidPDFException = sharedUtil.InvalidPDFException;
  27. var MissingPDFException = sharedUtil.MissingPDFException;
  28. var PasswordResponses = sharedUtil.PasswordResponses;
  29. var PasswordException = sharedUtil.PasswordException;
  30. var PDFPageProxy = displayApi.PDFPageProxy;
  31. var StreamType = sharedUtil.StreamType;
  32. var FontType = sharedUtil.FontType;
  33. describe('api', function () {
  34. var basicApiUrl = new URL('../pdfs/basicapi.pdf', window.location).href;
  35. var basicApiFileLength = 105779;
  36. var CanvasFactory;
  37. beforeAll(function (done) {
  38. CanvasFactory = new DOMCanvasFactory();
  39. done();
  40. });
  41. afterAll(function () {
  42. CanvasFactory = null;
  43. });
  44. function waitSome(callback) {
  45. var WAIT_TIMEOUT = 10;
  46. setTimeout(function () {
  47. callback();
  48. }, WAIT_TIMEOUT);
  49. }
  50. describe('PDFJS', function () {
  51. describe('getDocument', function () {
  52. it('creates pdf doc from URL', function (done) {
  53. var loadingTask = PDFJS.getDocument(basicApiUrl);
  54. var isProgressReportedResolved = false;
  55. var progressReportedCapability = createPromiseCapability();
  56. loadingTask.onProgress = function (progressData) {
  57. if (!isProgressReportedResolved) {
  58. isProgressReportedResolved = true;
  59. progressReportedCapability.resolve(progressData);
  60. }
  61. };
  62. var promises = [progressReportedCapability.promise, loadingTask.promise];
  63. Promise.all(promises).then(function (data) {
  64. expect(data[0].loaded / data[0].total > 0).toEqual(true);
  65. expect(data[1] instanceof PDFDocumentProxy).toEqual(true);
  66. expect(loadingTask).toEqual(data[1].loadingTask);
  67. loadingTask.destroy();
  68. done();
  69. }).catch(function (reason) {
  70. done.fail(reason);
  71. });
  72. });
  73. it('creates pdf doc from URL and aborts before worker initialized', function (done) {
  74. var loadingTask = PDFJS.getDocument(basicApiUrl);
  75. loadingTask.destroy();
  76. loadingTask.promise.then(function (reason) {
  77. done.fail('shall fail loading');
  78. }).catch(function (reason) {
  79. expect(true).toEqual(true);
  80. done();
  81. });
  82. });
  83. it('creates pdf doc from URL and aborts loading after worker initialized', function (done) {
  84. var loadingTask = PDFJS.getDocument(basicApiUrl);
  85. var destroyed = loadingTask._worker.promise.then(function () {
  86. return loadingTask.destroy();
  87. });
  88. destroyed.then(function (data) {
  89. expect(true).toEqual(true);
  90. done();
  91. }).catch(function (reason) {
  92. done.fail(reason);
  93. });
  94. });
  95. it('creates pdf doc from typed array', function (done) {
  96. var nonBinaryRequest = PDFJS.disableWorker;
  97. var request = new XMLHttpRequest();
  98. request.open('GET', basicApiUrl, false);
  99. if (!nonBinaryRequest) {
  100. try {
  101. request.responseType = 'arraybuffer';
  102. nonBinaryRequest = request.responseType !== 'arraybuffer';
  103. } catch (e) {
  104. nonBinaryRequest = true;
  105. }
  106. }
  107. if (nonBinaryRequest && request.overrideMimeType) {
  108. request.overrideMimeType('text/plain; charset=x-user-defined');
  109. }
  110. request.send(null);
  111. var typedArrayPdf;
  112. if (nonBinaryRequest) {
  113. var data = Array.prototype.map.call(request.responseText, function (ch) {
  114. return ch.charCodeAt(0) & 0xFF;
  115. });
  116. typedArrayPdf = new Uint8Array(data);
  117. } else {
  118. typedArrayPdf = new Uint8Array(request.response);
  119. }
  120. expect(typedArrayPdf.length).toEqual(basicApiFileLength);
  121. var loadingTask = PDFJS.getDocument(typedArrayPdf);
  122. loadingTask.promise.then(function (data) {
  123. expect(data instanceof PDFDocumentProxy).toEqual(true);
  124. loadingTask.destroy();
  125. done();
  126. }).catch(function (reason) {
  127. done.fail(reason);
  128. });
  129. });
  130. it('creates pdf doc from invalid PDF file', function (done) {
  131. var url = new URL('../pdfs/bug1020226.pdf', window.location).href;
  132. var loadingTask = PDFJS.getDocument(url);
  133. loadingTask.promise.then(function () {
  134. done.fail('shall fail loading');
  135. }).catch(function (error) {
  136. expect(error instanceof InvalidPDFException).toEqual(true);
  137. loadingTask.destroy();
  138. done();
  139. });
  140. });
  141. it('creates pdf doc from non-existent URL', function (done) {
  142. var nonExistentUrl = new URL('../pdfs/non-existent.pdf', window.location).href;
  143. var loadingTask = PDFJS.getDocument(nonExistentUrl);
  144. loadingTask.promise.then(function (error) {
  145. done.fail('shall fail loading');
  146. }).catch(function (error) {
  147. expect(error instanceof MissingPDFException).toEqual(true);
  148. loadingTask.destroy();
  149. done();
  150. });
  151. });
  152. it('creates pdf doc from PDF file protected with user and owner password', function (done) {
  153. var url = new URL('../pdfs/pr6531_1.pdf', window.location).href;
  154. var loadingTask = PDFJS.getDocument(url);
  155. var isPasswordNeededResolved = false;
  156. var passwordNeededCapability = createPromiseCapability();
  157. var isPasswordIncorrectResolved = false;
  158. var passwordIncorrectCapability = createPromiseCapability();
  159. loadingTask.onPassword = function (updatePassword, reason) {
  160. if (reason === PasswordResponses.NEED_PASSWORD && !isPasswordNeededResolved) {
  161. isPasswordNeededResolved = true;
  162. passwordNeededCapability.resolve();
  163. updatePassword('qwerty');
  164. return;
  165. }
  166. if (reason === PasswordResponses.INCORRECT_PASSWORD && !isPasswordIncorrectResolved) {
  167. isPasswordIncorrectResolved = true;
  168. passwordIncorrectCapability.resolve();
  169. updatePassword('asdfasdf');
  170. return;
  171. }
  172. expect(false).toEqual(true);
  173. };
  174. var promises = [passwordNeededCapability.promise, passwordIncorrectCapability.promise, loadingTask.promise];
  175. Promise.all(promises).then(function (data) {
  176. expect(data[2] instanceof PDFDocumentProxy).toEqual(true);
  177. loadingTask.destroy();
  178. done();
  179. }).catch(function (reason) {
  180. done.fail(reason);
  181. });
  182. });
  183. it('creates pdf doc from PDF file protected with only a user password', function (done) {
  184. var url = new URL('../pdfs/pr6531_2.pdf', window.location).href;
  185. var passwordNeededLoadingTask = PDFJS.getDocument({
  186. url: url,
  187. password: ''
  188. });
  189. var result1 = passwordNeededLoadingTask.promise.then(function () {
  190. done.fail('shall fail with no password');
  191. return Promise.reject(new Error('loadingTask should be rejected'));
  192. }, function (data) {
  193. expect(data instanceof PasswordException).toEqual(true);
  194. expect(data.code).toEqual(PasswordResponses.NEED_PASSWORD);
  195. return passwordNeededLoadingTask.destroy();
  196. });
  197. var passwordIncorrectLoadingTask = PDFJS.getDocument({
  198. url: url,
  199. password: 'qwerty'
  200. });
  201. var result2 = passwordIncorrectLoadingTask.promise.then(function () {
  202. done.fail('shall fail with wrong password');
  203. return Promise.reject(new Error('loadingTask should be rejected'));
  204. }, function (data) {
  205. expect(data instanceof PasswordException).toEqual(true);
  206. expect(data.code).toEqual(PasswordResponses.INCORRECT_PASSWORD);
  207. return passwordIncorrectLoadingTask.destroy();
  208. });
  209. var passwordAcceptedLoadingTask = PDFJS.getDocument({
  210. url: url,
  211. password: 'asdfasdf'
  212. });
  213. var result3 = passwordAcceptedLoadingTask.promise.then(function (data) {
  214. expect(data instanceof PDFDocumentProxy).toEqual(true);
  215. return passwordAcceptedLoadingTask.destroy();
  216. });
  217. Promise.all([result1, result2, result3]).then(function () {
  218. done();
  219. }).catch(function (reason) {
  220. done.fail(reason);
  221. });
  222. });
  223. it('creates pdf doc from password protected PDF file and aborts/throws ' + 'in the onPassword callback (issue 7806)', function (done) {
  224. var url = new URL('../pdfs/issue3371.pdf', window.location).href;
  225. var passwordNeededLoadingTask = PDFJS.getDocument(url);
  226. var passwordIncorrectLoadingTask = PDFJS.getDocument({
  227. url: url,
  228. password: 'qwerty'
  229. });
  230. passwordNeededLoadingTask.onPassword = function (callback, reason) {
  231. if (reason === PasswordResponses.NEED_PASSWORD) {
  232. passwordNeededLoadingTask.destroy();
  233. return;
  234. }
  235. expect(false).toEqual(true);
  236. };
  237. var result1 = passwordNeededLoadingTask.promise.then(function () {
  238. done.fail('shall fail since the loadingTask should be destroyed');
  239. return Promise.reject(new Error('loadingTask should be rejected'));
  240. }, function (reason) {
  241. expect(reason instanceof PasswordException).toEqual(true);
  242. expect(reason.code).toEqual(PasswordResponses.NEED_PASSWORD);
  243. });
  244. passwordIncorrectLoadingTask.onPassword = function (callback, reason) {
  245. if (reason === PasswordResponses.INCORRECT_PASSWORD) {
  246. throw new Error('Incorrect password');
  247. }
  248. expect(false).toEqual(true);
  249. };
  250. var result2 = passwordIncorrectLoadingTask.promise.then(function () {
  251. done.fail('shall fail since the onPassword callback should throw');
  252. return Promise.reject(new Error('loadingTask should be rejected'));
  253. }, function (reason) {
  254. expect(reason instanceof PasswordException).toEqual(true);
  255. expect(reason.code).toEqual(PasswordResponses.INCORRECT_PASSWORD);
  256. return passwordIncorrectLoadingTask.destroy();
  257. });
  258. Promise.all([result1, result2]).then(function () {
  259. done();
  260. }).catch(function (reason) {
  261. done.fail(reason);
  262. });
  263. });
  264. });
  265. });
  266. describe('PDFWorker', function () {
  267. it('worker created or destroyed', function (done) {
  268. var worker = new PDFJS.PDFWorker('test1');
  269. worker.promise.then(function () {
  270. expect(worker.name).toEqual('test1');
  271. expect(!!worker.port).toEqual(true);
  272. expect(worker.destroyed).toEqual(false);
  273. expect(!!worker._webWorker).toEqual(true);
  274. expect(worker.port === worker._webWorker).toEqual(true);
  275. worker.destroy();
  276. expect(!!worker.port).toEqual(false);
  277. expect(worker.destroyed).toEqual(true);
  278. done();
  279. }).catch(function (reason) {
  280. done.fail(reason);
  281. });
  282. });
  283. it('worker created or destroyed by getDocument', function (done) {
  284. var loadingTask = PDFJS.getDocument(basicApiUrl);
  285. var worker;
  286. loadingTask.promise.then(function () {
  287. worker = loadingTask._worker;
  288. expect(!!worker).toEqual(true);
  289. });
  290. var destroyPromise = loadingTask.promise.then(function () {
  291. return loadingTask.destroy();
  292. });
  293. destroyPromise.then(function () {
  294. var destroyedWorker = loadingTask._worker;
  295. expect(!!destroyedWorker).toEqual(false);
  296. expect(worker.destroyed).toEqual(true);
  297. done();
  298. }).catch(function (reason) {
  299. done.fail(reason);
  300. });
  301. });
  302. it('worker created and can be used in getDocument', function (done) {
  303. var worker = new PDFJS.PDFWorker('test1');
  304. var loadingTask = PDFJS.getDocument({
  305. url: basicApiUrl,
  306. worker: worker
  307. });
  308. loadingTask.promise.then(function () {
  309. var docWorker = loadingTask._worker;
  310. expect(!!docWorker).toEqual(false);
  311. var messageHandlerPort = loadingTask._transport.messageHandler.comObj;
  312. expect(messageHandlerPort === worker.port).toEqual(true);
  313. });
  314. var destroyPromise = loadingTask.promise.then(function () {
  315. return loadingTask.destroy();
  316. });
  317. destroyPromise.then(function () {
  318. expect(worker.destroyed).toEqual(false);
  319. worker.destroy();
  320. done();
  321. }).catch(function (reason) {
  322. done.fail(reason);
  323. });
  324. });
  325. it('creates more than one worker', function (done) {
  326. var worker1 = new PDFJS.PDFWorker('test1');
  327. var worker2 = new PDFJS.PDFWorker('test2');
  328. var worker3 = new PDFJS.PDFWorker('test3');
  329. var ready = Promise.all([worker1.promise, worker2.promise, worker3.promise]);
  330. ready.then(function () {
  331. expect(worker1.port !== worker2.port && worker1.port !== worker3.port && worker2.port !== worker3.port).toEqual(true);
  332. worker1.destroy();
  333. worker2.destroy();
  334. worker3.destroy();
  335. done();
  336. }).catch(function (reason) {
  337. done.fail(reason);
  338. });
  339. });
  340. });
  341. describe('PDFDocument', function () {
  342. var loadingTask;
  343. var doc;
  344. beforeAll(function (done) {
  345. loadingTask = PDFJS.getDocument(basicApiUrl);
  346. loadingTask.promise.then(function (data) {
  347. doc = data;
  348. done();
  349. });
  350. });
  351. afterAll(function () {
  352. loadingTask.destroy();
  353. });
  354. it('gets number of pages', function () {
  355. expect(doc.numPages).toEqual(3);
  356. });
  357. it('gets fingerprint', function () {
  358. var fingerprint = doc.fingerprint;
  359. expect(typeof fingerprint === 'undefined' ? 'undefined' : _typeof(fingerprint)).toEqual('string');
  360. expect(fingerprint.length > 0).toEqual(true);
  361. });
  362. it('gets page', function (done) {
  363. var promise = doc.getPage(1);
  364. promise.then(function (data) {
  365. expect(data instanceof PDFPageProxy).toEqual(true);
  366. expect(data.pageIndex).toEqual(0);
  367. done();
  368. }).catch(function (reason) {
  369. done.fail(reason);
  370. });
  371. });
  372. it('gets non-existent page', function (done) {
  373. var outOfRangePromise = doc.getPage(100);
  374. var nonIntegerPromise = doc.getPage(2.5);
  375. var nonNumberPromise = doc.getPage('1');
  376. outOfRangePromise = outOfRangePromise.then(function () {
  377. throw new Error('shall fail for out-of-range pageNumber parameter');
  378. }, function (reason) {
  379. expect(reason instanceof Error).toEqual(true);
  380. });
  381. nonIntegerPromise = nonIntegerPromise.then(function () {
  382. throw new Error('shall fail for non-integer pageNumber parameter');
  383. }, function (reason) {
  384. expect(reason instanceof Error).toEqual(true);
  385. });
  386. nonNumberPromise = nonNumberPromise.then(function () {
  387. throw new Error('shall fail for non-number pageNumber parameter');
  388. }, function (reason) {
  389. expect(reason instanceof Error).toEqual(true);
  390. });
  391. Promise.all([outOfRangePromise, nonIntegerPromise, nonNumberPromise]).then(function () {
  392. done();
  393. }).catch(function (reason) {
  394. done.fail(reason);
  395. });
  396. });
  397. it('gets page index', function (done) {
  398. var ref = {
  399. num: 17,
  400. gen: 0
  401. };
  402. var promise = doc.getPageIndex(ref);
  403. promise.then(function (pageIndex) {
  404. expect(pageIndex).toEqual(1);
  405. done();
  406. }).catch(function (reason) {
  407. done.fail(reason);
  408. });
  409. });
  410. it('gets invalid page index', function (done) {
  411. var ref = {
  412. num: 3,
  413. gen: 0
  414. };
  415. var promise = doc.getPageIndex(ref);
  416. promise.then(function () {
  417. done.fail('shall fail for invalid page reference.');
  418. }).catch(function (reason) {
  419. expect(reason instanceof Error).toEqual(true);
  420. done();
  421. });
  422. });
  423. it('gets destinations, from /Dests dictionary', function (done) {
  424. var promise = doc.getDestinations();
  425. promise.then(function (data) {
  426. expect(data).toEqual({
  427. chapter1: [{
  428. gen: 0,
  429. num: 17
  430. }, { name: 'XYZ' }, 0, 841.89, null]
  431. });
  432. done();
  433. }).catch(function (reason) {
  434. done.fail(reason);
  435. });
  436. });
  437. it('gets a destination, from /Dests dictionary', function (done) {
  438. var promise = doc.getDestination('chapter1');
  439. promise.then(function (data) {
  440. expect(data).toEqual([{
  441. gen: 0,
  442. num: 17
  443. }, { name: 'XYZ' }, 0, 841.89, null]);
  444. done();
  445. }).catch(function (reason) {
  446. done.fail(reason);
  447. });
  448. });
  449. it('gets a non-existent destination, from /Dests dictionary', function (done) {
  450. var promise = doc.getDestination('non-existent-named-destination');
  451. promise.then(function (data) {
  452. expect(data).toEqual(null);
  453. done();
  454. }).catch(function (reason) {
  455. done.fail(reason);
  456. });
  457. });
  458. it('gets destinations, from /Names (NameTree) dictionary', function (done) {
  459. var url = new URL('../pdfs/issue6204.pdf', window.location).href;
  460. var loadingTask = PDFJS.getDocument(url);
  461. var promise = loadingTask.promise.then(function (pdfDocument) {
  462. return pdfDocument.getDestinations();
  463. });
  464. promise.then(function (destinations) {
  465. expect(destinations).toEqual({
  466. 'Page.1': [{
  467. num: 1,
  468. gen: 0
  469. }, { name: 'XYZ' }, 0, 375, null],
  470. 'Page.2': [{
  471. num: 6,
  472. gen: 0
  473. }, { name: 'XYZ' }, 0, 375, null]
  474. });
  475. loadingTask.destroy();
  476. done();
  477. }).catch(function (reason) {
  478. done.fail(reason);
  479. });
  480. });
  481. it('gets a destination, from /Names (NameTree) dictionary', function (done) {
  482. var url = new URL('../pdfs/issue6204.pdf', window.location).href;
  483. var loadingTask = PDFJS.getDocument(url);
  484. var promise = loadingTask.promise.then(function (pdfDocument) {
  485. return pdfDocument.getDestination('Page.1');
  486. });
  487. promise.then(function (destination) {
  488. expect(destination).toEqual([{
  489. num: 1,
  490. gen: 0
  491. }, { name: 'XYZ' }, 0, 375, null]);
  492. loadingTask.destroy();
  493. done();
  494. }).catch(function (reason) {
  495. done.fail(reason);
  496. });
  497. });
  498. it('gets a non-existent destination, from /Names (NameTree) dictionary', function (done) {
  499. var url = new URL('../pdfs/issue6204.pdf', window.location).href;
  500. var loadingTask = PDFJS.getDocument(url);
  501. var promise = loadingTask.promise.then(function (pdfDocument) {
  502. return pdfDocument.getDestination('non-existent-named-destination');
  503. });
  504. promise.then(function (destination) {
  505. expect(destination).toEqual(null);
  506. loadingTask.destroy();
  507. done();
  508. }).catch(function (reason) {
  509. done.fail(reason);
  510. });
  511. });
  512. it('gets non-existent page labels', function (done) {
  513. var promise = doc.getPageLabels();
  514. promise.then(function (data) {
  515. expect(data).toEqual(null);
  516. done();
  517. }).catch(function (reason) {
  518. done.fail(reason);
  519. });
  520. });
  521. it('gets page labels', function (done) {
  522. var url0 = new URL('../pdfs/bug793632.pdf', window.location).href;
  523. var loadingTask0 = PDFJS.getDocument(url0);
  524. var promise0 = loadingTask0.promise.then(function (pdfDoc) {
  525. return pdfDoc.getPageLabels();
  526. });
  527. var url1 = new URL('../pdfs/issue1453.pdf', window.location).href;
  528. var loadingTask1 = PDFJS.getDocument(url1);
  529. var promise1 = loadingTask1.promise.then(function (pdfDoc) {
  530. return pdfDoc.getPageLabels();
  531. });
  532. var url2 = new URL('../pdfs/rotation.pdf', window.location).href;
  533. var loadingTask2 = PDFJS.getDocument(url2);
  534. var promise2 = loadingTask2.promise.then(function (pdfDoc) {
  535. return pdfDoc.getPageLabels();
  536. });
  537. var url3 = new URL('../pdfs/bad-PageLabels.pdf', window.location).href;
  538. var loadingTask3 = PDFJS.getDocument(url3);
  539. var promise3 = loadingTask3.promise.then(function (pdfDoc) {
  540. return pdfDoc.getPageLabels();
  541. });
  542. Promise.all([promise0, promise1, promise2, promise3]).then(function (pageLabels) {
  543. expect(pageLabels[0]).toEqual(['i', 'ii', 'iii', '1']);
  544. expect(pageLabels[1]).toEqual(['Front Page1']);
  545. expect(pageLabels[2]).toEqual(['1', '2']);
  546. expect(pageLabels[3]).toEqual(['X3']);
  547. loadingTask0.destroy();
  548. loadingTask1.destroy();
  549. loadingTask2.destroy();
  550. loadingTask3.destroy();
  551. done();
  552. }).catch(function (reason) {
  553. done.fail(reason);
  554. });
  555. });
  556. it('gets non-existent attachments', function (done) {
  557. var promise = doc.getAttachments();
  558. promise.then(function (data) {
  559. expect(data).toEqual(null);
  560. done();
  561. }).catch(function (reason) {
  562. done.fail(reason);
  563. });
  564. });
  565. it('gets attachments', function (done) {
  566. var url = new URL('../pdfs/bug766138.pdf', window.location).href;
  567. var loadingTask = PDFJS.getDocument(url);
  568. var promise = loadingTask.promise.then(function (pdfDoc) {
  569. return pdfDoc.getAttachments();
  570. });
  571. promise.then(function (data) {
  572. var attachment = data['Press Quality.joboptions'];
  573. expect(attachment.filename).toEqual('Press Quality.joboptions');
  574. expect(attachment.content instanceof Uint8Array).toBeTruthy();
  575. expect(attachment.content.length).toEqual(30098);
  576. loadingTask.destroy();
  577. done();
  578. }).catch(function (reason) {
  579. done.fail(reason);
  580. });
  581. });
  582. it('gets javascript', function (done) {
  583. var promise = doc.getJavaScript();
  584. promise.then(function (data) {
  585. expect(data).toEqual([]);
  586. done();
  587. }).catch(function (reason) {
  588. done.fail(reason);
  589. });
  590. });
  591. var viewerPrintRegExp = /\bprint\s*\(/;
  592. it('gets javascript with printing instructions (Print action)', function (done) {
  593. var pdfUrl = new URL('../pdfs/bug1001080.pdf', window.location).href;
  594. var loadingTask = PDFJS.getDocument(pdfUrl);
  595. var promise = loadingTask.promise.then(function (doc) {
  596. return doc.getJavaScript();
  597. });
  598. promise.then(function (data) {
  599. expect(data).toEqual(['print({});']);
  600. expect(data[0]).toMatch(viewerPrintRegExp);
  601. loadingTask.destroy();
  602. done();
  603. }).catch(function (reason) {
  604. done.fail(reason);
  605. });
  606. });
  607. it('gets javascript with printing instructions (JS action)', function (done) {
  608. var pdfUrl = new URL('../pdfs/issue6106.pdf', window.location).href;
  609. var loadingTask = PDFJS.getDocument(pdfUrl);
  610. var promise = loadingTask.promise.then(function (doc) {
  611. return doc.getJavaScript();
  612. });
  613. promise.then(function (data) {
  614. expect(data).toEqual(['this.print({bUI:true,bSilent:false,bShrinkToFit:true});']);
  615. expect(data[0]).toMatch(viewerPrintRegExp);
  616. loadingTask.destroy();
  617. done();
  618. }).catch(function (reason) {
  619. done.fail(reason);
  620. });
  621. });
  622. it('gets non-existent outline', function (done) {
  623. var url = new URL('../pdfs/tracemonkey.pdf', window.location).href;
  624. var loadingTask = PDFJS.getDocument(url);
  625. var promise = loadingTask.promise.then(function (pdfDocument) {
  626. return pdfDocument.getOutline();
  627. });
  628. promise.then(function (outline) {
  629. expect(outline).toEqual(null);
  630. loadingTask.destroy();
  631. done();
  632. }).catch(function (reason) {
  633. done.fail(reason);
  634. });
  635. });
  636. it('gets outline', function (done) {
  637. var promise = doc.getOutline();
  638. promise.then(function (outline) {
  639. expect(outline instanceof Array).toEqual(true);
  640. expect(outline.length).toEqual(2);
  641. var outlineItem = outline[1];
  642. expect(outlineItem.title).toEqual('Chapter 1');
  643. expect(outlineItem.dest instanceof Array).toEqual(true);
  644. expect(outlineItem.url).toEqual(null);
  645. expect(outlineItem.unsafeUrl).toBeUndefined();
  646. expect(outlineItem.newWindow).toBeUndefined();
  647. expect(outlineItem.bold).toEqual(true);
  648. expect(outlineItem.italic).toEqual(false);
  649. expect(outlineItem.color).toEqual(new Uint8Array([0, 64, 128]));
  650. expect(outlineItem.items.length).toEqual(1);
  651. expect(outlineItem.items[0].title).toEqual('Paragraph 1.1');
  652. done();
  653. }).catch(function (reason) {
  654. done.fail(reason);
  655. });
  656. });
  657. it('gets outline containing a url', function (done) {
  658. var pdfUrl = new URL('../pdfs/issue3214.pdf', window.location).href;
  659. var loadingTask = PDFJS.getDocument(pdfUrl);
  660. loadingTask.promise.then(function (pdfDocument) {
  661. pdfDocument.getOutline().then(function (outline) {
  662. expect(outline instanceof Array).toEqual(true);
  663. expect(outline.length).toEqual(5);
  664. var outlineItemTwo = outline[2];
  665. expect(_typeof(outlineItemTwo.title)).toEqual('string');
  666. expect(outlineItemTwo.dest).toEqual(null);
  667. expect(outlineItemTwo.url).toEqual('http://google.com/');
  668. expect(outlineItemTwo.unsafeUrl).toEqual('http://google.com');
  669. expect(outlineItemTwo.newWindow).toBeUndefined();
  670. var outlineItemOne = outline[1];
  671. expect(outlineItemOne.bold).toEqual(false);
  672. expect(outlineItemOne.italic).toEqual(true);
  673. expect(outlineItemOne.color).toEqual(new Uint8Array([0, 0, 0]));
  674. loadingTask.destroy();
  675. done();
  676. });
  677. }).catch(function (reason) {
  678. done.fail(reason);
  679. });
  680. });
  681. it('gets metadata', function (done) {
  682. var promise = doc.getMetadata();
  683. promise.then(function (metadata) {
  684. expect(metadata.info['Title']).toEqual('Basic API Test');
  685. expect(metadata.info['PDFFormatVersion']).toEqual('1.7');
  686. expect(metadata.metadata.get('dc:title')).toEqual('Basic API Test');
  687. done();
  688. }).catch(function (reason) {
  689. done.fail(reason);
  690. });
  691. });
  692. it('gets data', function (done) {
  693. var promise = doc.getData();
  694. promise.then(function (data) {
  695. expect(data instanceof Uint8Array).toEqual(true);
  696. expect(data.length).toEqual(basicApiFileLength);
  697. done();
  698. }).catch(function (reason) {
  699. done.fail(reason);
  700. });
  701. });
  702. it('gets download info', function (done) {
  703. var promise = doc.getDownloadInfo();
  704. promise.then(function (data) {
  705. expect(data).toEqual({ length: basicApiFileLength });
  706. done();
  707. }).catch(function (reason) {
  708. done.fail(reason);
  709. });
  710. });
  711. it('gets stats', function (done) {
  712. var promise = doc.getStats();
  713. promise.then(function (stats) {
  714. expect(stats).toEqual({
  715. streamTypes: [],
  716. fontTypes: []
  717. });
  718. done();
  719. }).catch(function (reason) {
  720. done.fail(reason);
  721. });
  722. });
  723. it('checks that fingerprints are unique', function (done) {
  724. var url1 = new URL('../pdfs/issue4436r.pdf', window.location).href;
  725. var loadingTask1 = PDFJS.getDocument(url1);
  726. var url2 = new URL('../pdfs/issue4575.pdf', window.location).href;
  727. var loadingTask2 = PDFJS.getDocument(url2);
  728. var promises = [loadingTask1.promise, loadingTask2.promise];
  729. Promise.all(promises).then(function (data) {
  730. var fingerprint1 = data[0].fingerprint;
  731. expect(typeof fingerprint1 === 'undefined' ? 'undefined' : _typeof(fingerprint1)).toEqual('string');
  732. expect(fingerprint1.length > 0).toEqual(true);
  733. var fingerprint2 = data[1].fingerprint;
  734. expect(typeof fingerprint2 === 'undefined' ? 'undefined' : _typeof(fingerprint2)).toEqual('string');
  735. expect(fingerprint2.length > 0).toEqual(true);
  736. expect(fingerprint1).not.toEqual(fingerprint2);
  737. loadingTask1.destroy();
  738. loadingTask2.destroy();
  739. done();
  740. }).catch(function (reason) {
  741. done.fail(reason);
  742. });
  743. });
  744. });
  745. describe('Page', function () {
  746. var loadingTask;
  747. var pdfDocument, page;
  748. beforeAll(function (done) {
  749. loadingTask = PDFJS.getDocument(basicApiUrl);
  750. loadingTask.promise.then(function (doc) {
  751. pdfDocument = doc;
  752. pdfDocument.getPage(1).then(function (data) {
  753. page = data;
  754. done();
  755. });
  756. }).catch(function (reason) {
  757. done.fail(reason);
  758. });
  759. });
  760. afterAll(function () {
  761. loadingTask.destroy();
  762. });
  763. it('gets page number', function () {
  764. expect(page.pageNumber).toEqual(1);
  765. });
  766. it('gets rotate', function () {
  767. expect(page.rotate).toEqual(0);
  768. });
  769. it('gets ref', function () {
  770. expect(page.ref).toEqual({
  771. num: 15,
  772. gen: 0
  773. });
  774. });
  775. it('gets userUnit', function () {
  776. expect(page.userUnit).toEqual(1.0);
  777. });
  778. it('gets view', function () {
  779. expect(page.view).toEqual([0, 0, 595.28, 841.89]);
  780. });
  781. it('gets viewport', function () {
  782. var viewport = page.getViewport(1.5, 90);
  783. expect(viewport.viewBox).toEqual(page.view);
  784. expect(viewport.scale).toEqual(1.5);
  785. expect(viewport.rotation).toEqual(90);
  786. expect(viewport.transform).toEqual([0, 1.5, 1.5, 0, 0, 0]);
  787. expect(viewport.width).toEqual(1262.835);
  788. expect(viewport.height).toEqual(892.92);
  789. });
  790. it('gets annotations', function (done) {
  791. var defaultPromise = page.getAnnotations().then(function (data) {
  792. expect(data.length).toEqual(4);
  793. });
  794. var displayPromise = page.getAnnotations({ intent: 'display' }).then(function (data) {
  795. expect(data.length).toEqual(4);
  796. });
  797. var printPromise = page.getAnnotations({ intent: 'print' }).then(function (data) {
  798. expect(data.length).toEqual(4);
  799. });
  800. Promise.all([defaultPromise, displayPromise, printPromise]).then(function () {
  801. done();
  802. }).catch(function (reason) {
  803. done.fail(reason);
  804. });
  805. });
  806. it('gets annotations containing relative URLs (bug 766086)', function (done) {
  807. var url = new URL('../pdfs/bug766086.pdf', window.location).href;
  808. var defaultLoadingTask = PDFJS.getDocument(url);
  809. var defaultPromise = defaultLoadingTask.promise.then(function (pdfDoc) {
  810. return pdfDoc.getPage(1).then(function (pdfPage) {
  811. return pdfPage.getAnnotations();
  812. });
  813. });
  814. var docBaseUrlLoadingTask = PDFJS.getDocument({
  815. url: url,
  816. docBaseUrl: 'http://www.example.com/test/pdfs/qwerty.pdf'
  817. });
  818. var docBaseUrlPromise = docBaseUrlLoadingTask.promise.then(function (pdfDoc) {
  819. return pdfDoc.getPage(1).then(function (pdfPage) {
  820. return pdfPage.getAnnotations();
  821. });
  822. });
  823. var invalidDocBaseUrlLoadingTask = PDFJS.getDocument({
  824. url: url,
  825. docBaseUrl: 'qwerty.pdf'
  826. });
  827. var invalidDocBaseUrlPromise = invalidDocBaseUrlLoadingTask.promise.then(function (pdfDoc) {
  828. return pdfDoc.getPage(1).then(function (pdfPage) {
  829. return pdfPage.getAnnotations();
  830. });
  831. });
  832. Promise.all([defaultPromise, docBaseUrlPromise, invalidDocBaseUrlPromise]).then(function (data) {
  833. var defaultAnnotations = data[0];
  834. var docBaseUrlAnnotations = data[1];
  835. var invalidDocBaseUrlAnnotations = data[2];
  836. expect(defaultAnnotations[0].url).toBeUndefined();
  837. expect(defaultAnnotations[0].unsafeUrl).toEqual('../../0021/002156/215675E.pdf#nameddest=15');
  838. expect(docBaseUrlAnnotations[0].url).toEqual('http://www.example.com/0021/002156/215675E.pdf#nameddest=15');
  839. expect(docBaseUrlAnnotations[0].unsafeUrl).toEqual('../../0021/002156/215675E.pdf#nameddest=15');
  840. expect(invalidDocBaseUrlAnnotations[0].url).toBeUndefined();
  841. expect(invalidDocBaseUrlAnnotations[0].unsafeUrl).toEqual('../../0021/002156/215675E.pdf#nameddest=15');
  842. defaultLoadingTask.destroy();
  843. docBaseUrlLoadingTask.destroy();
  844. invalidDocBaseUrlLoadingTask.destroy();
  845. done();
  846. }).catch(function (reason) {
  847. done.fail(reason);
  848. });
  849. });
  850. it('gets text content', function (done) {
  851. var defaultPromise = page.getTextContent();
  852. var parametersPromise = page.getTextContent({
  853. normalizeWhitespace: true,
  854. disableCombineTextItems: true
  855. });
  856. var promises = [defaultPromise, parametersPromise];
  857. Promise.all(promises).then(function (data) {
  858. expect(!!data[0].items).toEqual(true);
  859. expect(data[0].items.length).toEqual(7);
  860. expect(!!data[0].styles).toEqual(true);
  861. expect(JSON.stringify(data[0])).toEqual(JSON.stringify(data[1]));
  862. done();
  863. }).catch(function (reason) {
  864. done.fail(reason);
  865. });
  866. });
  867. it('gets operator list', function (done) {
  868. var promise = page.getOperatorList();
  869. promise.then(function (oplist) {
  870. expect(!!oplist.fnArray).toEqual(true);
  871. expect(!!oplist.argsArray).toEqual(true);
  872. expect(oplist.lastChunk).toEqual(true);
  873. done();
  874. }).catch(function (reason) {
  875. done.fail(reason);
  876. });
  877. });
  878. it('gets stats after parsing page', function (done) {
  879. var promise = page.getOperatorList().then(function () {
  880. return pdfDocument.getStats();
  881. });
  882. var expectedStreamTypes = [];
  883. expectedStreamTypes[StreamType.FLATE] = true;
  884. var expectedFontTypes = [];
  885. expectedFontTypes[FontType.TYPE1] = true;
  886. expectedFontTypes[FontType.CIDFONTTYPE2] = true;
  887. promise.then(function (stats) {
  888. expect(stats).toEqual({
  889. streamTypes: expectedStreamTypes,
  890. fontTypes: expectedFontTypes
  891. });
  892. done();
  893. }).catch(function (reason) {
  894. done.fail(reason);
  895. });
  896. });
  897. it('cancels rendering of page', function (done) {
  898. var viewport = page.getViewport(1);
  899. var canvasAndCtx = CanvasFactory.create(viewport.width, viewport.height);
  900. var renderTask = page.render({
  901. canvasContext: canvasAndCtx.context,
  902. viewport: viewport
  903. });
  904. renderTask.cancel();
  905. renderTask.promise.then(function () {
  906. done.fail('shall cancel rendering');
  907. }).catch(function (error) {
  908. expect(error instanceof RenderingCancelledException).toEqual(true);
  909. expect(error.type).toEqual('canvas');
  910. CanvasFactory.destroy(canvasAndCtx);
  911. done();
  912. });
  913. });
  914. });
  915. describe('Multiple PDFJS instances', function () {
  916. var pdf1 = new URL('../pdfs/tracemonkey.pdf', window.location).href;
  917. var pdf2 = new URL('../pdfs/TAMReview.pdf', window.location).href;
  918. var pdf3 = new URL('../pdfs/issue6068.pdf', window.location).href;
  919. var loadingTasks = [];
  920. var pdfDocuments = [];
  921. function renderPDF(filename) {
  922. var loadingTask = PDFJS.getDocument(filename);
  923. loadingTasks.push(loadingTask);
  924. return loadingTask.promise.then(function (pdf) {
  925. pdfDocuments.push(pdf);
  926. return pdf.getPage(1);
  927. }).then(function (page) {
  928. var viewport = page.getViewport(1.2);
  929. var canvasAndCtx = CanvasFactory.create(viewport.width, viewport.height);
  930. return page.render({
  931. canvasContext: canvasAndCtx.context,
  932. viewport: viewport
  933. }).then(function () {
  934. var data = canvasAndCtx.canvas.toDataURL();
  935. CanvasFactory.destroy(canvasAndCtx);
  936. return data;
  937. });
  938. });
  939. }
  940. afterEach(function (done) {
  941. var destroyPromises = pdfDocuments.map(function (pdfDocument) {
  942. return pdfDocument.destroy();
  943. });
  944. var destroyPromises2 = loadingTasks.map(function (loadingTask) {
  945. return loadingTask.destroy();
  946. });
  947. Promise.all(destroyPromises.concat(destroyPromises2)).then(function () {
  948. done();
  949. });
  950. });
  951. it('should correctly render PDFs in parallel', function (done) {
  952. var baseline1, baseline2, baseline3;
  953. var promiseDone = renderPDF(pdf1).then(function (data1) {
  954. baseline1 = data1;
  955. return renderPDF(pdf2);
  956. }).then(function (data2) {
  957. baseline2 = data2;
  958. return renderPDF(pdf3);
  959. }).then(function (data3) {
  960. baseline3 = data3;
  961. return Promise.all([renderPDF(pdf1), renderPDF(pdf2), renderPDF(pdf3)]);
  962. }).then(function (dataUrls) {
  963. expect(dataUrls[0]).toEqual(baseline1);
  964. expect(dataUrls[1]).toEqual(baseline2);
  965. expect(dataUrls[2]).toEqual(baseline3);
  966. return true;
  967. });
  968. promiseDone.then(function () {
  969. done();
  970. }).catch(function (reason) {
  971. done.fail(reason);
  972. });
  973. });
  974. });
  975. describe('PDFDataRangeTransport', function () {
  976. var pdfPath = new URL('../pdfs/tracemonkey.pdf', window.location).href;
  977. var loadPromise;
  978. function getDocumentData() {
  979. if (loadPromise) {
  980. return loadPromise;
  981. }
  982. loadPromise = new Promise(function (resolve, reject) {
  983. var xhr = new XMLHttpRequest(pdfPath);
  984. xhr.open('GET', pdfPath);
  985. xhr.responseType = 'arraybuffer';
  986. xhr.onload = function () {
  987. resolve(new Uint8Array(xhr.response));
  988. };
  989. xhr.onerror = function () {
  990. reject(new Error('PDF is not loaded'));
  991. };
  992. xhr.send();
  993. });
  994. return loadPromise;
  995. }
  996. it('should fetch document info and page using ranges', function (done) {
  997. var transport;
  998. var initialDataLength = 4000;
  999. var fetches = 0;
  1000. var getDocumentPromise = getDocumentData().then(function (data) {
  1001. var initialData = data.subarray(0, initialDataLength);
  1002. transport = new PDFJS.PDFDataRangeTransport(data.length, initialData);
  1003. transport.requestDataRange = function (begin, end) {
  1004. fetches++;
  1005. waitSome(function () {
  1006. transport.onDataProgress(4000);
  1007. transport.onDataRange(begin, data.subarray(begin, end));
  1008. });
  1009. };
  1010. var loadingTask = PDFJS.getDocument(transport);
  1011. return loadingTask.promise;
  1012. });
  1013. var pdfDocument;
  1014. var getPagePromise = getDocumentPromise.then(function (pdfDocument_) {
  1015. pdfDocument = pdfDocument_;
  1016. var pagePromise = pdfDocument.getPage(10);
  1017. return pagePromise;
  1018. });
  1019. getPagePromise.then(function (page) {
  1020. expect(pdfDocument.numPages).toEqual(14);
  1021. expect(page.rotate).toEqual(0);
  1022. expect(fetches).toBeGreaterThan(2);
  1023. done();
  1024. }).catch(function (reason) {
  1025. done.fail(reason);
  1026. });
  1027. });
  1028. it('should fetch document info and page using range and streaming', function (done) {
  1029. var transport;
  1030. var initialDataLength = 4000;
  1031. var fetches = 0;
  1032. var getDocumentPromise = getDocumentData().then(function (data) {
  1033. var initialData = data.subarray(0, initialDataLength);
  1034. transport = new PDFJS.PDFDataRangeTransport(data.length, initialData);
  1035. transport.requestDataRange = function (begin, end) {
  1036. fetches++;
  1037. if (fetches === 1) {
  1038. transport.onDataProgressiveRead(data.subarray(initialDataLength));
  1039. }
  1040. waitSome(function () {
  1041. transport.onDataRange(begin, data.subarray(begin, end));
  1042. });
  1043. };
  1044. var loadingTask = PDFJS.getDocument(transport);
  1045. return loadingTask.promise;
  1046. });
  1047. var pdfDocument;
  1048. var getPagePromise = getDocumentPromise.then(function (pdfDocument_) {
  1049. pdfDocument = pdfDocument_;
  1050. var pagePromise = pdfDocument.getPage(10);
  1051. return pagePromise;
  1052. });
  1053. getPagePromise.then(function (page) {
  1054. expect(pdfDocument.numPages).toEqual(14);
  1055. expect(page.rotate).toEqual(0);
  1056. expect(fetches).toEqual(1);
  1057. done();
  1058. }).catch(function (reason) {
  1059. done.fail(reason);
  1060. });
  1061. });
  1062. });
  1063. });