diff --git a/examples/components/simpleviewer.js b/examples/components/simpleviewer.js index c3315e8f1..60f0126de 100644 --- a/examples/components/simpleviewer.js +++ b/examples/components/simpleviewer.js @@ -30,6 +30,7 @@ PDFJS.workerSrc = '../../build/pdf.worker.js'; // PDFJS.cMapPacked = true; var DEFAULT_URL = '../../web/compressed.tracemonkey-pldi-09.pdf'; +var SEARCH_FOR = ''; // try 'Mozilla'; var container = document.getElementById('viewerContainer'); @@ -42,9 +43,19 @@ var pdfViewer = new PDFJS.PDFViewer({ }); pdfLinkService.setViewer(pdfViewer); +// (Optionally) enable find controller. +var pdfFindController = new PDFJS.PDFFindController({ + pdfViewer: pdfViewer +}); +pdfViewer.setFindController(pdfFindController); + container.addEventListener('pagesinit', function () { // We can use pdfViewer now, e.g. let's change default scale. pdfViewer.currentScaleValue = 'page-width'; + + if (SEARCH_FOR) { // We can try search for things + pdfFindController.executeCommand('find', {query: SEARCH_FOR}); + } }); // Loading document. diff --git a/extensions/firefox/tools/l10n.js b/extensions/firefox/tools/l10n.js index 9b2d24072..2e0684e06 100644 --- a/extensions/firefox/tools/l10n.js +++ b/extensions/firefox/tools/l10n.js @@ -1,14 +1,14 @@ -/* globals FirefoxCom */ 'use strict'; // Small subset of the webL10n API by Fabien Cazenave for pdf.js extension. (function(window) { var gLanguage = ''; + var gExternalLocalizerServices = null; // fetch an l10n objects function getL10nData(key) { - var response = FirefoxCom.requestSync('getStrings', key); + var response = gExternalLocalizerServices.getStrings(key); var data = JSON.parse(response); if (!data) { console.warn('[l10n] #' + key + ' missing for [' + gLanguage + ']'); @@ -94,8 +94,8 @@ } } - window.addEventListener('DOMContentLoaded', function() { - gLanguage = FirefoxCom.requestSync('getLocale', null); + function translateDocument() { + gLanguage = gExternalLocalizerServices.getLocale(); translateFragment(); @@ -104,6 +104,13 @@ evtObject.initEvent('localized', false, false); evtObject.language = gLanguage; window.dispatchEvent(evtObject); + } + + window.addEventListener('DOMContentLoaded', function() { + if (gExternalLocalizerServices) { + translateDocument(); + } + // ... else see setExternalLocalizerServices below }); // Public API @@ -128,6 +135,16 @@ return (rtlList.indexOf(shortCode) >= 0) ? 'rtl' : 'ltr'; }, + setExternalLocalizerServices: function (externalLocalizerServices) { + gExternalLocalizerServices = externalLocalizerServices; + + // ... in case if we missed DOMContentLoaded above. + if (window.document.readyState === 'interactive' || + window.document.readyState === 'complete') { + translateDocument(); + } + }, + // translate an element or document fragment translate: translateFragment }; diff --git a/make.js b/make.js index 0815b16d5..a6df503e9 100644 --- a/make.js +++ b/make.js @@ -129,7 +129,7 @@ target.generic = function() { var TMP_VIEWER = GENERIC_DIR + '/web/viewer.js.tmp'; cd('web/'); - var viewerBundleFiles = ['app.js']; + var viewerBundleFiles = ['app.js', 'mozPrintCallback_polyfill.js']; bundle('viewer.js', ROOT_DIR + TMP_VIEWER, viewerBundleFiles, 'pdfjs-dist/web/viewer', defines, true); cd(ROOT_DIR); @@ -179,6 +179,7 @@ target.components = function() { var bundleFiles = [ 'pdf_viewer.js', 'pdf_history.js', + 'pdf_find_controller.js', 'download_manager.js' ]; bundle('pdf_viewer.component.js', ROOT_DIR + TMP_PDF_VIEWER, bundleFiles, @@ -1131,7 +1132,8 @@ target.chromium = function() { var TMP_VIEWER = CHROME_BUILD_CONTENT_DIR + '/web/viewer.js.tmp'; cd('web/'); - var viewerBundleFiles = ['app.js', 'chromecom.js']; + var viewerBundleFiles = ['app.js', 'chromecom.js', + 'mozPrintCallback_polyfill.js']; bundle('viewer.js', ROOT_DIR + TMP_VIEWER, viewerBundleFiles, 'pdfjs-dist/web/viewer', defines, true); cd(ROOT_DIR); diff --git a/web/app.js b/web/app.js index b30bf0cb5..98c784779 100644 --- a/web/app.js +++ b/web/app.js @@ -19,8 +19,8 @@ (function (root, factory) { if (typeof define === 'function' && define.amd) { define('pdfjs-web/app', ['exports', 'pdfjs-web/ui_utils', - 'pdfjs-web/firefoxcom', 'pdfjs-web/download_manager', - 'pdfjs-web/pdf_history', 'pdfjs-web/preferences', 'pdfjs-web/pdf_sidebar', + 'pdfjs-web/download_manager', 'pdfjs-web/pdf_history', + 'pdfjs-web/preferences', 'pdfjs-web/pdf_sidebar', 'pdfjs-web/view_history', 'pdfjs-web/pdf_thumbnail_viewer', 'pdfjs-web/secondary_toolbar', 'pdfjs-web/password_prompt', 'pdfjs-web/pdf_presentation_mode', 'pdfjs-web/pdf_document_properties', @@ -28,46 +28,42 @@ 'pdfjs-web/pdf_rendering_queue', 'pdfjs-web/pdf_link_service', 'pdfjs-web/pdf_outline_viewer', 'pdfjs-web/overlay_manager', 'pdfjs-web/pdf_attachment_viewer', 'pdfjs-web/pdf_find_controller', - 'pdfjs-web/pdf_find_bar', 'pdfjs-web/mozPrintCallback_polyfill', - 'pdfjs-web/pdfjs'], + 'pdfjs-web/pdf_find_bar', 'pdfjs-web/pdfjs'], factory); } else if (typeof exports !== 'undefined') { - factory(exports, require('./ui_utils.js'), require('./firefoxcom.js'), - require('./download_manager.js'), require('./pdf_history.js'), - require('./preferences.js'), require('./pdf_sidebar.js'), - require('./view_history.js'), require('./pdf_thumbnail_viewer.js'), - require('./secondary_toolbar.js'), require('./password_prompt.js'), - require('./pdf_presentation_mode.js'), + factory(exports, require('./ui_utils.js'), require('./download_manager.js'), + require('./pdf_history.js'), require('./preferences.js'), + require('./pdf_sidebar.js'), require('./view_history.js'), + require('./pdf_thumbnail_viewer.js'), require('./secondary_toolbar.js'), + require('./password_prompt.js'), require('./pdf_presentation_mode.js'), require('./pdf_document_properties.js'), require('./hand_tool.js'), require('./pdf_viewer.js'), require('./pdf_rendering_queue.js'), require('./pdf_link_service.js'), require('./pdf_outline_viewer.js'), require('./overlay_manager.js'), require('./pdf_attachment_viewer.js'), require('./pdf_find_controller.js'), require('./pdf_find_bar.js'), - require('./mozPrintCallback_polyfill.js'), require('./pdfjs.js')); + require('./pdfjs.js')); } else { factory((root.pdfjsWebApp = {}), root.pdfjsWebUIUtils, - root.pdfjsWebFirefoxCom, root.pdfjsWebDownloadManager, - root.pdfjsWebPDFHistory, root.pdfjsWebPreferences, - root.pdfjsWebPDFSidebar, root.pdfjsWebViewHistory, - root.pdfjsWebPDFThumbnailViewer, root.pdfjsWebSecondaryToolbar, - root.pdfjsWebPasswordPrompt, root.pdfjsWebPDFPresentationMode, - root.pdfjsWebPDFDocumentProperties, root.pdfjsWebHandTool, - root.pdfjsWebPDFViewer, root.pdfjsWebPDFRenderingQueue, - root.pdfjsWebPDFLinkService, root.pdfjsWebPDFOutlineViewer, - root.pdfjsWebOverlayManager, root.pdfjsWebPDFAttachmentViewer, - root.pdfjsWebPDFFindController, root.pdfjsWebPDFFindBar, - root.pdfjsWebMozPrintCallbackPolyfill, root.pdfjsWebPDFJS); + root.pdfjsWebDownloadManager, root.pdfjsWebPDFHistory, + root.pdfjsWebPreferences, root.pdfjsWebPDFSidebar, + root.pdfjsWebViewHistory, root.pdfjsWebPDFThumbnailViewer, + root.pdfjsWebSecondaryToolbar, root.pdfjsWebPasswordPrompt, + root.pdfjsWebPDFPresentationMode, root.pdfjsWebPDFDocumentProperties, + root.pdfjsWebHandTool, root.pdfjsWebPDFViewer, + root.pdfjsWebPDFRenderingQueue, root.pdfjsWebPDFLinkService, + root.pdfjsWebPDFOutlineViewer, root.pdfjsWebOverlayManager, + root.pdfjsWebPDFAttachmentViewer, root.pdfjsWebPDFFindController, + root.pdfjsWebPDFFindBar, root.pdfjsWebPDFJS); } -}(this, function (exports, uiUtilsLib, firefoxComLib, downloadManagerLib, - pdfHistoryLib, preferencesLib, pdfSidebarLib, viewHistoryLib, +}(this, function (exports, uiUtilsLib, downloadManagerLib, pdfHistoryLib, + preferencesLib, pdfSidebarLib, viewHistoryLib, pdfThumbnailViewerLib, secondaryToolbarLib, passwordPromptLib, pdfPresentationModeLib, pdfDocumentPropertiesLib, handToolLib, pdfViewerLib, pdfRenderingQueueLib, pdfLinkServiceLib, pdfOutlineViewerLib, overlayManagerLib, pdfAttachmentViewerLib, pdfFindControllerLib, pdfFindBarLib, - mozPrintCallbackPolyfillLib, pdfjsLib) { + pdfjsLib) { -var FirefoxCom = firefoxComLib.FirefoxCom; var UNKNOWN_SCALE = uiUtilsLib.UNKNOWN_SCALE; var DEFAULT_SCALE_VALUE = uiUtilsLib.DEFAULT_SCALE_VALUE; var ProgressBar = uiUtilsLib.ProgressBar; @@ -75,8 +71,6 @@ var getPDFFileNameFromURL = uiUtilsLib.getPDFFileNameFromURL; var noContextMenuHandler = uiUtilsLib.noContextMenuHandler; var mozL10n = uiUtilsLib.mozL10n; var parseQueryString = uiUtilsLib.parseQueryString; -var DownloadManager = downloadManagerLib.DownloadManager || - firefoxComLib.DownloadManager; var PDFHistory = pdfHistoryLib.PDFHistory; var Preferences = preferencesLib.Preferences; var SidebarView = pdfSidebarLib.SidebarView; @@ -122,6 +116,23 @@ function configure(PDFJS) { //#endif } +var DefaultExernalServices = { + updateFindControlState: function (data) {}, + initPassiveLoading: function (callbacks) {}, + fallback: function (data, callback) {}, + reportTelemetry: function (data) {}, + createDownloadManager: function () { + return new downloadManagerLib.DownloadManager(); + }, + supportsIntegratedFind: false, + supportsDocumentFonts: true, + supportsDocumentColors: true, + supportedMouseWheelZoomModifierKeys: { + ctrlKey: true, + metaKey: true, + } +}; + var PDFViewerApplication = { initialBookmark: document.location.hash.substring(1), initialDestination: null, @@ -153,6 +164,8 @@ var PDFViewerApplication = { pdfAttachmentViewer: null, /** @type {ViewHistory} */ store: null, + /** @type {DownloadManager} */ + downloadManager: null, pageRotation: 0, isInitialViewSet: false, animationStartedPromise: null, @@ -162,6 +175,7 @@ var PDFViewerApplication = { preferenceDefaultZoomValue: '', isViewerEmbedded: (window.parent !== window), url: '', + externalServices: DefaultExernalServices, // called once when the document is loaded initialize: function pdfViewInitialize(appConfig) { @@ -175,6 +189,9 @@ var PDFViewerApplication = { var pdfLinkService = new PDFLinkService(); this.pdfLinkService = pdfLinkService; + var downloadManager = this.externalServices.createDownloadManager(); + this.downloadManager = downloadManager; + var container = appConfig.mainContainer; var viewer = appConfig.viewerContainer; this.pdfViewer = new PDFViewer({ @@ -182,7 +199,7 @@ var PDFViewerApplication = { viewer: viewer, renderingQueue: pdfRenderingQueue, linkService: pdfLinkService, - downloadManager: new DownloadManager() + downloadManager: downloadManager }); pdfRenderingQueue.setViewer(this.pdfViewer); pdfLinkService.setViewer(this.pdfViewer); @@ -204,9 +221,24 @@ var PDFViewerApplication = { pdfLinkService.setHistory(this.pdfHistory); this.findController = new PDFFindController({ - pdfViewer: this.pdfViewer, - integratedFind: this.supportsIntegratedFind + pdfViewer: this.pdfViewer }); + this.findController.onUpdateResultsCount = function (matchCount) { + if (this.supportsIntegratedFind) { + return; + } + this.findBar.updateResultsCount(matchCount); + }.bind(this); + this.findController.onUpdateState = function (state, previous, matchCount) { + if (this.supportsIntegratedFind) { + this.externalServices.updateFindControlState( + {result: state, findPrevious: previous}); + } else { + this.findBar.updateUIState(state, previous, matchCount); + } + }.bind(this); + this.findController.listenWindowEvents(); + this.pdfViewer.setFindController(this.findController); // FIXME better PDFFindBar constructor parameters @@ -214,8 +246,6 @@ var PDFViewerApplication = { findBarConfig.findController = this.findController; this.findBar = new PDFFindBar(findBarConfig); - this.findController.setFindBar(this.findBar); - this.overlayManager = OverlayManager; this.handTool = new HandTool({ @@ -257,7 +287,7 @@ var PDFViewerApplication = { this.pdfAttachmentViewer = new PDFAttachmentViewer({ container: appConfig.sidebar.attachmentsView, - downloadManager: new DownloadManager(), + downloadManager: downloadManager }); // FIXME better PDFSidebar constructor parameters @@ -398,30 +428,15 @@ var PDFViewerApplication = { }, get supportsIntegratedFind() { - var support = false; -//#if (FIREFOX || MOZCENTRAL) -// support = FirefoxCom.requestSync('supportsIntegratedFind'); -//#endif - - return pdfjsLib.shadow(this, 'supportsIntegratedFind', support); + return this.externalServices.supportsIntegratedFind; }, get supportsDocumentFonts() { - var support = true; -//#if (FIREFOX || MOZCENTRAL) -// support = FirefoxCom.requestSync('supportsDocumentFonts'); -//#endif - - return pdfjsLib.shadow(this, 'supportsDocumentFonts', support); + return this.externalServices.supportsDocumentFonts; }, get supportsDocumentColors() { - var support = true; -//#if (FIREFOX || MOZCENTRAL) -// support = FirefoxCom.requestSync('supportsDocumentColors'); -//#endif - - return pdfjsLib.shadow(this, 'supportsDocumentColors', support); + return this.externalServices.supportsDocumentColors; }, get loadingBar() { @@ -431,84 +446,40 @@ var PDFViewerApplication = { }, get supportedMouseWheelZoomModifierKeys() { - var support = { - ctrlKey: true, - metaKey: true, - }; -//#if (FIREFOX || MOZCENTRAL) -// support = FirefoxCom.requestSync('supportedMouseWheelZoomModifierKeys'); -//#endif - - return pdfjsLib.shadow(this, 'supportedMouseWheelZoomModifierKeys', - support); + return this.externalServices.supportedMouseWheelZoomModifierKeys; }, -//#if (FIREFOX || MOZCENTRAL) +//#if (FIREFOX || MOZCENTRAL || CHROME) initPassiveLoading: function pdfViewInitPassiveLoading() { - function FirefoxComDataRangeTransport(length, initialData) { - pdfjsLib.PDFDataRangeTransport.call(this, length, initialData); - } - FirefoxComDataRangeTransport.prototype = - Object.create(pdfjsLib.PDFDataRangeTransport.prototype); - FirefoxComDataRangeTransport.prototype.requestDataRange = - function FirefoxComDataRangeTransport_requestDataRange(begin, end) { - FirefoxCom.request('requestDataRange', { begin: begin, end: end }); - }; - FirefoxComDataRangeTransport.prototype.abort = - function FirefoxComDataRangeTransport_abort() { - // Sync call to ensure abort is really started. - FirefoxCom.requestSync('abortLoading', null); - }; + this.externalServices.initPassiveLoading({ + onOpenWithTransport: function (url, length, transport) { + PDFViewerApplication.open(url, {range: transport}); - var pdfDataRangeTransport; - - window.addEventListener('message', function windowMessage(e) { - if (e.source !== null) { - // The message MUST originate from Chrome code. - console.warn('Rejected untrusted message from ' + e.origin); - return; - } - var args = e.data; - - if (typeof args !== 'object' || !('pdfjsLoadAction' in args)) { - return; - } - switch (args.pdfjsLoadAction) { - case 'supportsRangedLoading': - pdfDataRangeTransport = - new FirefoxComDataRangeTransport(args.length, args.data); - - PDFViewerApplication.open(args.pdfUrl, - {range: pdfDataRangeTransport}); - - if (args.length) { - PDFViewerApplication.pdfDocumentProperties - .setFileSize(args.length); - } - break; - case 'range': - pdfDataRangeTransport.onDataRange(args.begin, args.chunk); - break; - case 'rangeProgress': - pdfDataRangeTransport.onDataProgress(args.loaded); - break; - case 'progressiveRead': - pdfDataRangeTransport.onDataProgressiveRead(args.chunk); - break; - case 'progress': - PDFViewerApplication.progress(args.loaded / args.total); - break; - case 'complete': - if (!args.data) { - PDFViewerApplication.error(mozL10n.get('loading_error', null, - 'An error occurred while loading the PDF.'), e); - break; - } - PDFViewerApplication.open(args.data); - break; + if (length) { + PDFViewerApplication.pdfDocumentProperties.setFileSize(length); + } + }, + onOpenWithData: function (data) { + PDFViewerApplication.open(data); + }, + onOpenWithURL: function (url, length, originalURL) { + var file = url, args = null; + if (length !== undefined) { + args = {length: length}; + } + if (originalURL !== undefined) { + file = {file: url, originalURL: originalURL}; + } + PDFViewerApplication.open(file, args); + }, + onError: function (e) { + PDFViewerApplication.error(mozL10n.get('loading_error', null, + 'An error occurred while loading the PDF.'), e); + }, + onProgress: function (loaded, total) { + PDFViewerApplication.progress(loaded / total); } }); - FirefoxCom.requestSync('initPassiveLoading', null); }, //#endif @@ -688,7 +659,7 @@ var PDFViewerApplication = { var url = this.url.split('#')[0]; var filename = getPDFFileNameFromURL(url); - var downloadManager = new DownloadManager(); + var downloadManager = this.downloadManager; downloadManager.onerror = function (err) { // This error won't really be helpful because it's likely the // fallback won't work either (or is already open). @@ -728,7 +699,7 @@ var PDFViewerApplication = { } this.fellback = true; var url = this.url.split('#')[0]; - FirefoxCom.request('fallback', { featureId: featureId, url: url }, + this.externalServices.fallback({ featureId: featureId, url: url }, function response(download) { if (!download) { return; @@ -1056,12 +1027,12 @@ var PDFViewerApplication = { } var formType = !info.IsAcroFormPresent ? null : info.IsXFAPresent ? 'xfa' : 'acroform'; - FirefoxCom.request('reportTelemetry', JSON.stringify({ + self.externalServices.reportTelemetry({ type: 'documentInfo', version: versionId, generator: generatorId, formType: formType - })); + }); //#endif }); }, @@ -1184,9 +1155,9 @@ var PDFViewerApplication = { } //#endif //#if (FIREFOX || MOZCENTRAL) - FirefoxCom.request('reportTelemetry', JSON.stringify({ + this.externalServices.reportTelemetry({ type: 'print' - })); + }); //#endif }, @@ -1482,7 +1453,7 @@ function webViewerInitialized() { appConfig.toolbar.download.addEventListener('click', SecondaryToolbar.downloadClick.bind(SecondaryToolbar)); -//#if (FIREFOX || MOZCENTRAL) +//#if (FIREFOX || MOZCENTRAL || CHROME) //PDFViewerApplication.setTitleUsingUrl(file); //PDFViewerApplication.initPassiveLoading(); //return; @@ -1513,11 +1484,6 @@ function webViewerInitialized() { PDFViewerApplication.open(file); } //#endif -//#if CHROME -//if (file) { -// ChromeCom.openPDFFile(file); -//} -//#endif } document.addEventListener('pagerendered', function (e) { @@ -1554,15 +1520,15 @@ document.addEventListener('pagerendered', function (e) { } //#endif //#if (FIREFOX || MOZCENTRAL) - FirefoxCom.request('reportTelemetry', JSON.stringify({ + PDFViewerApplication.externalServices.reportTelemetry({ type: 'pageInfo' - })); + }); // It is a good time to report stream and font types. PDFViewerApplication.pdfDocument.getStats().then(function (stats) { - FirefoxCom.request('reportTelemetry', JSON.stringify({ + PDFViewerApplication.externalServices.reportTelemetry({ type: 'documentStats', stats: stats - })); + }); }); //#endif }, true); @@ -2178,6 +2144,7 @@ window.addEventListener('afterprint', function afterPrint(evt) { })(); exports.PDFViewerApplication = PDFViewerApplication; +exports.DefaultExernalServices = DefaultExernalServices; // TODO remove circular reference of pdfjs-web/secondary_toolbar on app. secondaryToolbarLib._setApp(exports); diff --git a/web/chromecom.js b/web/chromecom.js index 1d6734c52..a31343585 100644 --- a/web/chromecom.js +++ b/web/chromecom.js @@ -13,27 +13,28 @@ * limitations under the License. */ -/* globals chrome */ +/* globals chrome, DEFAULT_PREFERENCES, DEFAULT_URL */ 'use strict'; (function (root, factory) { if (typeof define === 'function' && define.amd) { define('pdfjs-web/chromecom', ['exports', 'pdfjs-web/app', - 'pdfjs-web/overlay_manager', 'pdfjs-web/pdfjs'], factory); + 'pdfjs-web/overlay_manager', 'pdfjs-web/preferences', 'pdfjs-web/pdfjs'], + factory); } else if (typeof exports !== 'undefined') { factory(exports, require('./app.js'), require('./overlay_manager.js'), - require('./pdfjs.js')); + require('./preferences.js'), require('./pdfjs.js')); } else { factory((root.pdfjsWebChromeCom = {}), root.pdfjsWebApp, - root.pdfjsWebOverlayManager, root.pdfjsWebPDFJS); + root.pdfjsWebOverlayManager, root.pdfjsWebPreferences, + root.pdfjsWebPDFJS); } -}(this, function (exports, app, overlayManager, pdfjsLib) { +}(this, function (exports, app, overlayManager, preferences, pdfjsLib) { //#if CHROME -//#if !CHROME - if (true) { return; } // TODO ensure nothing depends on this module. -//#endif var PDFViewerApplication = app.PDFViewerApplication; + var DefaultExernalServices = app.DefaultExernalServices; var OverlayManager = overlayManager.OverlayManager; + var Preferences = preferences.Preferences; var ChromeCom = {}; /** @@ -64,11 +65,12 @@ }; /** - * Opens a PDF file with the PDF viewer. + * Resolves a PDF file path and attempts to detects length. * * @param {String} file Absolute URL of PDF file. + * @param {Function} callback A callback with resolved URL and file length. */ - ChromeCom.openPDFFile = function ChromeCom_openPDFFile(file) { + ChromeCom.resolvePDFFile = function ChromeCom_resolvePDFFile(file, callback) { // Expand drive:-URLs to filesystem URLs (Chrome OS) file = file.replace(/^drive:/i, 'filesystem:' + location.origin + '/external/'); @@ -81,10 +83,7 @@ var streamUrl = response.streamUrl; if (streamUrl) { console.log('Found data stream for ' + file); - PDFViewerApplication.open(streamUrl, { - length: response.contentLength - }); - PDFViewerApplication.setTitleUsingUrl(file); + callback(streamUrl, response.contentLength, file); return; } if (isFTPFile && !response.extensionSupportsFTP) { @@ -108,16 +107,14 @@ resolveLocalFileSystemURL(file, function onResolvedFSURL(fileEntry) { fileEntry.file(function(fileObject) { var blobUrl = URL.createObjectURL(fileObject); - PDFViewerApplication.open(blobUrl, { - length: fileObject.size - }); + callback(blobUrl, fileObject.size); }); }, function onFileSystemError(error) { // This should not happen. When it happens, just fall back to the // usual way of getting the File's data (via the Web worker). console.warn('Cannot resolve file ' + file + ', ' + error.name + ' ' + error.message); - PDFViewerApplication.open(file); + callback(file); }); return; } @@ -126,7 +123,7 @@ // There is no UI to input a different URL, so this assumption will hold // for now. setReferer(file, function() { - PDFViewerApplication.open(file); + callback(file); }); return; } @@ -145,7 +142,7 @@ } isAllowedFileSchemeAccess(function(isAllowedAccess) { if (isAllowedAccess) { - PDFViewerApplication.open(file); + callback(file); } else { requestAccessToLocalFile(file); } @@ -153,7 +150,7 @@ }); return; } - PDFViewerApplication.open(file); + callback(file); }); }; @@ -324,6 +321,55 @@ } } + Preferences._writeToStorage = function (prefObj) { + return new Promise(function (resolve) { + if (prefObj === DEFAULT_PREFERENCES) { + var keysToRemove = Object.keys(DEFAULT_PREFERENCES); + // If the storage is reset, remove the keys so that the values from + // managed storage are applied again. + chrome.storage.local.remove(keysToRemove, function() { + resolve(); + }); + } else { + chrome.storage.local.set(prefObj, function() { + resolve(); + }); + } + }); + }; + + Preferences._readFromStorage = function (prefObj) { + return new Promise(function (resolve) { + if (chrome.storage.managed) { + // Get preferences as set by the system administrator. + // See extensions/chromium/preferences_schema.json for more information. + // These preferences can be overridden by the user. + chrome.storage.managed.get(DEFAULT_PREFERENCES, getPreferences); + } else { + // Managed storage not supported, e.g. in old Chromium versions. + getPreferences(DEFAULT_PREFERENCES); + } + + function getPreferences(defaultPrefs) { + if (chrome.runtime.lastError) { + // Managed storage not supported, e.g. in Opera. + defaultPrefs = DEFAULT_PREFERENCES; + } + chrome.storage.local.get(defaultPrefs, function(readPrefs) { + resolve(readPrefs); + }); + } + }); + }; + + var ChromeExternalServices = Object.create(DefaultExernalServices); + ChromeExternalServices.initPassiveLoading = function (callbacks) { + ChromeCom.resolvePDFFile(DEFAULT_URL, function (url, length, originalURL) { + callbacks.onOpenWithURL(url, length, originalURL); + }); + }; + PDFViewerApplication.externalServices = ChromeExternalServices; + exports.ChromeCom = ChromeCom; //#endif })); diff --git a/web/firefoxcom.js b/web/firefoxcom.js index 9a60097a9..8dc01f192 100644 --- a/web/firefoxcom.js +++ b/web/firefoxcom.js @@ -18,19 +18,18 @@ (function (root, factory) { if (typeof define === 'function' && define.amd) { define('pdfjs-web/firefoxcom', ['exports', 'pdfjs-web/preferences', - 'pdfjs-web/pdfjs'], factory); + 'pdfjs-web/app', 'pdfjs-web/pdfjs'], factory); } else if (typeof exports !== 'undefined') { - factory(exports, require('./preferences.js'), require('./pdfjs.js')); + factory(exports, require('./preferences.js'), require('./app.js'), + require('./pdfjs.js')); } else { factory((root.pdfjsWebFirefoxCom = {}), root.pdfjsWebPreferences, - root.pdfjsWebPDFJS); + root.pdfjsWebApp, root.pdfjsWebPDFJS); } -}(this, function (exports, preferences, pdfjsLib) { +}(this, function (exports, preferences, app, pdfjsLib) { //#if FIREFOX || MOZCENTRAL -//#if !(FIREFOX || MOZCENTRAL) - if (true) { return; } // TODO ensure nothing depends on this module. -//#endif var Preferences = preferences.Preferences; +var PDFViewerApplication = app.PDFViewerApplication; var FirefoxCom = (function FirefoxComClosure() { return { @@ -149,6 +148,117 @@ Preferences._readFromStorage = function (prefObj) { }); }; +function FirefoxComDataRangeTransport(length, initialData) { + pdfjsLib.PDFDataRangeTransport.call(this, length, initialData); +} +FirefoxComDataRangeTransport.prototype = + Object.create(pdfjsLib.PDFDataRangeTransport.prototype); +FirefoxComDataRangeTransport.prototype.requestDataRange = + function FirefoxComDataRangeTransport_requestDataRange(begin, end) { + FirefoxCom.request('requestDataRange', { begin: begin, end: end }); +}; +FirefoxComDataRangeTransport.prototype.abort = + function FirefoxComDataRangeTransport_abort() { + // Sync call to ensure abort is really started. + FirefoxCom.requestSync('abortLoading', null); +}; + +PDFViewerApplication.externalServices = { + updateFindControlState: function (data) { + FirefoxCom.request('updateFindControlState', data); + }, + + initPassiveLoading: function (callbacks) { + var pdfDataRangeTransport; + + window.addEventListener('message', function windowMessage(e) { + if (e.source !== null) { + // The message MUST originate from Chrome code. + console.warn('Rejected untrusted message from ' + e.origin); + return; + } + var args = e.data; + + if (typeof args !== 'object' || !('pdfjsLoadAction' in args)) { + return; + } + switch (args.pdfjsLoadAction) { + case 'supportsRangedLoading': + pdfDataRangeTransport = + new FirefoxComDataRangeTransport(args.length, args.data); + + callbacks.onOpenWithTransport(args.pdfUrl, args.length, + pdfDataRangeTransport); + break; + case 'range': + pdfDataRangeTransport.onDataRange(args.begin, args.chunk); + break; + case 'rangeProgress': + pdfDataRangeTransport.onDataProgress(args.loaded); + break; + case 'progressiveRead': + pdfDataRangeTransport.onDataProgressiveRead(args.chunk); + break; + case 'progress': + callbacks.onProgress(args.loaded, args.total); + break; + case 'complete': + if (!args.data) { + callbacks.onError(args.errorCode); + break; + } + callbacks.onOpenWithData(args.data); + break; + } + }); + FirefoxCom.requestSync('initPassiveLoading', null); + }, + + fallback: function (data, callback) { + FirefoxCom.request('fallback', data, callback); + }, + + reportTelemetry: function (data) { + FirefoxCom.request('reportTelemetry', JSON.stringify(data)); + }, + + createDownloadManager: function () { + return new DownloadManager(); + }, + + get supportsIntegratedFind() { + var support = FirefoxCom.requestSync('supportsIntegratedFind'); + return pdfjsLib.shadow(this, 'supportsIntegratedFind', support); + }, + + get supportsDocumentFonts() { + var support = FirefoxCom.requestSync('supportsDocumentFonts'); + return pdfjsLib.shadow(this, 'supportsDocumentFonts', support); + }, + + get supportsDocumentColors() { + var support = FirefoxCom.requestSync('supportsDocumentColors'); + return pdfjsLib.shadow(this, 'supportsDocumentColors', support); + }, + + get supportedMouseWheelZoomModifierKeys() { + var support = FirefoxCom.requestSync('supportedMouseWheelZoomModifierKeys'); + return pdfjsLib.shadow(this, 'supportedMouseWheelZoomModifierKeys', + support); + }, +}; + +//// l10n.js for Firefox extension expects services to be set. +document.mozL10n.setExternalLocalizerServices({ + getLocale: function () { + return FirefoxCom.requestSync('getLocale', null); + }, + + getStrings: function (key) { + return FirefoxCom.requestSync('getStrings', key); + } +}); + exports.DownloadManager = DownloadManager; exports.FirefoxCom = FirefoxCom; //#endif diff --git a/web/pdf_find_controller.js b/web/pdf_find_controller.js index ac813f7c2..b61a3642b 100644 --- a/web/pdf_find_controller.js +++ b/web/pdf_find_controller.js @@ -17,18 +17,16 @@ (function (root, factory) { if (typeof define === 'function' && define.amd) { - define('pdfjs-web/pdf_find_controller', ['exports', - 'pdfjs-web/ui_utils', 'pdfjs-web/firefoxcom'], factory); + define('pdfjs-web/pdf_find_controller', ['exports', 'pdfjs-web/ui_utils'], + factory); } else if (typeof exports !== 'undefined') { - factory(exports, require('./ui_utils.js'), require('./firefoxcom.js')); + factory(exports, require('./ui_utils.js')); } else { - factory((root.pdfjsWebPDFFindController = {}), root.pdfjsWebUIUtils, - root.pdfjsWebFirefoxCom); + factory((root.pdfjsWebPDFFindController = {}), root.pdfjsWebUIUtils); } }(this, function (exports, uiUtils, firefoxCom) { var scrollIntoView = uiUtils.scrollIntoView; -var FirefoxCom = firefoxCom.FirefoxCom; var FindStates = { FIND_FOUND: 0, @@ -61,31 +59,32 @@ var CHARACTERS_TO_NORMALIZE = { var PDFFindController = (function PDFFindControllerClosure() { function PDFFindController(options) { this.pdfViewer = options.pdfViewer || null; - this.integratedFind = options.integratedFind || false; - this.findBar = options.findBar || null; + + this.onUpdateResultsCount = null; + this.onUpdateState = null; this.reset(); // Compile the regular expression for text normalization once. var replace = Object.keys(CHARACTERS_TO_NORMALIZE).join(''); this.normalizationRegex = new RegExp('[' + replace + ']', 'g'); - - var events = [ - 'find', - 'findagain', - 'findhighlightallchange', - 'findcasesensitivitychange' - ]; - this.handleEvent = this.handleEvent.bind(this); - - for (var i = 0, len = events.length; i < len; i++) { - window.addEventListener(events[i], this.handleEvent); - } } PDFFindController.prototype = { - setFindBar: function PDFFindController_setFindBar(findBar) { - this.findBar = findBar; + listenWindowEvents: function PDFFindController_listenWindowEvents() { + var events = [ + 'find', + 'findagain', + 'findhighlightallchange', + 'findcasesensitivitychange' + ]; + var handleEvent = function (e) { + this.executeCommand(e.type, e.detail); + }.bind(this); + + for (var i = 0, len = events.length; i < len; i++) { + window.addEventListener(events[i], handleEvent); + } }, reset: function PDFFindController_reset() { @@ -199,18 +198,18 @@ var PDFFindController = (function PDFFindControllerClosure() { extractPageText(0); }, - handleEvent: function PDFFindController_handleEvent(e) { - if (this.state === null || e.type !== 'findagain') { + executeCommand: function PDFFindController_executeCommand(cmd, state) { + if (this.state === null || cmd !== 'findagain') { this.dirtyMatch = true; } - this.state = e.detail; + this.state = state; this.updateUIState(FindStates.FIND_PENDING); this.firstPagePromise.then(function() { this.extractText(); clearTimeout(this.findTimeout); - if (e.type === 'find') { + if (cmd === 'find') { // Only trigger the find action after 250ms of silence. this.findTimeout = setTimeout(this.nextMatch.bind(this), 250); } else { @@ -408,24 +407,15 @@ var PDFFindController = (function PDFFindControllerClosure() { updateUIResultsCount: function PDFFindController_updateUIResultsCount() { - if (this.findBar === null) { - throw new Error('PDFFindController is not initialized with a ' + - 'PDFFindBar instance.'); + if (this.onUpdateResultsCount) { + this.onUpdateResultsCount(this.matchCount); } - this.findBar.updateResultsCount(this.matchCount); }, updateUIState: function PDFFindController_updateUIState(state, previous) { - if (this.integratedFind) { - FirefoxCom.request('updateFindControlState', - { result: state, findPrevious: previous }); - return; + if (this.onUpdateState) { + this.onUpdateState(state, previous, this.matchCount); } - if (this.findBar === null) { - throw new Error('PDFFindController is not initialized with a ' + - 'PDFFindBar instance.'); - } - this.findBar.updateUIState(state, previous, this.matchCount); } }; return PDFFindController; diff --git a/web/pdf_viewer.component.js b/web/pdf_viewer.component.js index 53da359ef..9f4cd129c 100644 --- a/web/pdf_viewer.component.js +++ b/web/pdf_viewer.component.js @@ -50,6 +50,8 @@ PDFJS.DefaultAnnotationLayerFactory = pdfViewerLibs.pdfjsWebAnnotationLayerBuilder.DefaultAnnotationLayerFactory; PDFJS.PDFHistory = pdfViewerLibs.pdfjsWebPDFHistory.PDFHistory; + PDFJS.PDFFindController = + pdfViewerLibs.pdfjsWebPDFFindController.PDFFindController; PDFJS.DownloadManager = pdfViewerLibs.pdfjsWebDownloadManager.DownloadManager; PDFJS.ProgressBar = pdfViewerLibs.pdfjsWebUIUtils.ProgressBar; diff --git a/web/preferences.js b/web/preferences.js index e3c28f39a..ec43653f3 100644 --- a/web/preferences.js +++ b/web/preferences.js @@ -161,49 +161,6 @@ var Preferences = { } }; -//#if CHROME -//Preferences._writeToStorage = function (prefObj) { -// return new Promise(function (resolve) { -// if (prefObj == DEFAULT_PREFERENCES) { -// var keysToRemove = Object.keys(DEFAULT_PREFERENCES); -// // If the storage is reset, remove the keys so that the values from -// // managed storage are applied again. -// chrome.storage.local.remove(keysToRemove, function() { -// resolve(); -// }); -// } else { -// chrome.storage.local.set(prefObj, function() { -// resolve(); -// }); -// } -// }); -//}; -// -//Preferences._readFromStorage = function (prefObj) { -// return new Promise(function (resolve) { -// if (chrome.storage.managed) { -// // Get preferences as set by the system administrator. -// // See extensions/chromium/preferences_schema.json for more information. -// // These preferences can be overridden by the user. -// chrome.storage.managed.get(DEFAULT_PREFERENCES, getPreferences); -// } else { -// // Managed storage not supported, e.g. in old Chromium versions. -// getPreferences(DEFAULT_PREFERENCES); -// } -// -// function getPreferences(defaultPrefs) { -// if (chrome.runtime.lastError) { -// // Managed storage not supported, e.g. in Opera. -// defaultPrefs = DEFAULT_PREFERENCES; -// } -// chrome.storage.local.get(defaultPrefs, function(readPrefs) { -// resolve(readPrefs); -// }); -// } -// }); -//}; -//#endif - //#if !(FIREFOX || MOZCENTRAL || CHROME) Preferences._writeToStorage = function (prefObj) { return new Promise(function (resolve) { diff --git a/web/viewer.js b/web/viewer.js index 2e3890a48..a6bb8d3a3 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -166,7 +166,7 @@ function webViewerLoad() { var config = getViewerConfiguration(); //#if !PRODUCTION require.config({paths: {'pdfjs': '../src', 'pdfjs-web': '.'}}); - require(['pdfjs-web/app'], function (web) { + require(['pdfjs-web/app', 'mozPrintCallback_polyfill.js'], function (web) { window.PDFViewerApplication = web.PDFViewerApplication; web.PDFViewerApplication.run(config); });