Chromium Code Reviews| Index: chrome/browser/resources/pdf/pdf.js |
| diff --git a/chrome/browser/resources/pdf/pdf.js b/chrome/browser/resources/pdf/pdf.js |
| index 88e3d26bc5ee57ec2f9146b5605513fb2deda1ae..5e970849f0df5f2973e6634a6bb9854baa4512ec 100644 |
| --- a/chrome/browser/resources/pdf/pdf.js |
| +++ b/chrome/browser/resources/pdf/pdf.js |
| @@ -39,12 +39,11 @@ PDFViewer.MIN_TOOLBAR_OFFSET = 15; |
| /** |
| * Creates a new PDFViewer. There should only be one of these objects per |
| * document. |
| - * @param {Object} streamDetails The stream object which points to the data |
| - * contained in the PDF. |
| */ |
| -function PDFViewer(streamDetails) { |
| - this.streamDetails = streamDetails; |
| - this.loaded = false; |
| +function PDFViewer() { |
| + this.pluginLoaded_ = false; |
| + this.documentLoaded_ = false; |
|
Sam McNally
2015/01/06 05:31:03
The public "loaded" property is still used by the
raymes
2015/01/07 03:17:58
I removed the use of it.
|
| + |
| // The sizer element is placed behind the plugin element to cause scrollbars |
| // to be displayed in the window. It is sized according to the document size |
| @@ -54,110 +53,117 @@ function PDFViewer(streamDetails) { |
| this.pageIndicator_ = $('page-indicator'); |
| this.progressBar_ = $('progress-bar'); |
| this.passwordScreen_ = $('password-screen'); |
| - this.passwordScreen_.addEventListener('password-submitted', |
| - this.onPasswordSubmitted_.bind(this)); |
| this.errorScreen_ = $('error-screen'); |
| - // Create the viewport. |
| - this.viewport_ = new Viewport(window, |
| - this.sizer_, |
| - this.viewportChanged_.bind(this), |
| - this.beforeZoom_.bind(this), |
| - this.afterZoom_.bind(this), |
| - getScrollbarWidth()); |
| - var isPrintPreview = |
| - this.streamDetails.originalUrl.indexOf('chrome://print') == 0; |
| - // Create the plugin object dynamically so we can set its src. The plugin |
| - // element is sized to fill the entire window and is set to be fixed |
| - // positioning, acting as a viewport. The plugin renders into this viewport |
| - // according to the scroll position of the window. |
| - // |
| - // TODO(sammc): Remove special casing for print preview. This is currently |
| - // necessary because setting the src for an embed element triggers origin |
| - // checking and the PDF extension is not allowed to embed URLs with a scheme |
| - // of "chrome", which is used by print preview. |
| - this.plugin_ = document.createElement(isPrintPreview ? 'object' : 'embed'); |
| - // NOTE: The plugin's 'id' field must be set to 'plugin' since |
| - // chrome/renderer/printing/print_web_view_helper.cc actually references it. |
| - this.plugin_.id = 'plugin'; |
| - this.plugin_.type = 'application/x-google-chrome-pdf'; |
| - this.plugin_.addEventListener('message', this.handlePluginMessage_.bind(this), |
| - false); |
| - |
| // Handle scripting messages from outside the extension that wish to interact |
| - // with it. We also send a message indicating that extension has loaded and |
| - // is ready to receive messages. |
| + // with it. |
| window.addEventListener('message', this.handleScriptingMessage_.bind(this), |
| false); |
| - this.sendScriptingMessage_({type: 'readyToReceive'}); |
| - |
| - document.title = getFilenameFromURL(this.streamDetails.originalUrl); |
| - this.plugin_.setAttribute('src', this.streamDetails.originalUrl); |
| - this.plugin_.setAttribute('stream-url', this.streamDetails.streamUrl); |
| - var headers = ''; |
| - for (var header in this.streamDetails.responseHeaders) { |
| - headers += header + ': ' + |
| - this.streamDetails.responseHeaders[header] + '\n'; |
| - } |
| - this.plugin_.setAttribute('headers', headers); |
| - |
| - if (!this.streamDetails.embedded) |
| - this.plugin_.setAttribute('full-frame', ''); |
| - document.body.appendChild(this.plugin_); |
| - |
| - // TODO(raymes): Remove this spurious message once crbug.com/388606 is fixed. |
| - // This is a hack to initialize pepper sync scripting and avoid re-entrancy. |
| - this.plugin_.postMessage({ |
| - type: 'viewport', |
| - zoom: 1, |
| - xOffset: 0, |
| - yOffset: 0 |
| - }); |
| - |
| - // Setup the button event listeners. |
| - $('fit-to-width-button').addEventListener('click', |
| - this.viewport_.fitToWidth.bind(this.viewport_)); |
| - $('fit-to-page-button').addEventListener('click', |
| - this.viewport_.fitToPage.bind(this.viewport_)); |
| - $('zoom-in-button').addEventListener('click', |
| - this.viewport_.zoomIn.bind(this.viewport_)); |
| - $('zoom-out-button').addEventListener('click', |
| - this.viewport_.zoomOut.bind(this.viewport_)); |
| - $('save-button').addEventListener('click', this.save_.bind(this)); |
| - $('print-button').addEventListener('click', this.print_.bind(this)); |
| - |
| - // Setup the keyboard event listener. |
| - document.onkeydown = this.handleKeyEvent_.bind(this); |
| - |
| - // Set up the zoom API. |
| - if (this.shouldManageZoom_()) { |
| - chrome.tabs.setZoomSettings(this.streamDetails.tabId, |
| - {mode: 'manual', scope: 'per-tab'}, |
| - this.afterZoom_.bind(this)); |
| - chrome.tabs.onZoomChange.addListener(function(zoomChangeInfo) { |
| - if (zoomChangeInfo.tabId != this.streamDetails.tabId) |
| - return; |
| - // If the zoom level is close enough to the current zoom level, don't |
| - // change it. This avoids us getting into an infinite loop of zoom changes |
| - // due to floating point error. |
| - var MIN_ZOOM_DELTA = 0.01; |
| - var zoomDelta = Math.abs(this.viewport_.zoom - |
| - zoomChangeInfo.newZoomFactor); |
| - // We should not change zoom level when we are responsible for initiating |
| - // the zoom. onZoomChange() is called before setZoomComplete() callback |
| - // when we initiate the zoom. |
| - if ((zoomDelta > MIN_ZOOM_DELTA) && !this.setZoomInProgress_) |
| - this.viewport_.setZoom(zoomChangeInfo.newZoomFactor); |
| - }.bind(this)); |
| - } |
| - |
| - // Parse open pdf parameters. |
| - var paramsParser = new OpenPDFParamsParser(this.streamDetails.originalUrl); |
| - this.urlParams_ = paramsParser.urlParams; |
| } |
| PDFViewer.prototype = { |
| /** |
| + * Initialize the PDF viewer with the details of the stream object pointing to |
| + * the PDF data. |
| + * @param {Object} streamDetails The stream object which points to the data |
| + * contained in the PDF. |
| + */ |
| + init: function(streamDetails) { |
|
Sam McNally
2015/01/06 05:31:04
How about setStreamDetails?
raymes
2015/01/07 03:17:57
I ended up not needing the init function so I've g
|
| + this.streamDetails_ = streamDetails; |
| + |
| + // Create the viewport. |
| + this.viewport_ = new Viewport(window, |
| + this.sizer_, |
| + this.viewportChanged_.bind(this), |
| + this.beforeZoom_.bind(this), |
| + this.afterZoom_.bind(this), |
| + getScrollbarWidth()); |
| + |
| + document.title = getFilenameFromURL(this.streamDetails_.originalUrl); |
| + |
| + var isPrintPreview = |
| + this.streamDetails_.originalUrl.indexOf('chrome://print') == 0; |
| + // Create the plugin object dynamically so we can set its src. The plugin |
| + // element is sized to fill the entire window and is set to be fixed |
| + // positioning, acting as a viewport. The plugin renders into this viewport |
| + // according to the scroll position of the window. |
| + // |
| + // TODO(sammc): Remove special casing for print preview. This is currently |
| + // necessary because setting the src for an embed element triggers origin |
| + // checking and the PDF extension is not allowed to embed URLs with a scheme |
| + // of "chrome", which is used by print preview. |
| + this.plugin_ = document.createElement(isPrintPreview ? 'object' : 'embed'); |
| + // NOTE: The plugin's 'id' field must be set to 'plugin' since |
| + // chrome/renderer/printing/print_web_view_helper.cc actually references it. |
| + this.plugin_.id = 'plugin'; |
| + this.plugin_.type = 'application/x-google-chrome-pdf'; |
| + this.plugin_.addEventListener('message', |
| + this.handlePluginMessage_.bind(this), false); |
| + this.plugin_.setAttribute('src', this.streamDetails_.originalUrl); |
| + this.plugin_.setAttribute('stream-url', this.streamDetails_.streamUrl); |
| + var headers = ''; |
| + for (var header in this.streamDetails_.responseHeaders) { |
| + headers += header + ': ' + |
| + this.streamDetails_.responseHeaders[header] + '\n'; |
| + } |
| + this.plugin_.setAttribute('headers', headers); |
| + |
| + if (!this.streamDetails_.embedded) |
| + this.plugin_.setAttribute('full-frame', ''); |
| + document.body.appendChild(this.plugin_); |
| + |
| + // Add the password event listener. |
| + this.passwordScreen_.addEventListener('password-submitted', |
| + this.onPasswordSubmitted_.bind(this)); |
| + |
| + // Setup the button event listeners. |
| + $('fit-to-width-button').addEventListener('click', |
| + this.viewport_.fitToWidth.bind(this.viewport_)); |
| + $('fit-to-page-button').addEventListener('click', |
| + this.viewport_.fitToPage.bind(this.viewport_)); |
| + $('zoom-in-button').addEventListener('click', |
| + this.viewport_.zoomIn.bind(this.viewport_)); |
| + $('zoom-out-button').addEventListener('click', |
| + this.viewport_.zoomOut.bind(this.viewport_)); |
| + $('save-button').addEventListener('click', this.save_.bind(this)); |
| + $('print-button').addEventListener('click', this.print_.bind(this)); |
| + |
| + // Setup the keyboard event listener. |
| + document.onkeydown = this.handleKeyEvent_.bind(this); |
| + |
| + // Set up the zoom API. |
| + if (this.shouldManageZoom_()) { |
| + chrome.tabs.setZoomSettings(this.streamDetails_.tabId, |
| + {mode: 'manual', scope: 'per-tab'}, |
| + this.afterZoom_.bind(this)); |
| + chrome.tabs.onZoomChange.addListener(function(zoomChangeInfo) { |
| + if (zoomChangeInfo.tabId != this.streamDetails_.tabId) |
| + return; |
| + // If the zoom level is close enough to the current zoom level, don't |
| + // change it. This avoids us getting into an infinite loop of zoom |
| + // changes due to floating point error. |
| + var MIN_ZOOM_DELTA = 0.01; |
| + var zoomDelta = Math.abs(this.viewport_.zoom - |
| + zoomChangeInfo.newZoomFactor); |
| + // We should not change zoom level when we are responsible for |
| + // initiating the zoom. onZoomChange() is called before |
| + // setZoomComplete() callback when we initiate the zoom. |
| + if ((zoomDelta > MIN_ZOOM_DELTA) && !this.setZoomInProgress_) |
| + this.viewport_.setZoom(zoomChangeInfo.newZoomFactor); |
| + }.bind(this)); |
| + } |
| + |
| + // Parse open pdf parameters. |
| + var paramsParser = new OpenPDFParamsParser(this.streamDetails_.originalUrl); |
| + this.urlParams_ = paramsParser.urlParams; |
| + |
| + this.pluginLoaded_ = true; |
| + this.sendScriptingMessage_({ |
| + type: 'readyToReceive' |
| + }); |
| + }, |
| + |
| + /** |
| * @private |
| * Handle key events. These may come from the user directly or via the |
| * scripting API. |
| @@ -331,9 +337,7 @@ PDFViewer.prototype = { |
| if (this.lastViewportPosition_) |
| this.viewport_.position = this.lastViewportPosition_; |
| this.handleURLParams_(); |
| - this.loaded = true; |
| - var loadEvent = new Event('pdfload'); |
| - window.dispatchEvent(loadEvent); |
| + this.documentLoaded_ = true; |
| this.sendScriptingMessage_({ |
| type: 'documentLoaded' |
| }); |
| @@ -417,7 +421,7 @@ PDFViewer.prototype = { |
| this.errorScreen_.text = message.data.loadFailedString; |
| break; |
| case 'cancelStreamUrl': |
| - chrome.streamsPrivate.abort(this.streamDetails.streamUrl); |
| + chrome.streamsPrivate.abort(this.streamDetails_.streamUrl); |
| break; |
| } |
| }, |
| @@ -443,7 +447,7 @@ PDFViewer.prototype = { |
| var zoom = this.viewport_.zoom; |
| if (this.shouldManageZoom_() && !this.setZoomInProgress_) { |
| this.setZoomInProgress_ = true; |
| - chrome.tabs.setZoom(this.streamDetails.tabId, zoom, |
| + chrome.tabs.setZoom(this.streamDetails_.tabId, zoom, |
| this.setZoomComplete_.bind(this, zoom)); |
| } |
| this.plugin_.postMessage({ |
| @@ -465,7 +469,7 @@ PDFViewer.prototype = { |
| setZoomComplete_: function(lastZoom) { |
| var zoom = this.viewport_.zoom; |
| if (zoom != lastZoom) { |
| - chrome.tabs.setZoom(this.streamDetails.tabId, zoom, |
| + chrome.tabs.setZoom(this.streamDetails_.tabId, zoom, |
| this.setZoomComplete_.bind(this, zoom)); |
| } else { |
| this.setZoomInProgress_ = false; |
| @@ -578,6 +582,15 @@ PDFViewer.prototype = { |
| e.keyCode = message.data.keyCode; |
| this.handleKeyEvent_(e); |
| break; |
| + case 'setParentWindow': |
| + // Set the parent window to which messages will be sent. |
| + this.parentWindow_ = message.source; |
| + if (this.pluginLoaded_) { |
| + this.sendScriptingMessage_({ |
| + type: 'readyToReceive' |
| + }); |
| + } |
| + break; |
| } |
| }, |
| @@ -589,7 +602,8 @@ PDFViewer.prototype = { |
| * @param {Object} message the message to send. |
| */ |
| sendScriptingMessage_: function(message) { |
| - window.parent.postMessage(message, '*'); |
| + if (this.parentWindow_) |
|
Sam McNally
2015/01/06 05:31:03
Won't this lose messages?
raymes
2015/01/07 03:17:58
Yes, but that's ok. I've made it always send a doc
|
| + this.parentWindow_.postMessage(message, '*'); |
| }, |
| /** |
| @@ -599,8 +613,8 @@ PDFViewer.prototype = { |
| * containing page. |
| */ |
| shouldManageZoom_: function() { |
| - return !!(chrome.tabs && !this.streamDetails.embedded && |
| - this.streamDetails.tabId != -1); |
| + return !!(chrome.tabs && !this.streamDetails_.embedded && |
| + this.streamDetails_.tabId != -1); |
| }, |
| /** |