diff --git a/extensions/firefox/components/PdfStreamConverter.js b/extensions/firefox/components/PdfStreamConverter.js
index 9e5dcbe61..8980fccc5 100644
--- a/extensions/firefox/components/PdfStreamConverter.js
+++ b/extensions/firefox/components/PdfStreamConverter.js
@@ -128,37 +128,58 @@ function ChromeActions(domWindow) {
}
ChromeActions.prototype = {
- download: function(data) {
- var handlerInfo = Svc.mime
- .getFromTypeAndExtension('application/pdf', 'pdf');
- var uri = NetUtil.newURI(data);
-
+ download: function(data, sendResponse) {
+ var originalUrl = data.originalUrl;
+ // The data may not be downloaded so we need just retry getting the pdf with
+ // the original url.
+ var blobUrl = data.blobUrl || originalUrl;
+ var originalUri = NetUtil.newURI(originalUrl);
+ var blobUri = NetUtil.newURI(blobUrl);
var extHelperAppSvc =
Cc['@mozilla.org/uriloader/external-helper-app-service;1'].
- getService(Ci.nsIExternalHelperAppService);
+ getService(Ci.nsIExternalHelperAppService);
var frontWindow = Cc['@mozilla.org/embedcomp/window-watcher;1'].
- getService(Ci.nsIWindowWatcher).activeWindow;
+ getService(Ci.nsIWindowWatcher).activeWindow;
var ioService = Services.io;
- var channel = ioService.newChannel(data, null, null);
- var listener = {
- extListener: null,
- onStartRequest: function(aRequest, aContext) {
- this.extListener = extHelperAppSvc.doContent('application/pdf',
- aRequest, frontWindow, false);
- this.extListener.onStartRequest(aRequest, aContext);
- },
- onStopRequest: function(aRequest, aContext, aStatusCode) {
- if (this.extListener)
- this.extListener.onStopRequest(aRequest, aContext, aStatusCode);
- },
- onDataAvailable: function(aRequest, aContext, aInputStream, aOffset,
- aCount) {
- this.extListener.onDataAvailable(aRequest, aContext, aInputStream,
- aOffset, aCount);
- }
- };
+ var channel = ioService.newChannel(originalUrl, null, null);
- channel.asyncOpen(listener, null);
+ NetUtil.asyncFetch(blobUri, function(aInputStream, aResult) {
+ if (!Components.isSuccessCode(aResult)) {
+ if (sendResponse)
+ sendResponse(true);
+ return;
+ }
+ // Create a nsIInputStreamChannel so we can set the url on the channel
+ // so the filename will be correct.
+ let channel = Cc['@mozilla.org/network/input-stream-channel;1'].
+ createInstance(Ci.nsIInputStreamChannel);
+ channel.setURI(originalUri);
+ channel.contentStream = aInputStream;
+ channel.QueryInterface(Ci.nsIChannel);
+
+ var listener = {
+ extListener: null,
+ onStartRequest: function(aRequest, aContext) {
+ this.extListener = extHelperAppSvc.doContent('application/pdf',
+ aRequest, frontWindow, false);
+ this.extListener.onStartRequest(aRequest, aContext);
+ },
+ onStopRequest: function(aRequest, aContext, aStatusCode) {
+ if (this.extListener)
+ this.extListener.onStopRequest(aRequest, aContext, aStatusCode);
+ // Notify the content code we're done downloading.
+ if (sendResponse)
+ sendResponse(false);
+ },
+ onDataAvailable: function(aRequest, aContext, aInputStream, aOffset,
+ aCount) {
+ this.extListener.onDataAvailable(aRequest, aContext, aInputStream,
+ aOffset, aCount);
+ }
+ };
+
+ channel.asyncOpen(listener, null);
+ });
},
setDatabase: function(data) {
if (inPrivateBrowsing)
@@ -222,20 +243,38 @@ ChromeActions.prototype = {
function RequestListener(actions) {
this.actions = actions;
}
-// Receive an event and synchronously responds.
+// Receive an event and synchronously or asynchronously responds.
RequestListener.prototype.receive = function(event) {
var message = event.target;
+ var doc = message.ownerDocument;
var action = message.getUserData('action');
var data = message.getUserData('data');
+ var sync = message.getUserData('sync');
var actions = this.actions;
if (!(action in actions)) {
log('Unknown action: ' + action);
return;
}
- var response = actions[action].call(this.actions, data);
- message.setUserData('response', response, null);
-};
+ if (sync) {
+ var response = actions[action].call(this.actions, data);
+ message.setUserData('response', response, null);
+ } else {
+ var response;
+ if (!message.getUserData('callback')) {
+ doc.documentElement.removeChild(message);
+ response = null;
+ } else {
+ response = function sendResponse(response) {
+ message.setUserData('response', response, null);
+ var listener = doc.createEvent('HTMLEvents');
+ listener.initEvent('pdf.js.response', true, false);
+ return message.dispatchEvent(listener);
+ }
+ }
+ actions[action].call(this.actions, data, response);
+ }
+};
function PdfStreamConverter() {
}
diff --git a/extensions/firefox/tools/l10n.js b/extensions/firefox/tools/l10n.js
index b16636e31..df20ff577 100644
--- a/extensions/firefox/tools/l10n.js
+++ b/extensions/firefox/tools/l10n.js
@@ -9,7 +9,7 @@
// fetch an l10n objects
function getL10nData(key) {
- var response = FirefoxCom.request('getStrings', key);
+ var response = FirefoxCom.requestSync('getStrings', key);
var data = JSON.parse(response);
if (!data)
console.warn('[l10n] #' + key + ' missing for [' + gLanguage + ']');
@@ -78,7 +78,7 @@
}
window.addEventListener('DOMContentLoaded', function() {
- gLanguage = FirefoxCom.request('getLocale', null);
+ gLanguage = FirefoxCom.requestSync('getLocale', null);
translateFragment();
diff --git a/l10n/en-US/chrome.properties b/l10n/en-US/chrome.properties
index 467d5920b..1885e6036 100644
--- a/l10n/en-US/chrome.properties
+++ b/l10n/en-US/chrome.properties
@@ -1,2 +1,3 @@
+# Chrome notification bar messages and buttons
unsupported_feature=This PDF document might not be displayed correctly.
open_with_different_viewer=Open With Different Viewer
diff --git a/l10n/en-US/viewer.properties b/l10n/en-US/viewer.properties
index 4ac776da2..25abd9275 100644
--- a/l10n/en-US/viewer.properties
+++ b/l10n/en-US/viewer.properties
@@ -1,10 +1,46 @@
-bookmark.title=Current view (copy or open in new window)
+# Main toolbar buttons (tooltips and alt text for images)
previous.title=Previous Page
+previous_label=Previous
next.title=Next Page
-print.title=Print
-download.title=Download
+next_label=Next
+page_label=Page:
+page_of=of {{pageCount}}
zoom_out.title=Zoom Out
+zoom_out_label=Zoom Out
zoom_in.title=Zoom In
+zoom_in_label=Zoom In
+zoom.title=Zoom
+print.title=Print
+print_label=Print
+open_file.title=Open File
+open_file_label=Open
+download.title=Download
+download_label=Download
+bookmark.title=Current view (copy or open in new window)
+bookmark_label=Current View
+
+# Side panel toolbar buttons (tooltips and alt text for images)
+toggle_slider.title=Toggle Slider
+toggle_slider_label=Toggle Slider
+outline.title=Show Document Outline
+outline_label=Document Outline
+thumbs.title=Show Thumbnails
+thumbs_label=Thumbnails
+search_panel.title=Search Document
+search_panel_label=Search
+
+# Document outline messages
+no_outline=No Outline Available
+
+# Thumbnails panel item (tooltip and alt text for images)
+thumb_page_title=Page {{page}}
+thumb_page_canvas=Thumbnail of Page {{page}}
+
+# Search panel button title and messages
+search=Find
+search_terms_not_found=(Not found)
+
+# Error panel labels
error_more_info=More Information
error_less_info=Less Information
error_close=Close
@@ -13,38 +49,19 @@ error_message=Message: {{message}}
error_stack=Stack: {{stack}}
error_file=File: {{file}}
error_line=Line: {{line}}
+rendering_error=An error occurred while rendering the page.
+
+# Predefined zoom values
page_scale_width=Page Width
page_scale_fit=Page Fit
page_scale_auto=Automatic Zoom
page_scale_actual=Actual Size
-toggle_slider.title=Toggle Slider
-thumbs.title=Show Thumbnails
-outline.title=Show Document Outline
+
+# Loading indicator messages
loading=Loading... {{percent}}%
loading_error_indicator=Error
loading_error=An error occurred while loading the PDF.
-rendering_error=An error occurred while rendering the page.
-page_label=Page:
-page_of=of {{pageCount}}
-no_outline=No Outline Available
-open_file.title=Open File
-text_annotation_type=[{{type}} Annotation]
-toggle_slider_label=Toggle Slider
-thumbs_label=Thumbnails
-outline_label=Document Outline
-bookmark_label=Current View
-previous_label=Previous
-next_label=Next
-print_label=Print
-download_label=Download
-zoom_out_label=Zoom Out
-zoom_in_label=Zoom In
-zoom.title=Zoom
-thumb_page_title=Page {{page}}
-thumb_page_canvas=Thumbnail of Page {{page}}
-request_password=PDF is protected by a password:
-open_file_label=Open
-search.title=Search Document
-search_label=Search
-search_button=Find
+# Misc labels and messages
+text_annotation_type=[{{type}} Annotation]
+request_password=PDF is protected by a password:
diff --git a/l10n/xx/viewer.properties b/l10n/xx/viewer.properties
deleted file mode 100644
index e26f79422..000000000
--- a/l10n/xx/viewer.properties
+++ /dev/null
@@ -1,44 +0,0 @@
-bookmark.title=<<<_¢ȗггεпţ ṿiεẂ (¢OÞӳ Oг OÞεп iп пεẂ ẂiпÐOẂ)_>>>
-previous.title=<<<_ÞгεṿiOȗ§ Þãģε_>>>
-next.title=<<<_пεӾţ Þãģε_>>>
-print.title=<<<_Þгiпţ_>>>
-download.title=<<<_ÐOẂпḻOãÐ_>>>
-zoom_out.title=<<<_ƩOOм Oȗţ_>>>
-zoom_in.title=<<<_ƩOOм iп_>>>
-error_more_info=<<<_мOгε iп£OгмãţiOп_>>>
-error_less_info=<<<_ḻ姧 iп£OгмãţiOп_>>>
-error_close=<<<_¢ḻO§ε_>>>
-error_build=<<<_ÞУ.ʃ§ ьȗiḻÐ: {{build}}_>>>
-error_message=<<<_м姧ãģε: {{message}}_>>>
-error_stack=<<<_§ţã¢қ: {{stack}}_>>>
-error_file=<<<_£iḻε: {{file}}_>>>
-error_line=<<<_ḻiпε: {{line}}_>>>
-page_scale_width=<<<_Þãģε ẂiÐţН_>>>
-page_scale_fit=<<<_Þãģε £iţ_>>>
-page_scale_auto=<<<_ãȗţOмãţi¢ ƩOOм_>>>
-page_scale_actual=<<<_ã¢ţȗãḻ §iƩε_>>>
-toggle_slider.title=<<<_ţOģģḻε §ḻiÐεг_>>>
-thumbs.title=<<<_§НOẂ ţНȗмьпãiḻ§_>>>
-outline.title=<<<_§НOẂ ÐO¢ȗмεпţ Oȗţḻiпε_>>>
-loading=<<<_ḻOãÐiпģ... {{percent}}%_>>>
-loading_error_indicator=<<<_εггOг_>>>
-loading_error=<<<_ãп εггOг O¢¢ȗггεÐ ẂНiḻε ḻOãÐiпģ ţНε ÞУ._>>>
-rendering_error=<<<_ãп εггOг O¢¢ȗггεÐ ẂНiḻε гεпÐεгiпģ ţНε Þãģε._>>>
-page_label=Þãģε:
-page_of=<<<_O£ {{pageCount}}_>>>
-no_outline=<<<_пO Oȗţḻiпε ãṿãiḻãьḻε_>>>
-open_file.title=<<<_OÞεп £iḻε_>>>
-text_annotation_type=<<<_[{{type}} ãппOţãţiOп]_>>>
-toggle_slider_label=<<<_ţOģģḻε §ḻiÐεг_>>>
-thumbs_label=<<<_ţНȗмьпãiḻ§_>>>
-outline_label=<<<_ÐO¢ȗмεпţ Oȗţḻiпε_>>>
-bookmark_label=<<<_¢ȗггεпţ ṿiεẂ_>>>
-previous_label=<<<_ÞгεṿiOȗ§_>>>
-next_label=<<<_пεӾţ_>>>
-print_label=<<<_Þгiпţ_>>>
-download_label=<<<_ÐOẂпḻOãÐ_>>>
-zoom_out_label=<<<_ƩOOм Oȗţ_>>>
-zoom_in_label=<<<_ƩOOм iп_>>>
-zoom.title=<<<_ƩOOм_>>>
-thumb_page_title=<<<_Þãģε {{page}}_>>>
-thumb_page_canvas=<<<_ţНȗмьпãiḻ O£ Þãģε {{page}}_>>>
diff --git a/l10n/zh-TW/chrome.properties b/l10n/zh-TW/chrome.properties
new file mode 100644
index 000000000..92bb92dfe
--- /dev/null
+++ b/l10n/zh-TW/chrome.properties
@@ -0,0 +1,2 @@
+unsupported_feature=本 PDF 文件可能無法正常顯示。
+open_with_different_viewer=使用其他檢視器打開文件
diff --git a/l10n/zh-TW/viewer.properties b/l10n/zh-TW/viewer.properties
index 0f2182594..8a34b65a5 100644
--- a/l10n/zh-TW/viewer.properties
+++ b/l10n/zh-TW/viewer.properties
@@ -24,8 +24,8 @@ loading=正在載入... {{percent}}%
loading_error_indicator=錯誤
loading_error=載入PDF檔案時發生錯誤。
rendering_error=渲染頁面時發生錯誤。
-page_label=頁次:
-page_of=, 共 {{pageCount}} 頁
+page_label=第
+page_of=頁, 共 {{pageCount}} 頁
no_outline=無可用的綱要
open_file.title=開啟檔案
text_annotation_type=[{{type}} 註解]
@@ -43,3 +43,7 @@ zoom.title=縮放
thumb_page_title=第 {{page}} 頁
thumb_page_canvas=第 {{page}} 頁的縮圖
request_password=PDF 檔案受密碼保護:
+open_file_label=開啟
+search.title=搜索文件
+search_label=搜索
+search_button=尋找
diff --git a/src/api.js b/src/api.js
index 59f9661bf..7d65f96b4 100644
--- a/src/api.js
+++ b/src/api.js
@@ -151,6 +151,15 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
promise.resolve(this.pdfInfo.encrypted);
return promise;
},
+ /**
+ * @return {Promise} A promise that is resolved with a TypedArray that has
+ * the raw data from the PDF.
+ */
+ getData: function PDFDocumentProxy_getData() {
+ var promise = new PDFJS.Promise();
+ this.transport.getData(promise);
+ return promise;
+ },
destroy: function PDFDocumentProxy_destroy() {
this.transport.destroy();
}
@@ -616,6 +625,12 @@ var WorkerTransport = (function WorkerTransportClosure() {
this.messageHandler.send('GetDocRequest', {data: data, params: params});
},
+ getData: function WorkerTransport_sendData(promise) {
+ this.messageHandler.send('GetData', null, function(data) {
+ promise.resolve(data);
+ });
+ },
+
getPage: function WorkerTransport_getPage(pageNumber, promise) {
var pageIndex = pageNumber - 1;
if (pageIndex in this.pagePromises)
diff --git a/src/worker.js b/src/worker.js
index a93c36e95..c1dfa79af 100644
--- a/src/worker.js
+++ b/src/worker.js
@@ -136,6 +136,10 @@ var WorkerMessageHandler = {
handler.send('GetPage', {pageInfo: page});
});
+ handler.on('GetData', function wphSetupGetData(data, promise) {
+ promise.resolve(pdfModel.stream.bytes);
+ });
+
handler.on('GetAnnotationsRequest', function wphSetupGetAnnotations(data) {
var pdfPage = pdfModel.getPage(data.pageIndex + 1);
handler.send('GetAnnotations', {
diff --git a/web/viewer.html b/web/viewer.html
index 087fb7af3..56522478e 100644
--- a/web/viewer.html
+++ b/web/viewer.html
@@ -51,8 +51,8 @@
-