2
0

api_spec.js 40 KB

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