diff --git a/l10n/en-US/viewer.properties b/l10n/en-US/viewer.properties index dadfe4143..c52020c5c 100644 --- a/l10n/en-US/viewer.properties +++ b/l10n/en-US/viewer.properties @@ -146,6 +146,7 @@ loading_error_indicator=Error loading_error=An error occurred while loading the PDF. invalid_file_error=Invalid or corrupted PDF file. missing_file_error=Missing PDF file. +unexpected_response_error=Unexpected server response. # LOCALIZATION NOTE (text_annotation_type.alt): This is used as a tooltip. # "{{type}}" will be replaced with an annotation type from a list defined in diff --git a/src/core/worker.js b/src/core/worker.js index 78a91d317..7dca8f05d 100644 --- a/src/core/worker.js +++ b/src/core/worker.js @@ -14,11 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* globals error, globalScope, InvalidPDFException, info, - MissingPDFException, PasswordException, PDFJS, Promise, - UnknownErrorException, NetworkManager, LocalPdfManager, - NetworkPdfManager, XRefParseException, createPromiseCapability, - isInt, PasswordResponses, MessageHandler, Ref, RANGE_CHUNK_SIZE */ +/* globals PDFJS, createPromiseCapability, LocalPdfManager, NetworkPdfManager, + NetworkManager, isInt, RANGE_CHUNK_SIZE, MissingPDFException, + UnexpectedResponseException, PasswordException, Promise, + PasswordResponses, InvalidPDFException, UnknownErrorException, + XRefParseException, Ref, info, globalScope, error, MessageHandler */ 'use strict'; @@ -141,14 +141,16 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = { }, onError: function onError(status) { + var exception; if (status === 404) { - var exception = new MissingPDFException('Missing PDF "' + - source.url + '".'); - handler.send('MissingPDF', { exception: exception }); + exception = new MissingPDFException('Missing PDF "' + + source.url + '".'); + handler.send('MissingPDF', exception); } else { - handler.send('DocError', 'Unexpected server response (' + - status + ') while retrieving PDF "' + - source.url + '".'); + exception = new UnexpectedResponseException( + 'Unexpected server response (' + status + + ') while retrieving PDF "' + source.url + '".', status); + handler.send('UnexpectedResponse', exception); } }, @@ -200,26 +202,19 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = { var onFailure = function(e) { if (e instanceof PasswordException) { if (e.code === PasswordResponses.NEED_PASSWORD) { - handler.send('NeedPassword', { - exception: e - }); + handler.send('NeedPassword', e); } else if (e.code === PasswordResponses.INCORRECT_PASSWORD) { - handler.send('IncorrectPassword', { - exception: e - }); + handler.send('IncorrectPassword', e); } } else if (e instanceof InvalidPDFException) { - handler.send('InvalidPDF', { - exception: e - }); + handler.send('InvalidPDF', e); } else if (e instanceof MissingPDFException) { - handler.send('MissingPDF', { - exception: e - }); + handler.send('MissingPDF', e); + } else if (e instanceof UnexpectedResponseException) { + handler.send('UnexpectedResponse', e); } else { - handler.send('UnknownError', { - exception: new UnknownErrorException(e.message, e.toString()) - }); + handler.send('UnknownError', + new UnknownErrorException(e.message, e.toString())); } }; diff --git a/src/display/api.js b/src/display/api.js index 9850c0dc8..a8840db98 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -14,11 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* globals CanvasGraphics, combineUrl, createScratchCanvas, error, - FontLoader, globalScope, info, isArrayBuffer, loadJpegStream, - MessageHandler, PDFJS, Promise, StatTimer, warn, - PasswordResponses, Util, loadScript, createPromiseCapability, - FontFace */ +/* globals PDFJS, isArrayBuffer, error, combineUrl, createPromiseCapability, + StatTimer, globalScope, MessageHandler, info, FontLoader, Util, warn, + Promise, PasswordResponses, PasswordException, InvalidPDFException, + MissingPDFException, UnknownErrorException, FontFace, loadJpegStream, + createScratchCanvas, CanvasGraphics, UnexpectedResponseException */ 'use strict'; @@ -865,36 +865,46 @@ var WorkerTransport = (function WorkerTransportClosure() { this.workerReadyCapability.resolve(pdfDocument); }, this); - messageHandler.on('NeedPassword', function transportPassword(data) { + messageHandler.on('NeedPassword', + function transportNeedPassword(exception) { if (this.passwordCallback) { return this.passwordCallback(updatePassword, PasswordResponses.NEED_PASSWORD); } - this.workerReadyCapability.reject(data.exception.message, - data.exception); + this.workerReadyCapability.reject( + new PasswordException(exception.message, exception.code)); }, this); - messageHandler.on('IncorrectPassword', function transportBadPass(data) { + messageHandler.on('IncorrectPassword', + function transportIncorrectPassword(exception) { if (this.passwordCallback) { return this.passwordCallback(updatePassword, PasswordResponses.INCORRECT_PASSWORD); } - this.workerReadyCapability.reject(data.exception.message, - data.exception); + this.workerReadyCapability.reject( + new PasswordException(exception.message, exception.code)); }, this); - messageHandler.on('InvalidPDF', function transportInvalidPDF(data) { - this.workerReadyCapability.reject(data.exception.name, data.exception); + messageHandler.on('InvalidPDF', function transportInvalidPDF(exception) { + this.workerReadyCapability.reject( + new InvalidPDFException(exception.message)); }, this); - messageHandler.on('MissingPDF', function transportMissingPDF(data) { - this.workerReadyCapability.reject(data.exception.message, - data.exception); + messageHandler.on('MissingPDF', function transportMissingPDF(exception) { + this.workerReadyCapability.reject( + new MissingPDFException(exception.message)); }, this); - messageHandler.on('UnknownError', function transportUnknownError(data) { - this.workerReadyCapability.reject(data.exception.message, - data.exception); + messageHandler.on('UnexpectedResponse', + function transportUnexpectedResponse(exception) { + this.workerReadyCapability.reject( + new UnexpectedResponseException(exception.message, exception.status)); + }, this); + + messageHandler.on('UnknownError', + function transportUnknownError(exception) { + this.workerReadyCapability.reject( + new UnknownErrorException(exception.message, exception.details)); }, this); messageHandler.on('DataLoaded', function transportPage(data) { @@ -990,10 +1000,6 @@ var WorkerTransport = (function WorkerTransportClosure() { } }, this); - messageHandler.on('DocError', function transportDocError(data) { - this.workerReadyCapability.reject(data); - }, this); - messageHandler.on('PageError', function transportError(data) { var page = this.pageCache[data.pageNum - 1]; var intentState = page.intentStates[data.intent]; diff --git a/src/shared/util.js b/src/shared/util.js index 201ca3e0f..7deb99175 100644 --- a/src/shared/util.js +++ b/src/shared/util.js @@ -342,6 +342,7 @@ var PasswordException = (function PasswordExceptionClosure() { return PasswordException; })(); +PDFJS.PasswordException = PasswordException; var UnknownErrorException = (function UnknownErrorExceptionClosure() { function UnknownErrorException(msg, details) { @@ -355,6 +356,7 @@ var UnknownErrorException = (function UnknownErrorExceptionClosure() { return UnknownErrorException; })(); +PDFJS.UnknownErrorException = UnknownErrorException; var InvalidPDFException = (function InvalidPDFExceptionClosure() { function InvalidPDFException(msg) { @@ -367,6 +369,7 @@ var InvalidPDFException = (function InvalidPDFExceptionClosure() { return InvalidPDFException; })(); +PDFJS.InvalidPDFException = InvalidPDFException; var MissingPDFException = (function MissingPDFExceptionClosure() { function MissingPDFException(msg) { @@ -379,6 +382,22 @@ var MissingPDFException = (function MissingPDFExceptionClosure() { return MissingPDFException; })(); +PDFJS.MissingPDFException = MissingPDFException; + +var UnexpectedResponseException = + (function UnexpectedResponseExceptionClosure() { + function UnexpectedResponseException(msg, status) { + this.name = 'UnexpectedResponseException'; + this.message = msg; + this.status = status; + } + + UnexpectedResponseException.prototype = new Error(); + UnexpectedResponseException.constructor = UnexpectedResponseException; + + return UnexpectedResponseException; +})(); +PDFJS.UnexpectedResponseException = UnexpectedResponseException; var NotImplementedException = (function NotImplementedExceptionClosure() { function NotImplementedException(msg) { diff --git a/test/unit/api_spec.js b/test/unit/api_spec.js index f82e960d9..c6bf6609e 100644 --- a/test/unit/api_spec.js +++ b/test/unit/api_spec.js @@ -1,14 +1,14 @@ /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ /* globals PDFJS, expect, it, describe, Promise, combineUrl, waitsFor, - isArray */ + isArray, MissingPDFException */ 'use strict'; describe('api', function() { // TODO run with worker enabled var basicApiUrl = combineUrl(window.location.href, '../pdfs/basicapi.pdf'); - function waitsForPromise(promise, successCallback) { + function waitsForPromiseResolved(promise, successCallback) { var data; promise.then(function(val) { data = val; @@ -22,11 +22,25 @@ describe('api', function() { return data !== undefined; }, 20000); } + function waitsForPromiseRejected(promise, failureCallback) { + var data; + promise.then(function(val) { + // Shouldn't get here. + expect(false).toEqual(true); + }, + function(error) { + data = error; + failureCallback(data); + }); + waitsFor(function() { + return data !== undefined; + }, 20000); + } describe('PDFJS', function() { describe('getDocument', function() { it('creates pdf doc from URL', function() { var promise = PDFJS.getDocument(basicApiUrl); - waitsForPromise(promise, function(data) { + waitsForPromiseResolved(promise, function(data) { expect(true).toEqual(true); }); }); @@ -61,16 +75,24 @@ describe('api', function() { expect(typedArrayPdf.length).toEqual(105779); var promise = PDFJS.getDocument(typedArrayPdf); - waitsForPromise(promise, function(data) { + waitsForPromiseResolved(promise, function(data) { expect(true).toEqual(true); }); }); + it('creates pdf doc from non-existent URL', function() { + var nonExistentUrl = combineUrl(window.location.href, + '../pdfs/non-existent.pdf'); + var promise = PDFJS.getDocument(nonExistentUrl); + waitsForPromiseRejected(promise, function(error) { + expect(error instanceof MissingPDFException).toEqual(true); + }); + }); }); }); describe('PDFDocument', function() { var promise = PDFJS.getDocument(basicApiUrl); var doc; - waitsForPromise(promise, function(data) { + waitsForPromiseResolved(promise, function(data) { doc = data; }); it('gets number of pages', function() { @@ -81,7 +103,7 @@ describe('api', function() { }); it('gets page', function() { var promise = doc.getPage(1); - waitsForPromise(promise, function(data) { + waitsForPromiseResolved(promise, function(data) { expect(true).toEqual(true); }); }); @@ -89,32 +111,32 @@ describe('api', function() { // reference to second page var ref = {num: 17, gen: 0}; var promise = doc.getPageIndex(ref); - waitsForPromise(promise, function(pageIndex) { + waitsForPromiseResolved(promise, function(pageIndex) { expect(pageIndex).toEqual(1); }); }); it('gets destinations', function() { var promise = doc.getDestinations(); - waitsForPromise(promise, function(data) { + waitsForPromiseResolved(promise, function(data) { expect(data).toEqual({ chapter1: [{ gen: 0, num: 17 }, { name: 'XYZ' }, 0, 841.89, null] }); }); }); it('gets attachments', function() { var promise = doc.getAttachments(); - waitsForPromise(promise, function (data) { + waitsForPromiseResolved(promise, function (data) { expect(data).toEqual(null); }); }); it('gets javascript', function() { var promise = doc.getJavaScript(); - waitsForPromise(promise, function (data) { + waitsForPromiseResolved(promise, function (data) { expect(data).toEqual([]); }); }); it('gets outline', function() { var promise = doc.getOutline(); - waitsForPromise(promise, function(outline) { + waitsForPromiseResolved(promise, function(outline) { // Two top level entries. expect(outline.length).toEqual(2); // Make sure some basic attributes are set. @@ -125,26 +147,26 @@ describe('api', function() { }); it('gets metadata', function() { var promise = doc.getMetadata(); - waitsForPromise(promise, function(metadata) { + waitsForPromiseResolved(promise, function(metadata) { expect(metadata.info['Title']).toEqual('Basic API Test'); expect(metadata.metadata.get('dc:title')).toEqual('Basic API Test'); }); }); it('gets data', function() { var promise = doc.getData(); - waitsForPromise(promise, function (data) { + waitsForPromiseResolved(promise, function (data) { expect(true).toEqual(true); }); }); it('gets filesize in bytes', function() { var promise = doc.getDownloadInfo(); - waitsForPromise(promise, function (data) { + waitsForPromiseResolved(promise, function (data) { expect(data.length).toEqual(105779); }); }); it('gets stats', function() { var promise = doc.getStats(); - waitsForPromise(promise, function (stats) { + waitsForPromiseResolved(promise, function (stats) { expect(isArray(stats.streamTypes)).toEqual(true); expect(isArray(stats.fontTypes)).toEqual(true); }); @@ -161,7 +183,7 @@ describe('api', function() { }); }); var page; - waitsForPromise(promise, function(data) { + waitsForPromiseResolved(promise, function(data) { page = data; }); it('gets page number', function () { @@ -187,13 +209,13 @@ describe('api', function() { }); it('gets annotations', function () { var promise = page.getAnnotations(); - waitsForPromise(promise, function (data) { + waitsForPromiseResolved(promise, function (data) { expect(data.length).toEqual(4); }); }); it('gets text content', function () { var promise = page.getTextContent(); - waitsForPromise(promise, function (data) { + waitsForPromiseResolved(promise, function (data) { expect(!!data.items).toEqual(true); expect(data.items.length).toEqual(7); expect(!!data.styles).toEqual(true); @@ -201,7 +223,7 @@ describe('api', function() { }); it('gets operator list', function() { var promise = page.getOperatorList(); - waitsForPromise(promise, function (oplist) { + waitsForPromiseResolved(promise, function (oplist) { expect(!!oplist.fnArray).toEqual(true); expect(!!oplist.argsArray).toEqual(true); expect(oplist.lastChunk).toEqual(true); diff --git a/web/viewer.js b/web/viewer.js index ddf3adcc4..ae047c732 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -677,30 +677,27 @@ var PDFView = { self.load(pdfDocument, scale); self.loading = false; }, - function getDocumentError(message, exception) { + function getDocumentError(exception) { + var message = exception && exception.message; var loadingErrorMessage = mozL10n.get('loading_error', null, 'An error occurred while loading the PDF.'); - if (exception && exception.name === 'InvalidPDFException') { + if (exception instanceof PDFJS.InvalidPDFException) { // change error message also for other builds loadingErrorMessage = mozL10n.get('invalid_file_error', null, - 'Invalid or corrupted PDF file.'); -//#if B2G -// window.alert(loadingErrorMessage); -// return window.close(); -//#endif - } - - if (exception && exception.name === 'MissingPDFException') { + 'Invalid or corrupted PDF file.'); + } else if (exception instanceof PDFJS.MissingPDFException) { // special message for missing PDF's loadingErrorMessage = mozL10n.get('missing_file_error', null, - 'Missing PDF file.'); - -//#if B2G -// window.alert(loadingErrorMessage); -// return window.close(); -//#endif + 'Missing PDF file.'); + } else if (exception instanceof PDFJS.UnexpectedResponseException) { + loadingErrorMessage = mozL10n.get('unexpected_response_error', null, + 'Unexpected server response.'); } +//#if B2G +// window.alert(loadingErrorMessage); +// return window.close(); +//#endif var moreInfo = { message: message