From 7e63ad5937e77980fe19f2d58857696982ecd938 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Fri, 13 Jul 2012 16:25:50 -0700 Subject: [PATCH] Bug 773422 - Update pdf.js to version 0.3.452. r=Mossop --- browser/extensions/pdfjs/README.mozilla | 2 +- browser/extensions/pdfjs/bootstrap.js | 111 -- .../pdfjs/components/PdfStreamConverter.js | 119 +- .../web/images/toolbarButton-openFile.png | Bin 708 -> 417 bytes browser/extensions/pdfjs/content/web/l10n.js | 4 +- .../extensions/pdfjs/content/web/viewer.css | 340 ++-- .../extensions/pdfjs/content/web/viewer.html | 1364 ++++++++++++++++- .../extensions/pdfjs/content/web/viewer.js | 577 ++++--- browser/extensions/pdfjs/install.rdf.in | 27 - .../locales/en-US/pdfviewer/chrome.properties | 1 + .../locales/en-US/pdfviewer/viewer.properties | 6 +- 11 files changed, 2030 insertions(+), 521 deletions(-) delete mode 100644 browser/extensions/pdfjs/bootstrap.js delete mode 100644 browser/extensions/pdfjs/install.rdf.in diff --git a/browser/extensions/pdfjs/README.mozilla b/browser/extensions/pdfjs/README.mozilla index 7e2fb644616a..6e2882e3f94b 100644 --- a/browser/extensions/pdfjs/README.mozilla +++ b/browser/extensions/pdfjs/README.mozilla @@ -1,4 +1,4 @@ This is the pdf.js project output, https://github.com/mozilla/pdf.js -Current extension version is: 0.3.345 +Current extension version is: 0.3.452 diff --git a/browser/extensions/pdfjs/bootstrap.js b/browser/extensions/pdfjs/bootstrap.js deleted file mode 100644 index 5bf66d444c00..000000000000 --- a/browser/extensions/pdfjs/bootstrap.js +++ /dev/null @@ -1,111 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ - -'use strict'; - -const RESOURCE_NAME = 'pdf.js'; -const EXT_PREFIX = 'extensions.uriloader@pdf.js'; - -let Cc = Components.classes; -let Ci = Components.interfaces; -let Cm = Components.manager; -let Cu = Components.utils; - -Cu.import('resource://gre/modules/Services.jsm'); - -function getBoolPref(pref, def) { - try { - return Services.prefs.getBoolPref(pref); - } catch (ex) { - return def; - } -} - -function setStringPref(pref, value) { - let str = Cc['@mozilla.org/supports-string;1'] - .createInstance(Ci.nsISupportsString); - str.data = value; - Services.prefs.setComplexValue(pref, Ci.nsISupportsString, str); -} - -function log(str) { - if (!getBoolPref(EXT_PREFIX + '.pdfBugEnabled', false)) - return; - dump(str + '\n'); -} - -// Register/unregister a class as a component. -let Factory = { - registrar: null, - aClass: null, - register: function(aClass) { - if (this.aClass) { - log('Cannot register more than one class'); - return; - } - this.registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar); - this.aClass = aClass; - var proto = aClass.prototype; - this.registrar.registerFactory(proto.classID, proto.classDescription, - proto.contractID, this); - }, - unregister: function() { - if (!this.aClass) { - log('Class was never registered.'); - return; - } - var proto = this.aClass.prototype; - this.registrar.unregisterFactory(proto.classID, this); - this.aClass = null; - }, - // nsIFactory::createInstance - createInstance: function(outer, iid) { - if (outer !== null) - throw Cr.NS_ERROR_NO_AGGREGATION; - return (new (this.aClass)).QueryInterface(iid); - } -}; - -let pdfStreamConverterUrl = null; - -// As of Firefox 13 bootstrapped add-ons don't support automatic registering and -// unregistering of resource urls and components/contracts. Until then we do -// it programatically. See ManifestDirective ManifestParser.cpp for support. - -function startup(aData, aReason) { - // Setup the resource url. - var ioService = Services.io; - var resProt = ioService.getProtocolHandler('resource') - .QueryInterface(Ci.nsIResProtocolHandler); - var aliasURI = ioService.newURI('content/', 'UTF-8', aData.resourceURI); - resProt.setSubstitution(RESOURCE_NAME, aliasURI); - - // Load the component and register it. - pdfStreamConverterUrl = aData.resourceURI.spec + - 'components/PdfStreamConverter.js'; - Cu.import(pdfStreamConverterUrl); - Factory.register(PdfStreamConverter); -} - -function shutdown(aData, aReason) { - if (aReason == APP_SHUTDOWN) - return; - var ioService = Services.io; - var resProt = ioService.getProtocolHandler('resource') - .QueryInterface(Ci.nsIResProtocolHandler); - // Remove the resource url. - resProt.setSubstitution(RESOURCE_NAME, null); - // Remove the contract/component. - Factory.unregister(); - // Unload the converter - Cu.unload(pdfStreamConverterUrl); - pdfStreamConverterUrl = null; -} - -function install(aData, aReason) { -} - -function uninstall(aData, aReason) { - setStringPref(EXT_PREFIX + '.database', '{}'); -} - diff --git a/browser/extensions/pdfjs/components/PdfStreamConverter.js b/browser/extensions/pdfjs/components/PdfStreamConverter.js index 857c85a8a6e1..2f55b4365521 100644 --- a/browser/extensions/pdfjs/components/PdfStreamConverter.js +++ b/browser/extensions/pdfjs/components/PdfStreamConverter.js @@ -128,37 +128,55 @@ 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 originalUri = NetUtil.newURI(data.originalUrl); + var blobUri = data.blobUrl ? NetUtil.newURI(data.blobUrl) : originalUri; 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; - 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); - } - }; + getService(Ci.nsIWindowWatcher).activeWindow; - 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) @@ -195,7 +213,7 @@ ChromeActions.prototype = { searchEnabled: function() { return getBoolPref(PREF_PREFIX + '.searchEnabled', false); }, - fallback: function(url) { + fallback: function(url, sendResponse) { var self = this; var domWindow = this.domWindow; var strings = getLocalizedStrings('chrome.properties'); @@ -204,17 +222,32 @@ ChromeActions.prototype = { var win = Services.wm.getMostRecentWindow('navigator:browser'); var browser = win.gBrowser.getBrowserForDocument(domWindow.top.document); var notificationBox = win.gBrowser.getNotificationBox(browser); + // Flag so we don't call the response callback twice, since if the user + // clicks open with different viewer both the button callback and + // eventCallback will be called. + var sentResponse = false; var buttons = [{ label: getLocalizedString(strings, 'open_with_different_viewer'), accessKey: getLocalizedString(strings, 'open_with_different_viewer', 'accessKey'), callback: function() { - self.download(url); + sentResponse = true; + sendResponse(true); } }]; notificationBox.appendNotification(message, 'pdfjs-fallback', null, notificationBox.PRIORITY_WARNING_LOW, - buttons); + buttons, + function eventsCallback(eventType) { + // Currently there is only one event "removed" but if there are any other + // added in the future we still only care about removed at the moment. + if (eventType !== 'removed') + return; + // Don't send a response again if we already responded when the button was + // clicked. + if (!sentResponse) + sendResponse(false); + }); } }; @@ -222,20 +255,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/browser/extensions/pdfjs/content/web/images/toolbarButton-openFile.png b/browser/extensions/pdfjs/content/web/images/toolbarButton-openFile.png index 12ce45f876b12eef3e5030b492d58d5fbb47ebbf..fc7023f2aafcdbb3b2412934c017225637c8bb9e 100644 GIT binary patch delta 392 zcmV;30eAky1)&3wBYy#CNklY`u@r0Pg5(gIt zKS4o}g1A}g%jhT};$T7OAPy;H>flra2St?bnbSZL$Y+TEgF85m2n7#*aQD1j5<>Dk z{}-_qVGT5BavG17$sDU1MbRrJ{zyK9Ab6?OYC6B5c=6<(=YM%$j^lg_uIo;H-=9t< zlSkxtp{YKd7+ej*aEu$@{_qYTs@ZHdX1zdk1V->IOVe~{S=O~}+x;xdhH4&0tQQEy z;Yk+9@qki#irfZlnx@%Jl4PLPv0flMI6MgWnD@G_A0u9eGFNZ4S|=$;IdoA&%*aEIC8B#;6{bGAq_B!YUBYID#T6c70jX< zF<={qb5*0!=peVnXqwh3s$soA*73KUA<$LypwIQxJnLb-KvsalAsjJ$e*iY@^Szp< myqA<<2`aEWrwZ>W{Q@<`>KMYv%sl`A002ovPDHLkU;%=F`M78R delta 685 zcmV;e0#f~<1H=W8BYyw{b3#c}2nYxWdT2_|?DW!B>L;_wc?Zu;_6+$X4AyT|~3gSQD&4XUWvwt`1MT#adDA|iAF$O&J zW)IeYO?2C3X?|_U?q;)L$AgU|O^W?sm~S5Md-J`Sk1)n?TBK5`$2`wpsaC7^cXoDy zX&f?5U~_Ym9}EUB7Zw)Mk|afHwOZNpyp3Y9*!r(PGMPL#Gc)r}Rn;4kB=GbGvUdso->AAhF`Boc|silV$#Rdt!?`7vR}7!1Ss={U~ALZR?+h;t);Z^^R!d47I= znGiBzD-1)#VzEo2D85Oj(+`F?9VVhEMmdiAWSXWxDZRe9xOibyz_Ki(UavpmIL`Kc zzcOYalgZqko11&Ky1Kdq0J&TavMi5vaCmrV3xe>RNu$-Rt#MG);r1X%j@x^CmDt2!bGhZQB* #sidebarContainer { right: 0; bottom: 0; left: 0; - -moz-transition-duration: 200ms; - -moz-transition-timing-function: ease; -webkit-transition-duration: 200ms; -webkit-transition-timing-function: ease; + -moz-transition-duration: 200ms; + -moz-transition-timing-function: ease; + -ms-transition-duration: 200ms; + -ms-transition-timing-function: ease; + -o-transition-duration: 200ms; + -o-transition-timing-function: ease; + transition-duration: 200ms; + transition-timing-function: ease; } html[dir='ltr'] #outerContainer.sidebarOpen > #mainContainer { - -moz-transition-property: left; -webkit-transition-property: left; + -moz-transition-property: left; + -ms-transition-property: left; + -o-transition-property: left; + transition-property: left; left: 200px; } html[dir='rtl'] #outerContainer.sidebarOpen > #mainContainer { - -moz-transition-property: right; -webkit-transition-property: right; + -moz-transition-property: right; + -ms-transition-property: right; + -o-transition-property: right; + transition-property: right; right: 200px; } @@ -146,11 +176,17 @@ html[dir='rtl'] #sidebarContent { #toolbarSidebar { width: 200px; - height: 32px; + height: 29px; + background-image: url(images/texture.png), + -webkit-linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95)); background-image: url(images/texture.png), -moz-linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95)); background-image: url(images/texture.png), - -webkit-linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95)); + -ms-linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95)); + background-image: url(images/texture.png), + -o-linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95)); + background-image: url(images/texture.png), + linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95)); box-shadow: inset -2px 0 0 hsla(0,0%,100%,.08), inset 0 1px 1px hsla(0,0%,0%,.15), inset 0 -1px 0 hsla(0,0%,100%,.05), @@ -161,10 +197,16 @@ html[dir='rtl'] #sidebarContent { #toolbarViewer { position: relative; height: 32px; + background-image: url(images/texture.png), + -webkit-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95)); background-image: url(images/texture.png), -moz-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95)); background-image: url(images/texture.png), - -webkit-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95)); + -ms-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95)); + background-image: url(images/texture.png), + -o-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95)); + background-image: url(images/texture.png), + linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95)); border-left: 1px solid hsla(0,0%,0%,.5); box-shadow: inset 1px 0 0 hsla(0,0%,100%,.08), inset 0 1px 1px hsla(0,0%,0%,.15), @@ -242,28 +284,48 @@ html[dir='rtl'] .splitToolbarButton > .toolbarButton { margin-right:0; } +.splitToolbarButton.toggled .toolbarButton { + margin: 0; +} + .splitToolbarButton:hover > .toolbarButton, .splitToolbarButton:focus > .toolbarButton, -.splitToolbarButton.toggled > .toolbarButton { +.splitToolbarButton.toggled > .toolbarButton, +.toolbarButton.textButton { background-color: hsla(0,0%,0%,.12); - background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: -ms-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: -o-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); background-clip: padding-box; border: 1px solid hsla(0,0%,0%,.35); border-color: hsla(0,0%,0%,.32) hsla(0,0%,0%,.38) hsla(0,0%,0%,.42); box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset, 0 0 1px hsla(0,0%,100%,.15) inset, 0 1px 0 hsla(0,0%,100%,.05); - -moz-transition-property: background-color, border-color, box-shadow; - -moz-transition-duration: 150ms; - -moz-transition-timing-function: ease; -webkit-transition-property: background-color, border-color, box-shadow; -webkit-transition-duration: 150ms; -webkit-transition-timing-function: ease; + -moz-transition-property: background-color, border-color, box-shadow; + -moz-transition-duration: 150ms; + -moz-transition-timing-function: ease; + -ms-transition-property: background-color, border-color, box-shadow; + -ms-transition-duration: 150ms; + -ms-transition-timing-function: ease; + -o-transition-property: background-color, border-color, box-shadow; + -o-transition-duration: 150ms; + -o-transition-timing-function: ease; + transition-property: background-color, border-color, box-shadow; + transition-duration: 150ms; + transition-timing-function: ease; + } .splitToolbarButton > .toolbarButton:hover, .splitToolbarButton > .toolbarButton:focus, -.dropdownToolbarButton:hover { +.dropdownToolbarButton:hover, +.toolbarButton.textButton:hover, +.toolbarButton.textButton:focus { background-color: hsla(0,0%,0%,.2); box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset, 0 0 1px hsla(0,0%,100%,.15) inset, @@ -308,12 +370,21 @@ html[dir='rtl'] .splitToolbarButtonSeparator { padding: 12px 0; margin: 0; box-shadow: 0 0 0 1px hsla(0,0%,100%,.03); - -moz-transition-property: padding; - -moz-transition-duration: 10ms; - -moz-transition-timing-function: ease; -webkit-transition-property: padding; -webkit-transition-duration: 10ms; -webkit-transition-timing-function: ease; + -moz-transition-property: padding; + -moz-transition-duration: 10ms; + -moz-transition-timing-function: ease; + -ms-transition-property: padding; + -ms-transition-duration: 10ms; + -ms-transition-timing-function: ease; + -o-transition-property: padding; + -o-transition-duration: 10ms; + -o-transition-timing-function: ease; + transition-property: padding; + transition-duration: 10ms; + transition-timing-function: ease; } .toolbarButton, @@ -325,15 +396,26 @@ html[dir='rtl'] .splitToolbarButtonSeparator { color: hsl(0,0%,95%); font-size: 12px; line-height: 14px; - -moz-user-select:none; -webkit-user-select:none; + -moz-user-select:none; + -ms-user-select:none; + /* Opera does not support user-select, use <... unselectable="on"> instead */ cursor: default; - -moz-transition-property: background-color, border-color, box-shadow; - -moz-transition-duration: 150ms; - -moz-transition-timing-function: ease; -webkit-transition-property: background-color, border-color, box-shadow; -webkit-transition-duration: 150ms; -webkit-transition-timing-function: ease; + -moz-transition-property: background-color, border-color, box-shadow; + -moz-transition-duration: 150ms; + -moz-transition-timing-function: ease; + -ms-transition-property: background-color, border-color, box-shadow; + -ms-transition-duration: 150ms; + -ms-transition-timing-function: ease; + -o-transition-property: background-color, border-color, box-shadow; + -o-transition-duration: 150ms; + -o-transition-timing-function: ease; + transition-property: background-color, border-color, box-shadow; + transition-duration: 150ms; + transition-timing-function: ease; } html[dir='ltr'] .toolbarButton, @@ -349,8 +431,11 @@ html[dir='rtl'] .dropdownToolbarButton { .toolbarButton:focus, .dropdownToolbarButton { background-color: hsla(0,0%,0%,.12); - background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: -ms-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: -o-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); background-clip: padding-box; border: 1px solid hsla(0,0%,0%,.35); border-color: hsla(0,0%,0%,.32) hsla(0,0%,0%,.38) hsla(0,0%,0%,.42); @@ -362,35 +447,59 @@ html[dir='rtl'] .dropdownToolbarButton { .toolbarButton:hover:active, .dropdownToolbarButton:hover:active { background-color: hsla(0,0%,0%,.2); - background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: -ms-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: -o-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); border-color: hsla(0,0%,0%,.35) hsla(0,0%,0%,.4) hsla(0,0%,0%,.45); box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset, 0 0 1px hsla(0,0%,0%,.2) inset, 0 1px 0 hsla(0,0%,100%,.05); - -moz-transition-property: background-color, border-color, box-shadow; - -moz-transition-duration: 10ms; - -moz-transition-timing-function: linear; -webkit-transition-property: background-color, border-color, box-shadow; -webkit-transition-duration: 10ms; -webkit-transition-timing-function: linear; + -moz-transition-property: background-color, border-color, box-shadow; + -moz-transition-duration: 10ms; + -moz-transition-timing-function: linear; + -ms-transition-property: background-color, border-color, box-shadow; + -ms-transition-duration: 10ms; + -ms-transition-timing-function: linear; + -o-transition-property: background-color, border-color, box-shadow; + -o-transition-duration: 10ms; + -o-transition-timing-function: linear; + transition-property: background-color, border-color, box-shadow; + transition-duration: 10ms; + transition-timing-function: linear; } .toolbarButton.toggled, .splitToolbarButton.toggled > .toolbarButton.toggled { background-color: hsla(0,0%,0%,.3); - background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: -ms-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: -o-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); border-color: hsla(0,0%,0%,.4) hsla(0,0%,0%,.45) hsla(0,0%,0%,.5); box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset, 0 0 1px hsla(0,0%,0%,.2) inset, 0 1px 0 hsla(0,0%,100%,.05); - -moz-transition-property: background-color, border-color, box-shadow; - -moz-transition-duration: 10ms; - -moz-transition-timing-function: linear; -webkit-transition-property: background-color, border-color, box-shadow; -webkit-transition-duration: 10ms; -webkit-transition-timing-function: linear; + -moz-transition-property: background-color, border-color, box-shadow; + -moz-transition-duration: 10ms; + -moz-transition-timing-function: linear; + -ms-transition-property: background-color, border-color, box-shadow; + -ms-transition-duration: 10ms; + -ms-transition-timing-function: linear; + -o-transition-property: background-color, border-color, box-shadow; + -o-transition-duration: 10ms; + -o-transition-timing-function: linear; + transition-property: background-color, border-color, box-shadow; + transition-duration: 10ms; + transition-timing-function: linear; } .toolbarButton.toggled:hover:active, @@ -417,8 +526,8 @@ html[dir='rtl'] .dropdownToolbarButton { } .dropdownToolbarButton > select { - -moz-appearance: none; /* in the future this might matter, see bugzilla bug #649849 */ -webkit-appearance: none; + -moz-appearance: none; /* in the future this might matter, see bugzilla bug #649849 */ min-width: 140px; font-size: 12px; color: hsl(0,0%,95%); @@ -460,8 +569,8 @@ html[dir='rtl'] .toolbarButton:first-child { } .toolbarButtonFlexibleSpacer { - -moz-box-flex: 1; -webkit-box-flex: 1; + -moz-box-flex: 1; min-width: 30px; } @@ -516,8 +625,8 @@ html[dir='rtl'] .toolbarButton.pageDown::before { } .toolbarButton.bookmark { - -moz-box-sizing: border-box; -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; box-sizing: border-box; margin-top: 3px; padding-top: 4px; @@ -544,8 +653,6 @@ html[dir='rtl'] .toolbarButton.pageDown::before { .toolbarField { - min-width: 16px; - width: 32px; padding: 3px 6px; margin: 4px 0 4px 0; border: 1px solid transparent; @@ -560,7 +667,6 @@ html[dir='rtl'] .toolbarButton.pageDown::before { color: hsl(0,0%,95%); font-size: 12px; line-height: 14px; - text-align: right; outline-style: none; -moz-transition-property: background-color, border-color, box-shadow; -moz-transition-duration: 150ms; @@ -568,6 +674,8 @@ html[dir='rtl'] .toolbarButton.pageDown::before { } .toolbarField.pageNumber { + min-width: 16px; + text-align: right; width: 40px; } @@ -597,8 +705,8 @@ html[dir='rtl'] .toolbarButton.pageDown::before { font-size: 12px; line-height: 14px; text-align: left; - -moz-user-select:none; -webkit-user-select:none; + -moz-user-select:none; cursor: default; } @@ -674,17 +782,19 @@ a:focus > .thumbnail > .thumbnailSelectionRing, bottom: 0; padding: 4px 4px 0; overflow: auto; - -moz-user-select:none; -webkit-user-select:none; + -moz-user-select:none; } .outlineItem > .outlineItems { margin-left: 20px; } -.outlineItem > a { +.outlineItem > a, +#searchResults > a { text-decoration: none; - display: block; + display: inline-block; + min-width: 95%; height: 20px; padding: 2px 0 0 10px; margin-bottom: 1px; @@ -697,7 +807,8 @@ a:focus > .thumbnail > .thumbnailSelectionRing, white-space: nowrap; } -.outlineItem > a:hover { +.outlineItem > a:hover, +#searchResults > a:hover { background-color: hsla(0,0%,100%,.02); background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); background-clip: padding-box; @@ -707,6 +818,23 @@ a:focus > .thumbnail > .thumbnailSelectionRing, color: hsla(0,0%,100%,.9); } +.outlineItem.selected { + background-color: hsla(0,0%,100%,.08); + background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-clip: padding-box; + box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset, + 0 0 1px hsla(0,0%,100%,.1) inset, + 0 0 1px hsla(0,0%,0%,.2); + color: hsla(0,0%,100%,1); +} + +.noOutline, +.noResults { + font-size: 12px; + color: hsla(0,0%,100%,.8); + font-style: italic; +} + #searchScrollView { position: absolute; top: 10px; @@ -723,27 +851,26 @@ a:focus > .thumbnail > .thumbnailSelectionRing, } #searchToolbar > input { - margin-left: 8px; - width: 130px; + margin-left: 4px; + width: 124px; +} + +#searchToolbar button { + width: auto; + margin: 0; + padding: 0 6px; + height: 22px; } #searchResults { overflow: auto; - background-color: #fff; position: absolute; top: 30px; bottom: 0px; left: 0px; right: 0; + padding: 4px 4px 0; font-size: smaller; - opacity: 0.7; -} - -#searchResults a { - display: block; - white-space: pre; - text-decoration: none; - color: black; } #sidebarControls { @@ -754,24 +881,6 @@ a:focus > .thumbnail > .thumbnailSelectionRing, bottom: 35px; } -.outlineItem.selected { - background-color: hsla(0,0%,100%,.08); - background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); - background-clip: padding-box; - box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset, - 0 0 1px hsla(0,0%,100%,.1) inset, - 0 0 1px hsla(0,0%,0%,.2); - color: hsla(0,0%,100%,1); -} - -.noOutline { - font-size: 12px; - color: hsla(0,0%,100%,.8); - font-style: italic; -} - - - canvas { margin: auto; display: block; @@ -784,9 +893,9 @@ canvas { margin: 10px auto; position: relative; overflow: hidden; - box-shadow: 0px 4px 10px #000; - -moz-box-shadow: 0px 4px 10px #000; -webkit-box-shadow: 0px 4px 10px #000; + -moz-box-shadow: 0px 4px 10px #000; + box-shadow: 0px 4px 10px #000; background-color: white; } @@ -798,9 +907,9 @@ canvas { .page > a:hover { opacity: 0.2; background: #ff0; - box-shadow: 0px 2px 10px #ff0; - -moz-box-shadow: 0px 2px 10px #ff0; -webkit-box-shadow: 0px 2px 10px #ff0; + -moz-box-shadow: 0px 2px 10px #ff0; + box-shadow: 0px 2px 10px #ff0; } .loadingIcon { @@ -814,23 +923,33 @@ canvas { } #loadingBox { - margin: 100px 0; + position: absolute; + top: 50%; + margin-top: -25px; + left: 0; + right: 0; text-align: center; color: #ddd; font-size: 14px; } #loadingBar { - background-color: #333; display: inline-block; - border: 1px solid black; clear: both; margin: 0px; margin-top: 5px; line-height: 0; - border-radius: 4px; + border-radius: 2px; width: 200px; height: 25px; + + background-color: hsla(0,0%,0%,.3); + background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + border: 1px solid #000; + box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset, + 0 0 1px hsla(0,0%,0%,.2) inset, + 0 0 1px 1px rgba(255, 255, 255, 0.1); } #loadingBar .progress { @@ -838,23 +957,23 @@ canvas { float: left; background: #666; - background: -moz-linear-gradient(top, #999 0%, #666 50%, #999 100%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#999), color-stop(50%,#666), color-stop(100%,#999)); - background: -webkit-linear-gradient(top, #999 0%,#666 50%,#999 100%); - background: -o-linear-gradient(top, #999 0%,#666 50%,#999 100%); - background: -ms-linear-gradient(top, #999 0%,#666 50%,#999 100%); - background: linear-gradient(top, #999 0%,#666 50%,#999 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#b2b2b2), color-stop(100%,#898989)); + background: -webkit-linear-gradient(top, #b2b2b2 0%,#898989 100%); + background: -moz-linear-gradient(top, #b2b2b2 0%,#898989 100%); + background: -ms-linear-gradient(top, #b2b2b2 0%,#898989 100%); + background: -o-linear-gradient(top, #b2b2b2 0%,#898989 100%); + background: linear-gradient(top, #b2b2b2 0%,#898989 100%); - border-top-left-radius: 3px; - border-bottom-left-radius: 3px; + border-top-left-radius: 2px; + border-bottom-left-radius: 2px; width: 0%; height: 100%; } #loadingBar .progress.full { - border-top-right-radius: 3px; - border-bottom-right-radius: 3px; + border-top-right-radius: 2px; + border-bottom-right-radius: 2px; } .textLayer { @@ -896,9 +1015,9 @@ canvas { padding: 0.2em; max-width: 20em; background-color: #F1E47B; - box-shadow: 0px 2px 10px #333; - -moz-box-shadow: 0px 2px 10px #333; -webkit-box-shadow: 0px 2px 10px #333; + -moz-box-shadow: 0px 2px 10px #333; + box-shadow: 0px 2px 10px #333; } .annotComment > div > h1 { @@ -994,7 +1113,16 @@ canvas { font-size: 10px; } +@page { + margin: 0; +} + +#printContainer { + display: none; +} + @media print { + /* Rules for browsers that don't support mozPrintCallback. */ #sidebarContainer, .toolbar, #loadingBox, #errorWrapper, .textLayer { display: none; } @@ -1008,14 +1136,27 @@ canvas { .page { float: left; display: none; - box-shadow: none; - -moz-box-shadow: none; -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; } .page[data-loaded] { display: block; } + + /* Rules for browsers that support mozPrintCallback */ + body[data-mozPrintCallback] #outerContainer { + display: none; + } + body[data-mozPrintCallback] #printContainer { + display: block; + } + #printContainer canvas { + position: relative; + top: 0; + left: 0; + } } @media all and (max-width: 950px) { @@ -1066,3 +1207,10 @@ canvas { display: none; } } + +@media all and (max-width: 500px) { + #scaleSelectContainer, #pageNumberLabel { + display: none; + } +} + diff --git a/browser/extensions/pdfjs/content/web/viewer.html b/browser/extensions/pdfjs/content/web/viewer.html index 776fbec2ec74..4b895ab12061 100644 --- a/browser/extensions/pdfjs/content/web/viewer.html +++ b/browser/extensions/pdfjs/content/web/viewer.html @@ -2,6 +2,7 @@ + PDF.js viewer @@ -22,7 +23,7 @@ var PDFJS = {}; // Use strict in our context only - users might not want it 'use strict'; - PDFJS.build = '121040a'; + PDFJS.build = 'c757eed'; // Files are inserted below - see Makefile /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ @@ -1187,7 +1188,9 @@ var StatTimer = (function StatTimerClosure() { * @return {Promise} A promise that is resolved with {PDFDocumentProxy} object. */ PDFJS.getDocument = function getDocument(source) { - var url, data, headers, password, parameters = {}; + var url, data, headers, password, parameters = {}, workerInitializedPromise, + workerReadyPromise, transport; + if (typeof source === 'string') { url = source; } else if (isArrayBuffer(source)) { @@ -1206,8 +1209,9 @@ PDFJS.getDocument = function getDocument(source) { 'string or a parameter object'); } - var promise = new PDFJS.Promise(); - var transport = new WorkerTransport(promise); + workerInitializedPromise = new PDFJS.Promise(); + workerReadyPromise = new PDFJS.Promise(); + transport = new WorkerTransport(workerInitializedPromise, workerReadyPromise); if (data) { // assuming the data is array, instantiating directly from it transport.sendData(data, parameters); @@ -1217,24 +1221,31 @@ PDFJS.getDocument = function getDocument(source) { { url: url, progress: function getPDFProgress(evt) { - if (evt.lengthComputable) - promise.progress({ + if (evt.lengthComputable) { + workerReadyPromise.progress({ loaded: evt.loaded, total: evt.total }); + } }, error: function getPDFError(e) { - promise.reject('Unexpected server response of ' + + workerReadyPromise.reject('Unexpected server response of ' + e.target.status + '.'); }, headers: headers }, function getPDFLoad(data) { - transport.sendData(data, parameters); + // sometimes the pdf has finished downloading before the web worker-test + // has finished. In that case the rendering of the final pdf would cause + // errors. We have to wait for the WorkerTransport to finalize worker- + // support detection + workerInitializedPromise.then(function workerInitialized() { + transport.sendData(data, parameters); + }); }); } - return promise; + return workerReadyPromise; }; /** @@ -1320,6 +1331,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(); } @@ -1394,7 +1414,11 @@ var PDFPageProxy = (function PDFPageProxyClosure() { * { * canvasContext(required): A 2D context of a DOM Canvas object., * textLayer(optional): An object that has beginLayout, endLayout, and - * appendText functions. + * appendText functions., + * continueCallback(optional): A function that will be called each time + * the rendering is paused. To continue + * rendering call the function that is the + * first argument to the callback. * }. * @return {Promise} A promise that is resolved when the page finishes * rendering. @@ -1430,6 +1454,7 @@ var PDFPageProxy = (function PDFPageProxyClosure() { else promise.resolve(); }; + var continueCallback = params.continueCallback; // Once the operatorList and fonts are loaded, do the actual rendering. this.displayReadyPromise.then( @@ -1442,7 +1467,7 @@ var PDFPageProxy = (function PDFPageProxyClosure() { var gfx = new CanvasGraphics(params.canvasContext, this.objs, params.textLayer); try { - this.display(gfx, params.viewport, complete); + this.display(gfx, params.viewport, complete, continueCallback); } catch (e) { complete(e); } @@ -1500,7 +1525,8 @@ var PDFPageProxy = (function PDFPageProxyClosure() { /** * For internal use only. */ - display: function PDFPageProxy_display(gfx, viewport, callback) { + display: function PDFPageProxy_display(gfx, viewport, callback, + continueCallback) { var stats = this.stats; stats.time('Rendering'); @@ -1516,10 +1542,16 @@ var PDFPageProxy = (function PDFPageProxyClosure() { stepper.nextBreakPoint = stepper.getNextBreakPoint(); } + var continueWrapper; + if (continueCallback) + continueWrapper = function() { continueCallback(next); } + else + continueWrapper = next; + var self = this; function next() { - startIdx = - gfx.executeOperatorList(operatorList, startIdx, next, stepper); + startIdx = gfx.executeOperatorList(operatorList, startIdx, + continueWrapper, stepper); if (startIdx == length) { gfx.endDrawing(); stats.timeEnd('Rendering'); @@ -1527,7 +1559,7 @@ var PDFPageProxy = (function PDFPageProxyClosure() { if (callback) callback(); } } - next(); + continueWrapper(); }, /** * @return {Promise} That is resolved with the a {string} that is the text @@ -1574,8 +1606,8 @@ var PDFPageProxy = (function PDFPageProxyClosure() { * For internal use only. */ var WorkerTransport = (function WorkerTransportClosure() { - function WorkerTransport(promise) { - this.workerReadyPromise = promise; + function WorkerTransport(workerInitializedPromise, workerReadyPromise) { + this.workerReadyPromise = workerReadyPromise; this.objs = new PDFObjects(); this.pageCache = []; @@ -1619,6 +1651,7 @@ var WorkerTransport = (function WorkerTransportClosure() { globalScope.PDFJS.disableWorker = true; this.setupFakeWorker(); } + workerInitializedPromise.resolve(); }.bind(this)); var testObj = new Uint8Array(1); @@ -1634,6 +1667,7 @@ var WorkerTransport = (function WorkerTransportClosure() { // Thus, we fallback to a faked worker. globalScope.PDFJS.disableWorker = true; this.setupFakeWorker(); + workerInitializedPromise.resolve(); } WorkerTransport.prototype = { destroy: function WorkerTransport_destroy() { @@ -1785,6 +1819,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) @@ -2903,6 +2943,40 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { } } } + function rescaleImage(pixels, widthScale, heightScale) { + var scaledWidth = Math.ceil(width / widthScale); + var scaledHeight = Math.ceil(height / heightScale); + + var itemsSum = new Uint32Array(scaledWidth * scaledHeight * 4); + var itemsCount = new Uint32Array(scaledWidth * scaledHeight); + for (var i = 0, position = 0; i < height; i++) { + var lineOffset = (0 | (i / heightScale)) * scaledWidth; + for (var j = 0; j < width; j++) { + var countOffset = lineOffset + (0 | (j / widthScale)); + var sumOffset = countOffset << 2; + itemsSum[sumOffset] += pixels[position]; + itemsSum[sumOffset + 1] += pixels[position + 1]; + itemsSum[sumOffset + 2] += pixels[position + 2]; + itemsSum[sumOffset + 3] += pixels[position + 3]; + itemsCount[countOffset]++; + position += 4; + } + } + var tmpCanvas = createScratchCanvas(scaledWidth, scaledHeight); + var tmpCtx = tmpCanvas.getContext('2d'); + var imgData = tmpCtx.getImageData(0, 0, scaledWidth, scaledHeight); + pixels = imgData.data; + for (var i = 0, j = 0, ii = scaledWidth * scaledHeight; i < ii; i++) { + var count = itemsCount[i]; + pixels[j] = itemsSum[j] / count; + pixels[j + 1] = itemsSum[j + 1] / count; + pixels[j + 2] = itemsSum[j + 2] / count; + pixels[j + 3] = itemsSum[j + 3] / count; + j += 4; + } + tmpCtx.putImageData(imgData, 0, 0); + return tmpCanvas; + } this.save(); @@ -2925,8 +2999,19 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { applyStencilMask(pixels, inverseDecode); - tmpCtx.putImageData(imgData, 0, 0); - ctx.drawImage(tmpCanvas, 0, -h); + var currentTransform = ctx.mozCurrentTransformInverse; + var widthScale = Math.max(Math.abs(currentTransform[0]), 1); + var heightScale = Math.max(Math.abs(currentTransform[3]), 1); + if (widthScale >= 2 || heightScale >= 2) { + // canvas does not resize well large images to small -- using simple + // algorithm to perform pre-scaling + tmpCanvas = rescaleImage(imgData.data, widthScale, heightScale); + ctx.scale(widthScale, heightScale); + ctx.drawImage(tmpCanvas, 0, -h / heightScale); + } else { + tmpCtx.putImageData(imgData, 0, 0); + ctx.drawImage(tmpCanvas, 0, -h); + } this.restore(); }, @@ -13216,8 +13301,10 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { insertDependency([objId]); args = [objId, w, h]; - var softMask = dict.get('SMask', 'IM') || false; - if (!softMask && image instanceof JpegStream && + var softMask = dict.get('SMask', 'SM') || false; + var mask = dict.get('Mask') || false; + + if (!softMask && !mask && image instanceof JpegStream && image.isNativelySupported(xref, resources)) { // These JPEGs don't need any more processing so we can just send it. fn = 'paintJpegXObject'; @@ -14509,7 +14596,7 @@ var FontLoader = { // XXX we should have a time-out here too, and maybe fire // pdfjsFontLoadFailed? - var src = ''; + var src = ''; src += '