diff --git a/extensions/firefox/components/PdfStreamConverter.js b/extensions/firefox/components/PdfStreamConverter.js
index 84430a658..c89731b59 100644
--- a/extensions/firefox/components/PdfStreamConverter.js
+++ b/extensions/firefox/components/PdfStreamConverter.js
@@ -206,6 +206,10 @@ ChromeActions.prototype = {
// The data may not be downloaded so we need just retry getting the pdf with
// the original url.
var originalUri = NetUtil.newURI(data.originalUrl);
+ var filename = data.filename;
+ if (typeof filename !== 'string' || !/\.pdf$/i.test(filename)) {
+ filename = 'document.pdf';
+ }
var blobUri = data.blobUrl ? NetUtil.newURI(data.blobUrl) : originalUri;
var extHelperAppSvc =
Cc['@mozilla.org/uriloader/external-helper-app-service;1'].
@@ -234,7 +238,9 @@ ChromeActions.prototype = {
// contentDisposition/contentDispositionFilename is readonly before FF18
channel.contentDisposition = Ci.nsIChannel.DISPOSITION_ATTACHMENT;
if (self.contentDispositionFilename) {
- channel.contentDispositionFilename = self.contentDispositionFilename;
+ channel.contentDispositionFilename = self.contentDispositionFilename;
+ } else {
+ channel.contentDispositionFilename = filename;
}
} catch (e) {}
channel.setURI(originalUri);
diff --git a/web/compatibility.js b/web/compatibility.js
index e9b69ed07..0d12c64a9 100644
--- a/web/compatibility.js
+++ b/web/compatibility.js
@@ -92,6 +92,13 @@ if (typeof PDFJS === 'undefined') {
window.Float64Array = TypedArray;
})();
+// URL = URL || webkitURL
+(function normalizeURLObject() {
+ if (!window.URL && window.webkitURL) {
+ window.URL = window.webkitURL;
+ }
+})();
+
// Object.create() ?
(function checkObjectCreateCompatibility() {
if (typeof Object.create !== 'undefined')
diff --git a/web/viewer.js b/web/viewer.js
index 9ac2f5a95..a21cde03a 100644
--- a/web/viewer.js
+++ b/web/viewer.js
@@ -14,6 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+/* globals URL*/
/* globals PDFJS, PDFBug, FirefoxCom, Stats, Cache, PDFFindBar */
/* globals PDFFindController, ProgressBar, getFileName, CustomStyle */
/* globals getOutputScale, TextLayerBuilder */
@@ -914,60 +915,86 @@ var PDFView = {
},
download: function pdfViewDownload() {
- function noData() {
- FirefoxCom.request('download', { originalUrl: url });
- }
var url = this.url.split('#')[0];
+ function getPDFFileNameFromURL(url) {
+ var reURI = /^(?:([^:]+:)?\/\/[^\/]+)?([^?#]*)(\?[^#]*)?(#.*)?$/;
+ // SCHEME HOST 1.PATH 2.QUERY 3.REF
+ // Pattern to get last matching NAME.pdf
+ var reFilename = /[^\/?#=]+\.pdf\b(?!.*\.pdf\b)/i;
+ var splitURI = reURI.exec(url);
+ var suggestedFilename = reFilename.exec(splitURI[1]) ||
+ reFilename.exec(splitURI[2]) ||
+ reFilename.exec(splitURI[3]);
+ if (suggestedFilename) {
+ suggestedFilename = suggestedFilename[0];
+ if (suggestedFilename.indexOf('%') != -1) {
+ // URL-encoded %2Fpath%2Fto%2Ffile.pdf should be file.pdf
+ try {
+ suggestedFilename =
+ reFilename.exec(decodeURIComponent(suggestedFilename))[0];
+ } catch(e) { // Possible (extremely rare) errors:
+ // URIError "Malformed URI", e.g. for "%AA.pdf"
+ // TypeError "null has no properties", e.g. for "%2F.pdf"
+ }
+ }
+ }
+ return suggestedFilename || 'document.pdf';
+ }
//#if !(FIREFOX || MOZCENTRAL)
+ function noData() {
+ triggerSaveAs(url + '#pdfjs.action=download');
+ }
+ function triggerSaveAs(url, blobUrl) {
+ // If blobUrl is not specified, fall back to non-blob url.
+ if (!blobUrl) blobUrl = url;
- var a = document.createElement('a');
-
- // If _parent == self, then opening an identical URL with different
- // location hash will only cause a navigation, not a download.
- if (window.top === window && !('download' in a) &&
- url === window.location.href.split('#')[0]) {
- url += url.indexOf('?') === -1 ? '?' : '&';
- }
-
- url += '#pdfjs.action=download';
- if (a.click) {
- // Use a.click() if available. Otherwise, Chrome might show
- // "Unsafe JavaScript attempt to initiate a navigation change
- // for frame with URL" and not open the PDF at all.
- // Supported by (not mentioned = untested):
- // - Firefox 6 - 19 (4- does not support a.click, 5 ignores a.click)
- // - Chrome 19 - 26 (18- does not support a.click)
- // - Opera 9 - 12.15
- // - Internet Explorer 6 - 10
- // - Safari 6 (5.1- does not support a.click)
- a.href = url;
- a.target = '_parent';
- // Use a.download if available. This increases the likelihood that
- // the file is downloaded instead of opened by another PDF plugin.
- if ('download' in a) {
- var filename = url.match(/([^\/?#=]+\.pdf)/i);
- a.download = filename ? filename[1] : 'file.pdf';
+ var a = document.createElement('a');
+ if (a.click) {
+ // Use a.click() if available. Otherwise, Chrome might show
+ // "Unsafe JavaScript attempt to initiate a navigation change
+ // for frame with URL" and not open the PDF at all.
+ // Supported by (not mentioned = untested):
+ // - Firefox 6 - 19 (4- does not support a.click, 5 ignores a.click)
+ // - Chrome 19 - 26 (18- does not support a.click)
+ // - Opera 9 - 12.15
+ // - Internet Explorer 6 - 10
+ // - Safari 6 (5.1- does not support a.click)
+ a.href = blobUrl;
+ a.target = '_parent';
+ // Use a.download if available. This increases the likelihood that
+ // the file is downloaded instead of opened by another PDF plugin.
+ if ('download' in a) {
+ a.download = getPDFFileNameFromURL(url);
+ }
+ // must be in the document for IE and recent Firefox versions.
+ // (otherwise .click() is ignored)
+ (document.body || document.documentElement).appendChild(a);
+ a.click();
+ a.parentNode.removeChild(a);
+ } else {
+ if (window.top === window &&
+ blobUrl.split('#')[0] === window.location.href.split('#')[0]) {
+ // If _parent == self, then opening an identical URL with different
+ // location hash will only cause a navigation, not a download.
+ var padCharacter = blobUrl.indexOf('?') === -1 ? '?' : '&';
+ blobUrl = blobUrl.replace(/#|$/, padCharacter + '$&');
+ }
+ window.open(blobUrl, '_parent');
}
- // must be in the document for IE and recent Firefox versions.
- // (otherwise .click() is ignored)
- (document.body || document.documentElement).appendChild(a);
- a.click();
- a.parentNode.removeChild(a);
- } else {
- window.open(url, '_parent');
}
//#else
-// // Document isn't ready just try to download with the url.
-// if (!this.pdfDocument) {
-// noData();
-// return;
+// function noData() {
+// FirefoxCom.request('download', {
+// originalUrl: url,
+// filename: getPDFFileNameFromURL(url)
+// });
// }
-// this.pdfDocument.getData().then(
-// function getDataSuccess(data) {
-// var blob = PDFJS.createBlob(data.buffer, 'application/pdf');
-// var blobUrl = window.URL.createObjectURL(blob);
-//
-// FirefoxCom.request('download', { blobUrl: blobUrl, originalUrl: url },
+// function triggerSaveAs(url, blobUrl) {
+// FirefoxCom.request('download', {
+// blobUrl: blobUrl,
+// originalUrl: url,
+// filename: getPDFFileNameFromURL(url)
+// },
// function response(err) {
// if (err) {
// // This error won't really be helpful because it's likely the
@@ -977,10 +1004,31 @@ var PDFView = {
// window.URL.revokeObjectURL(blobUrl);
// }
// );
-// },
-// noData // Error occurred try downloading with just the url.
-// );
+// }
//#endif
+ // If the PDF is not ready yet, or if URL.createObjectURL is not supported,
+ // just try to download with the url.
+ if (!this.pdfDocument || !URL) {
+ noData();
+ return;
+ }
+ this.pdfDocument.getData().then(
+ function getDataSuccess(data) {
+ var blob = PDFJS.createBlob(data.buffer, 'application/pdf');
+//#if GENERIC
+ if (navigator.msSaveBlob) {
+ // IE10 / IE11
+ if (!navigator.msSaveBlob(blob, getPDFFileNameFromURL(url))) {
+ noData();
+ }
+ return;
+ }
+//#endif
+ var blobUrl = URL.createObjectURL(blob);
+ triggerSaveAs(url, blobUrl);
+ },
+ noData // Error occurred try downloading with just the url.
+ ).then(null, noData);
},
fallback: function pdfViewFallback() {