api_spec.js 36 KB

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