diff --git a/Makefile b/Makefile index 34a7930a3..c1062d49d 100644 --- a/Makefile +++ b/Makefile @@ -209,11 +209,11 @@ pages-repo: | $(BUILD_DIR) # copy of the pdf.js source. CONTENT_DIR := content BUILD_NUMBER := `git log --format=oneline $(EXTENSION_BASE_VERSION).. | wc -l | awk '{print $$1}'` -PDF_WEB_FILES = \ +EXTENSION_WEB_FILES = \ web/images \ - web/compatibility.js \ web/viewer.css \ web/viewer.js \ + web/viewer.html \ web/viewer-production.html \ $(NULL) @@ -251,8 +251,19 @@ extension: | production @cd extensions/firefox; cp -r $(FIREFOX_EXTENSION_FILES_TO_COPY) ../../$(FIREFOX_BUILD_DIR)/ # Copy a standalone version of pdf.js inside the content directory @cp $(BUILD_TARGET) $(FIREFOX_BUILD_CONTENT)/$(BUILD_DIR)/ - @cp -r $(PDF_WEB_FILES) $(FIREFOX_BUILD_CONTENT)/web/ - @mv -f $(FIREFOX_BUILD_CONTENT)/web/viewer-production.html $(FIREFOX_BUILD_CONTENT)/web/viewer.html + @cp -r $(EXTENSION_WEB_FILES) $(FIREFOX_BUILD_CONTENT)/web/ + @rm $(FIREFOX_BUILD_CONTENT)/web/viewer-production.html + # Copy over the firefox extension snippet so we can inline pdf.js in it + @cp web/viewer-snippet-firefox-extension.html $(FIREFOX_BUILD_CONTENT)/web/ + # Modify the viewer so it does all the extension only stuff. + @cd $(FIREFOX_BUILD_CONTENT)/web; \ + sed -i.bak '/PDFJSSCRIPT_INCLUDE_BUNDLE/ r ../build/pdf.js' viewer-snippet-firefox-extension.html; \ + sed -i.bak '/PDFJSSCRIPT_REMOVE/d' viewer.html; \ + sed -i.bak '/PDFJSSCRIPT_REMOVE_FIREFOX_EXTENSION/d' viewer.html; \ + sed -i.bak '/PDFJSSCRIPT_INCLUDE_FIREFOX_EXTENSION/ r viewer-snippet-firefox-extension.html' viewer.html; \ + rm -f *.bak; + # We don't need pdf.js anymore since its inlined + @rm -Rf $(FIREFOX_BUILD_CONTENT)/$(BUILD_DIR)/; # Update the build version number @sed -i.bak "s/PDFJSSCRIPT_BUILD/$(BUILD_NUMBER)/" $(FIREFOX_BUILD_DIR)/install.rdf @sed -i.bak "s/PDFJSSCRIPT_BUILD/$(BUILD_NUMBER)/" $(FIREFOX_BUILD_DIR)/update.rdf @@ -274,7 +285,7 @@ extension: | production @cp -R $(CHROME_EXTENSION_FILES) $(CHROME_BUILD_DIR)/ # Copy a standalone version of pdf.js inside the content directory @cp $(BUILD_TARGET) $(CHROME_BUILD_CONTENT)/$(BUILD_DIR)/ - @cp -r $(PDF_WEB_FILES) $(CHROME_BUILD_CONTENT)/web/ + @cp -r $(EXTENSION_WEB_FILES) $(CHROME_BUILD_CONTENT)/web/ @mv -f $(CHROME_BUILD_CONTENT)/web/viewer-production.html $(CHROME_BUILD_CONTENT)/web/viewer.html # Create the crx diff --git a/extensions/firefox/bootstrap.js b/extensions/firefox/bootstrap.js index e51df28f8..f1a712c0c 100644 --- a/extensions/firefox/bootstrap.js +++ b/extensions/firefox/bootstrap.js @@ -3,6 +3,8 @@ 'use strict'; +const EXT_PREFIX = 'extensions.uriloader@pdf.js'; +const PDFJS_EVENT_ID = 'pdf.js.message'; let Cc = Components.classes; let Ci = Components.interfaces; let Cm = Components.manager; @@ -14,6 +16,7 @@ function log(str) { dump(str + '\n'); } + function startup(aData, aReason) { let manifestPath = 'chrome.manifest'; let manifest = Cc['@mozilla.org/file/local;1'] @@ -34,13 +37,11 @@ function shutdown(aData, aReason) { } function install(aData, aReason) { - let url = 'chrome://pdf.js/content/web/viewer.html?file=%s'; - Services.prefs.setCharPref('extensions.pdf.js.url', url); Services.prefs.setBoolPref('extensions.pdf.js.active', false); } function uninstall(aData, aReason) { - Services.prefs.clearUserPref('extensions.pdf.js.url'); Services.prefs.clearUserPref('extensions.pdf.js.active'); + application.prefs.setValue(EXT_PREFIX + '.database', '{}'); } diff --git a/extensions/firefox/chrome.manifest b/extensions/firefox/chrome.manifest index d7db20b38..5351257e7 100644 --- a/extensions/firefox/chrome.manifest +++ b/extensions/firefox/chrome.manifest @@ -1,5 +1,5 @@ -content pdf.js content/ +resource pdf.js content/ -component {2278dfd0-b75c-11e0-8257-1ba3d93c9f1a} components/pdfContentHandler.js -contract @mozilla.org/uriloader/content-handler;1?type=application/pdf {2278dfd0-b75c-11e0-8257-1ba3d93c9f1a} +component {6457a96b-2d68-439a-bcfa-44465fbcdbb1} components/PdfStreamConverter.js +contract @mozilla.org/streamconv;1?from=application/pdf&to=*/* {6457a96b-2d68-439a-bcfa-44465fbcdbb1} diff --git a/extensions/firefox/components/PdfStreamConverter.js b/extensions/firefox/components/PdfStreamConverter.js new file mode 100644 index 000000000..984915d23 --- /dev/null +++ b/extensions/firefox/components/PdfStreamConverter.js @@ -0,0 +1,159 @@ +/* -*- 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 Cc = Components.classes; +const Ci = Components.interfaces; +const Cr = Components.results; +const Cu = Components.utils; +const PDFJS_EVENT_ID = 'pdf.js.message'; +const PDF_CONTENT_TYPE = 'application/pdf'; +const NS_ERROR_NOT_IMPLEMENTED = 0x80004001; +const EXT_PREFIX = 'extensions.uriloader@pdf.js'; + +Cu.import('resource://gre/modules/XPCOMUtils.jsm'); +Cu.import('resource://gre/modules/Services.jsm'); + +function log(aMsg) { + let msg = 'PdfStreamConverter.js: ' + (aMsg.join ? aMsg.join('') : aMsg); + Cc['@mozilla.org/consoleservice;1'].getService(Ci.nsIConsoleService) + .logStringMessage(msg); + dump(msg + '\n'); +} +let application = Cc['@mozilla.org/fuel/application;1'] + .getService(Ci.fuelIApplication); +let privateBrowsing = Cc['@mozilla.org/privatebrowsing;1'] + .getService(Ci.nsIPrivateBrowsingService); +let inPrivateBrowswing = privateBrowsing.privateBrowsingEnabled; + +// All the priviledged actions. +function ChromeActions() { + this.inPrivateBrowswing = privateBrowsing.privateBrowsingEnabled; +} +ChromeActions.prototype = { + download: function(data) { + Services.wm.getMostRecentWindow('navigator:browser').saveURL(data); + }, + setDatabase: function(data) { + if (this.inPrivateBrowswing) + return; + application.prefs.setValue(EXT_PREFIX + '.database', data); + }, + getDatabase: function() { + if (this.inPrivateBrowswing) + return '{}'; + return application.prefs.getValue(EXT_PREFIX + '.database', '{}'); + } +}; + +// Event listener to trigger chrome privedged code. +function RequestListener(actions) { + this.actions = actions; +} +// Receive an event and synchronously responds. +RequestListener.prototype.receive = function(event) { + var message = event.target; + var action = message.getUserData('action'); + var data = message.getUserData('data'); + 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); +}; + + +function PdfStreamConverter() { +} + +PdfStreamConverter.prototype = { + + // properties required for XPCOM registration: + classID: Components.ID('{6457a96b-2d68-439a-bcfa-44465fbcdbb1}'), + classDescription: 'pdf.js Component', + contractID: '@mozilla.org/streamconv;1?from=application/pdf&to=*/*', + + QueryInterface: XPCOMUtils.generateQI([ + Ci.nsISupports, + Ci.nsIStreamConverter, + Ci.nsIStreamListener, + Ci.nsIRequestObserver + ]), + + /* + * This component works as such: + * 1. asyncConvertData stores the listener + * 2. onStartRequest creates a new channel, streams the viewer and cancels + * the request so pdf.js can do the request + * Since the request is cancelled onDataAvailable should not be called. The + * onStopRequest does nothing. The convert function just returns the stream, + * it's just the synchronous version of asyncConvertData. + */ + + // nsIStreamConverter::convert + convert: function(aFromStream, aFromType, aToType, aCtxt) { + return aFromStream; + }, + + // nsIStreamConverter::asyncConvertData + asyncConvertData: function(aFromType, aToType, aListener, aCtxt) { + if (!Services.prefs.getBoolPref('extensions.pdf.js.active')) + throw NS_ERROR_NOT_IMPLEMENTED; + // Store the listener passed to us + this.listener = aListener; + }, + + // nsIStreamListener::onDataAvailable + onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) { + // Do nothing since all the data loading is handled by the viewer. + log('SANITY CHECK: onDataAvailable SHOULD NOT BE CALLED!'); + }, + + // nsIRequestObserver::onStartRequest + onStartRequest: function(aRequest, aContext) { + + // Setup the request so we can use it below. + aRequest.QueryInterface(Ci.nsIChannel); + // Cancel the request so the viewer can handle it. + aRequest.cancel(Cr.NS_BINDING_ABORTED); + + // Create a new channel that is viewer loaded as a resource. + var ioService = Cc['@mozilla.org/network/io-service;1'] + .getService(Ci.nsIIOService); + var channel = ioService.newChannel( + 'resource://pdf.js/web/viewer.html', null, null); + + // Keep the URL the same so the browser sees it as the same. + channel.originalURI = aRequest.originalURI; + channel.asyncOpen(this.listener, aContext); + + // Setup a global listener waiting for the next DOM to be created and verfiy + // that its the one we want by its URL. When the correct DOM is found create + // an event listener on that window for the pdf.js events that require + // chrome priviledges. + var url = aRequest.originalURI.spec; + var gb = Services.wm.getMostRecentWindow('navigator:browser'); + var domListener = function domListener(event) { + var doc = event.originalTarget; + var win = doc.defaultView; + if (doc.location.href === url) { + gb.removeEventListener('DOMContentLoaded', domListener); + var requestListener = new RequestListener(new ChromeActions()); + win.addEventListener(PDFJS_EVENT_ID, function(event) { + requestListener.receive(event); + }, false, true); + } + }; + gb.addEventListener('DOMContentLoaded', domListener, false); + }, + + // nsIRequestObserver::onStopRequest + onStopRequest: function(aRequest, aContext, aStatusCode) { + // Do nothing. + } +}; + +var NSGetFactory = XPCOMUtils.generateNSGetFactory([PdfStreamConverter]); diff --git a/extensions/firefox/components/pdfContentHandler.js b/extensions/firefox/components/pdfContentHandler.js deleted file mode 100644 index 67459b759..000000000 --- a/extensions/firefox/components/pdfContentHandler.js +++ /dev/null @@ -1,67 +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 Cc = Components.classes; -const Ci = Components.interfaces; -const Cr = Components.results; -const Cu = Components.utils; - -const PDF_CONTENT_TYPE = 'application/pdf'; - -Cu.import('resource://gre/modules/XPCOMUtils.jsm'); -Cu.import('resource://gre/modules/Services.jsm'); - -function log(aMsg) { - let msg = 'pdfContentHandler.js: ' + (aMsg.join ? aMsg.join('') : aMsg); - Cc['@mozilla.org/consoleservice;1'].getService(Ci.nsIConsoleService) - .logStringMessage(msg); - dump(msg + '\n'); -} - -const NS_ERROR_WONT_HANDLE_CONTENT = 0x805d0001; -function pdfContentHandler() { -} - -pdfContentHandler.prototype = { - handleContent: function handleContent(aMimetype, aContext, aRequest) { - if (aMimetype != PDF_CONTENT_TYPE) - throw NS_ERROR_WONT_HANDLE_CONTENT; - - if (!(aRequest instanceof Ci.nsIChannel)) - throw NS_ERROR_WONT_HANDLE_CONTENT; - - if (!Services.prefs.getBoolPref('extensions.pdf.js.active')) - throw NS_ERROR_WONT_HANDLE_CONTENT; - - let window = null; - let callbacks = aRequest.notificationCallbacks || - aRequest.loadGroup.notificationCallbacks; - if (!callbacks) - return; - - window = callbacks.getInterface(Ci.nsIDOMWindow); - - let url = null; - try { - url = Services.prefs.getCharPref('extensions.pdf.js.url'); - } catch (e) { - log('Error retrieving the pdf.js base url - ' + e); - throw NS_ERROR_WONT_HANDLE_CONTENT; - } - - let targetUrl = aRequest.URI.spec; - if (targetUrl.indexOf('#pdfjs.action=download') >= 0) - throw NS_ERROR_WONT_HANDLE_CONTENT; - - aRequest.cancel(Cr.NS_BINDING_ABORTED); - window.location = url.replace('%s', encodeURIComponent(targetUrl)); - }, - - classID: Components.ID('{2278dfd0-b75c-11e0-8257-1ba3d93c9f1a}'), - QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentHandler]) -}; - -var NSGetFactory = XPCOMUtils.generateNSGetFactory([pdfContentHandler]); - diff --git a/src/core.js b/src/core.js index df38c086f..cb601398e 100644 --- a/src/core.js +++ b/src/core.js @@ -624,9 +624,19 @@ var PDFDoc = (function PDFDocClosure() { } try { - // Some versions of FF can't create a worker on localhost, see: - // https://bugzilla.mozilla.org/show_bug.cgi?id=683280 - var worker = new Worker(workerSrc); + var worker; + if (PDFJS.isFirefoxExtension) { + // The firefox extension can't load the worker from the resource:// + // url so we have to inline the script and then use the blob loader. + var bb = new MozBlobBuilder(); + bb.append(document.querySelector('#PDFJS_SCRIPT_TAG').textContent); + var blobUrl = window.URL.createObjectURL(bb.getBlob()); + worker = new Worker(blobUrl); + } else { + // Some versions of FF can't create a worker on localhost, see: + // https://bugzilla.mozilla.org/show_bug.cgi?id=683280 + worker = new Worker(workerSrc); + } var messageHandler = new MessageHandler('main', worker); @@ -645,7 +655,9 @@ var PDFDoc = (function PDFDocClosure() { // serializing the typed array. messageHandler.send('test', testObj); return; - } catch (e) {} + } catch (e) { + warn('The worker has been disabled.'); + } } // Either workers are disabled, not supported or have thrown an exception. // Thus, we fallback to a faked worker. diff --git a/web/viewer-snippet-firefox-extension.html b/web/viewer-snippet-firefox-extension.html new file mode 100644 index 000000000..a3d3502a8 --- /dev/null +++ b/web/viewer-snippet-firefox-extension.html @@ -0,0 +1,14 @@ + + + + diff --git a/web/viewer.css b/web/viewer.css index e355f7fc2..b9fd3e9e4 100644 --- a/web/viewer.css +++ b/web/viewer.css @@ -9,7 +9,7 @@ body { } [hidden] { - display: none; + display: none !important; } /* === Toolbar === */ diff --git a/web/viewer.html b/web/viewer.html index 221ef7abf..7c55ec735 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -2,9 +2,11 @@ Simple pdf.js page viewer + + - + @@ -91,7 +93,7 @@ -
+
Bookmark diff --git a/web/viewer.js b/web/viewer.js index dd16b0282..04339ca66 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -62,6 +62,31 @@ var RenderingQueue = (function RenderingQueueClosure() { return RenderingQueue; })(); +var FirefoxCom = (function FirefoxComClosure() { + return { + /** + * Creates an event that hopefully the extension is listening for and will + * synchronously respond to. + * @param {String} action The action to trigger. + * @param {String} data Optional data to send. + * @return {*} The response. + */ + request: function(action, data) { + var request = document.createTextNode(''); + request.setUserData('action', action, null); + request.setUserData('data', data, null); + document.documentElement.appendChild(request); + + var sender = document.createEvent('Events'); + sender.initEvent('pdf.js.message', true, false); + request.dispatchEvent(sender); + var response = request.getUserData('response'); + document.documentElement.removeChild(request); + return response; + } + }; +})(); + // Settings Manager - This is a utility for saving settings // First we see if localStorage is available, FF bug #495747 // If not, we use FUEL in FF @@ -74,22 +99,14 @@ var Settings = (function SettingsClosure() { } return true; })(); - var extPrefix = 'extensions.uriloader@pdf.js'; - var isExtension = location.protocol == 'chrome:' && !isLocalStorageEnabled; - var inPrivateBrowsing = false; - if (isExtension) { - var pbs = Components.classes['@mozilla.org/privatebrowsing;1'] - .getService(Components.interfaces.nsIPrivateBrowsingService); - inPrivateBrowsing = pbs.privateBrowsingEnabled; - } + + var isFirefoxExtension = PDFJS.isFirefoxExtension; function Settings(fingerprint) { var database = null; var index; - if (inPrivateBrowsing) - return false; - else if (isExtension) - database = Application.prefs.getValue(extPrefix + '.database', '{}'); + if (isFirefoxExtension) + database = FirefoxCom.request('getDatabase', null); else if (isLocalStorageEnabled) database = localStorage.getItem('database') || '{}'; else @@ -111,31 +128,23 @@ var Settings = (function SettingsClosure() { index = database.files.push({fingerprint: fingerprint}) - 1; this.file = database.files[index]; this.database = database; - if (isExtension) - Application.prefs.setValue(extPrefix + '.database', - JSON.stringify(database)); - else if (isLocalStorageEnabled) + if (isLocalStorageEnabled) localStorage.setItem('database', JSON.stringify(database)); } Settings.prototype = { set: function settingsSet(name, val) { - if (inPrivateBrowsing) - return false; var file = this.file; file[name] = val; - if (isExtension) - Application.prefs.setValue(extPrefix + '.database', - JSON.stringify(this.database)); + var database = JSON.stringify(this.database); + if (isFirefoxExtension) + FirefoxCom.request('setDatabase', database); else if (isLocalStorageEnabled) - localStorage.setItem('database', JSON.stringify(this.database)); + localStorage.setItem('database', database); }, get: function settingsGet(name, defaultValue) { - if (inPrivateBrowsing) - return defaultValue; - else - return this.file[name] || defaultValue; + return this.file[name] || defaultValue; } }; @@ -258,7 +267,7 @@ var PDFView = { }, error: function getPdfError(e) { var loadingIndicator = document.getElementById('loading'); - loadingIndicator.innerHTML = 'Error'; + loadingIndicator.textContent = 'Error'; var moreInfo = { message: 'Unexpected server response of ' + e.target.status + '.' }; @@ -273,7 +282,13 @@ var PDFView = { }, download: function pdfViewDownload() { - window.open(this.url + '#pdfjs.action=download', '_parent'); + var url = this.url.split('#')[0]; + if (PDFJS.isFirefoxExtension) { + FirefoxCom.request('download', url); + } else { + url += '#pdfjs.action=download', '_parent'; + window.open(url, '_parent'); + } }, navigateTo: function pdfViewNavigateTo(dest) { @@ -294,14 +309,14 @@ var PDFView = { getDestinationHash: function pdfViewGetDestinationHash(dest) { if (typeof dest === 'string') - return '#' + escape(dest); + return PDFView.getAnchorUrl('#' + escape(dest)); if (dest instanceof Array) { var destRef = dest[0]; // see navigateTo method for dest format var pageNumber = destRef instanceof Object ? this.pagesRefMap[destRef.num + ' ' + destRef.gen + ' R'] : (destRef + 1); if (pageNumber) { - var pdfOpenParams = '#page=' + pageNumber; + var pdfOpenParams = PDFView.getAnchorUrl('#page=' + pageNumber); var destKind = dest[1]; if ('name' in destKind && destKind.name == 'XYZ') { var scale = (dest[4] || this.currentScale); @@ -316,6 +331,17 @@ var PDFView = { return ''; }, + /** + * For the firefox extension we prefix the full url on anchor links so they + * don't come up as resource:// urls and so open in new tab/window works. + * @param {String} anchor The anchor hash include the #. + */ + getAnchorUrl: function getAnchorUrl(anchor) { + if (PDFJS.isFirefoxExtension) + return this.url.split('#')[0] + anchor; + return anchor; + }, + /** * Show the error box. * @param {String} message A message that is human readable. @@ -328,7 +354,7 @@ var PDFView = { errorWrapper.removeAttribute('hidden'); var errorMessage = document.getElementById('errorMessage'); - errorMessage.innerHTML = message; + errorMessage.textContent = message; var closeButton = document.getElementById('errorClose'); closeButton.onclick = function() { @@ -363,7 +389,7 @@ var PDFView = { progress: function pdfViewProgress(level) { var percent = Math.round(level * 100); var loadingIndicator = document.getElementById('loading'); - loadingIndicator.innerHTML = 'Loading... ' + percent + '%'; + loadingIndicator.textContent = 'Loading... ' + percent + '%'; }, load: function pdfViewLoad(data, scale) { @@ -403,7 +429,7 @@ var PDFView = { var pagesCount = pdf.numPages; var id = pdf.fingerprint; var storedHash = null; - document.getElementById('numPages').innerHTML = pagesCount; + document.getElementById('numPages').textContent = pagesCount; document.getElementById('pageNumber').max = pagesCount; PDFView.documentFingerprint = id; var store = PDFView.store = new Settings(id); @@ -655,7 +681,15 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight, if (!item.content) { content.setAttribute('hidden', true); } else { - text.innerHTML = item.content.replace('\n', '
'); + var e = document.createElement('span'); + var lines = item.content.split('\n'); + for (var i = 0, ii = lines.length; i < ii; ++i) { + var line = lines[i]; + e.appendChild(document.createTextNode(line)); + if (i < (ii - 1)) + e.appendChild(document.createElement('br')); + } + text.appendChild(e); image.addEventListener('mouseover', function annotationImageOver() { this.nextSibling.removeAttribute('hidden'); }, false); @@ -831,13 +865,13 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight, var t1 = stats.compile, t2 = stats.fonts, t3 = stats.render; var str = 'Time to compile/fonts/render: ' + (t1 - stats.begin) + '/' + (t2 - t1) + '/' + (t3 - t2) + ' ms'; - document.getElementById('info').innerHTML = str; + document.getElementById('info').textContent = str; }; }; var ThumbnailView = function thumbnailView(container, page, id, pageRatio) { var anchor = document.createElement('a'); - anchor.href = '#' + id; + anchor.href = PDFView.getAnchorUrl('#page=' + id); anchor.onclick = function stopNivigation() { PDFView.page = id; return false; @@ -1045,12 +1079,18 @@ window.addEventListener('load', function webViewerLoad(evt) { } var scale = ('scale' in params) ? params.scale : 0; - PDFView.open(params.file || kDefaultURL, parseFloat(scale)); + var file = PDFJS.isFirefoxExtension ? + window.location.toString() : params.file || kDefaultURL; + PDFView.open(file, parseFloat(scale)); - if (!window.File || !window.FileReader || !window.FileList || !window.Blob) + if (PDFJS.isFirefoxExtension || !window.File || !window.FileReader || + !window.FileList || !window.Blob) { document.getElementById('fileInput').setAttribute('hidden', 'true'); - else + document.getElementById('fileInputSeperator') + .setAttribute('hidden', 'true'); + } else { document.getElementById('fileInput').value = null; + } if ('disableWorker' in params) PDFJS.disableWorker = (params['disableWorker'] === 'true'); @@ -1135,8 +1175,8 @@ function updateViewarea() { store.set('zoom', normalizedScaleValue); store.set('scrollLeft', Math.round(topLeft.x)); store.set('scrollTop', Math.round(topLeft.y)); - - document.getElementById('viewBookmark').href = pdfOpenParams; + var href = PDFView.getAnchorUrl(pdfOpenParams); + document.getElementById('viewBookmark').href = href; } window.addEventListener('scroll', function webViewerScroll(evt) {