From 812bc6795dabfab9fde15af9df3cce0412eac8df Mon Sep 17 00:00:00 2001
From: Piotr Zalewa <piotr@zalewa.info>
Date: Tue, 16 Oct 2012 12:10:37 +0200
Subject: [PATCH] * InvalidPDFException added * Act on throwing an Exception
 and InvalidPDFException by rejecting the worker instead of throwing * changed
 message for all builds * alerting and closing window only for B2G builds *
 invalid_file_error added to l10n (en and pl) * UnknownErrorException added
 and used for every error()

---
 l10n/en-US/viewer.properties |  1 +
 l10n/pl/viewer.properties    |  1 +
 src/api.js                   |  8 ++++++++
 src/obj.js                   |  3 ++-
 src/util.js                  | 25 +++++++++++++++++++++++++
 src/worker.js                | 13 +++++++++++--
 web/viewer.js                | 16 ++++++++++++++--
 7 files changed, 62 insertions(+), 5 deletions(-)

diff --git a/l10n/en-US/viewer.properties b/l10n/en-US/viewer.properties
index a743c32bc..9893317ed 100644
--- a/l10n/en-US/viewer.properties
+++ b/l10n/en-US/viewer.properties
@@ -96,6 +96,7 @@ page_scale_actual=Actual Size
 # Loading indicator messages
 loading_error_indicator=Error
 loading_error=An error occurred while loading the PDF.
+invalid_file_error=Invalid or corrupted PDF file.
 
 # LOCALIZATION NOTE (text_annotation_type): This is used as a tooltip.
 # "{{type}}" will be replaced with an annotation type from a list defined in
diff --git a/l10n/pl/viewer.properties b/l10n/pl/viewer.properties
index 9fbd5e3c1..8408b1f72 100644
--- a/l10n/pl/viewer.properties
+++ b/l10n/pl/viewer.properties
@@ -23,6 +23,7 @@ outline.title=Wyświetl konspekt dokumentu
 loading=Wczytywanie... {{percent}}%
 loading_error_indicator=Błąd
 loading_error=Wystąpił błąd podczas wczytywania pliku PDF.
+invalid_file_error=Błędny lub zepsuty plik PDF.
 rendering_error=Wystąpił błąd podczas wyświetlania strony.
 page_label=Strona:
 page_of=z {{pageCount}}
diff --git a/src/api.js b/src/api.js
index e3f20b859..ebe1d9bca 100644
--- a/src/api.js
+++ b/src/api.js
@@ -539,6 +539,14 @@ var WorkerTransport = (function WorkerTransportClosure() {
         this.workerReadyPromise.reject(data.exception.message, data.exception);
       }, this);
 
+      messageHandler.on('InvalidPDF', function transportInvalidPDF(data) {
+        this.workerReadyPromise.reject(data.exception.name, data.exception);
+      }, this);
+
+      messageHandler.on('UnknownError', function transportUnknownError(data) {
+        this.workerReadyPromise.reject(data.exception.message, data.exception);
+      }, this);
+
       messageHandler.on('GetPage', function transportPage(data) {
         var pageInfo = data.pageInfo;
         var page = new PDFPageProxy(pageInfo, this);
diff --git a/src/obj.js b/src/obj.js
index da4b3248a..5f246f2c9 100644
--- a/src/obj.js
+++ b/src/obj.js
@@ -574,7 +574,8 @@ var XRef = (function XRefClosure() {
       if (dict)
         return dict;
       // nothing helps
-      error('Invalid PDF structure');
+      // calling error() would reject worker with an UnknownErrorException.
+      throw new InvalidPDFException('Invalid PDF structure');
     },
     readXRef: function XRef_readXRef(startXRef, recoveryMode) {
       var stream = this.stream;
diff --git a/src/util.js b/src/util.js
index 21db65d0c..c2f30918d 100644
--- a/src/util.js
+++ b/src/util.js
@@ -148,6 +148,31 @@ var PasswordException = (function PasswordExceptionClosure() {
   return PasswordException;
 })();
 
+var UnknownErrorException = (function UnknownErrorExceptionClosure() {
+  function UnknownErrorException(msg, details) {
+    this.name = 'UnknownErrorException';
+    this.message = msg;
+    this.details = details;
+  }
+
+  UnknownErrorException.prototype = new Error();
+  UnknownErrorException.constructor = UnknownErrorException;
+
+  return UnknownErrorException;
+})();
+
+var InvalidPDFException = (function InvalidPDFExceptionClosure() {
+  function InvalidPDFException(msg) {
+    this.name = 'InvalidPDFException';
+    this.message = msg;
+  }
+
+  InvalidPDFException.prototype = new Error();
+  InvalidPDFException.constructor = InvalidPDFException;
+
+  return InvalidPDFException;
+})();
+
 function bytesToString(bytes) {
   var str = '';
   var length = bytes.length;
diff --git a/src/worker.js b/src/worker.js
index a5b323bf5..5c9ce60c7 100644
--- a/src/worker.js
+++ b/src/worker.js
@@ -124,9 +124,19 @@ var WorkerMessageHandler = {
             });
           }
 
+          return;
+        } else if (e instanceof InvalidPDFException) {
+          handler.send('InvalidPDF', {
+            exception: e
+          });
+
           return;
         } else {
-          throw e;
+          handler.send('UnknownError', {
+            exception: new UnknownErrorException(e.message, e.toString())
+          });
+
+          return;
         }
       }
       var doc = {
@@ -331,4 +341,3 @@ if (typeof window === 'undefined') {
   var handler = new MessageHandler('worker_processor', this);
   WorkerMessageHandler.setup(handler);
 }
-
diff --git a/web/viewer.js b/web/viewer.js
index 7c5ff7b5f..b25c73a51 100644
--- a/web/viewer.js
+++ b/web/viewer.js
@@ -895,14 +895,26 @@ var PDFView = {
           }
         }
 
+        var loadingErrorMessage = mozL10n.get('loading_error', null,
+          'An error occurred while loading the PDF.');
+
+        if (exception && exception.name === 'InvalidPDFException') {
+          // change error message also for other builds
+          var loadingErrorMessage = mozL10n.get('invalid_file_error', null,
+                                        'Invalid or corrupted PDF file.');
+//#if B2G
+//        window.alert(loadingErrorMessage);
+//        return window.close();
+//#endif
+        }
+
         var loadingIndicator = document.getElementById('loading');
         loadingIndicator.textContent = mozL10n.get('loading_error_indicator',
           null, 'Error');
         var moreInfo = {
           message: message
         };
-        self.error(mozL10n.get('loading_error', null,
-          'An error occurred while loading the PDF.'), moreInfo);
+        self.error(loadingErrorMessage, moreInfo);
         self.loading = false;
       },
       function getDocumentProgress(progressData) {