blob: 33556b994fda8cafe273c55fb86deff19e3bed5e [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* Create a new PDFScriptingAPI. This provides a scripting interface to
* the PDF viewer so that it can be customized by things like print preview.
* @param {Window} window the window of the page containing the pdf viewer.
* @param {Object} plugin the plugin element containing the pdf viewer.
*/
function PDFScriptingAPI(window, plugin) {
this.loaded_ = false;
this.pendingScriptingMessages_ = [];
this.setPlugin(plugin);
window.addEventListener('message', function(event) {
if (event.origin != 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai') {
console.error('Received message that was not from the extension: ' +
event);
return;
}
switch (event.data.type) {
case 'viewport':
if (this.viewportChangedCallback_)
this.viewportChangedCallback_(event.data.pageX,
event.data.pageY,
event.data.pageWidth,
event.data.viewportWidth,
event.data.viewportHeight);
break;
case 'documentLoaded':
this.loaded_ = true;
if (this.loadCallback_)
this.loadCallback_();
break;
case 'getAccessibilityJSONReply':
if (this.accessibilityCallback_) {
this.accessibilityCallback_(event.data.json);
this.accessibilityCallback_ = null;
}
break;
}
}.bind(this), false);
}
PDFScriptingAPI.prototype = {
/**
* @private
* Send a message to the extension. If messages try to get sent before there
* is a plugin element set, then we queue them up and send them later (this
* can happen in print preview).
* @param {Object} message The message to send.
*/
sendMessage_: function(message) {
if (this.plugin_)
this.plugin_.postMessage(message, '*');
else
this.pendingScriptingMessages_.push(message);
},
/**
* Sets the plugin element containing the PDF viewer. The element will usually
* be passed into the PDFScriptingAPI constructor but may also be set later.
* @param {Object} plugin the plugin element containing the PDF viewer.
*/
setPlugin: function(plugin) {
this.plugin_ = plugin;
// Send an initialization message to the plugin indicating the window to
// respond to.
if (this.plugin_) {
this.sendMessage_({
type: 'setParentWindow'
});
// Now we can flush pending messages
while (this.pendingScriptingMessages_.length > 0)
this.sendMessage_(this.pendingScriptingMessages_.shift());
}
},
/**
* Sets the callback which will be run when the PDF viewport changes.
* @param {Function} callback the callback to be called.
*/
setViewportChangedCallback: function(callback) {
this.viewportChangedCallback_ = callback;
},
/**
* Sets the callback which will be run when the PDF document has finished
* loading. If the document is already loaded, it will be run immediately.
* @param {Function} callback the callback to be called.
*/
setLoadCallback: function(callback) {
this.loadCallback_ = callback;
if (this.loaded_ && callback)
callback();
},
/**
* Resets the PDF viewer into print preview mode.
* @param {string} url the url of the PDF to load.
* @param {boolean} grayscale whether or not to display the PDF in grayscale.
* @param {Array.<number>} pageNumbers an array of the page numbers.
* @param {boolean} modifiable whether or not the document is modifiable.
*/
resetPrintPreviewMode: function(url, grayscale, pageNumbers, modifiable) {
this.sendMessage_({
type: 'resetPrintPreviewMode',
url: url,
grayscale: grayscale,
pageNumbers: pageNumbers,
modifiable: modifiable
});
},
/**
* Load a page into the document while in print preview mode.
* @param {string} url the url of the pdf page to load.
* @param {number} index the index of the page to load.
*/
loadPreviewPage: function(url, index) {
this.sendMessage_({
type: 'loadPreviewPage',
url: url,
index: index
});
},
/**
* Get accessibility JSON for the document.
* @param {Function} callback a callback to be called with the accessibility
* json that has been retrieved.
* @param {number} [page] the 0-indexed page number to get accessibility data
* for. If this is not provided, data about the entire document is
* returned.
* @return {boolean} true if the function is successful, false if there is an
* outstanding request for accessibility data that has not been answered.
*/
getAccessibilityJSON: function(callback, page) {
if (this.accessibilityCallback_)
return false;
this.accessibilityCallback_ = callback;
var message = {
type: 'getAccessibilityJSON',
};
if (page || page == 0)
message.page = page;
this.sendMessage_(message);
return true;
},
/**
* Send a key event to the extension.
* @param {number} keyCode the key code to send to the extension.
*/
sendKeyEvent: function(keyCode) {
this.sendMessage_({
type: 'sendKeyEvent',
keyCode: keyCode
});
},
};
/**
* Creates a PDF viewer with a scripting interface. This is basically 1) an
* iframe which is navigated to the PDF viewer extension and 2) a scripting
* interface which provides access to various features of the viewer for use
* by print preview and accessibility.
* @param {string} src the source URL of the PDF to load initially.
* @return {HTMLIFrameElement} the iframe element containing the PDF viewer.
*/
function PDFCreateOutOfProcessPlugin(src) {
var iframe = window.document.createElement('iframe');
iframe.setAttribute(
'src',
'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/index.html?' + src);
var client = new PDFScriptingAPI(window);
iframe.onload = function() {
client.setPlugin(iframe.contentWindow);
};
// Add the functions to the iframe so that they can be called directly.
iframe.setViewportChangedCallback =
client.setViewportChangedCallback.bind(client);
iframe.setLoadCallback = client.setLoadCallback.bind(client);
iframe.resetPrintPreviewMode = client.resetPrintPreviewMode.bind(client);
iframe.loadPreviewPage = client.loadPreviewPage.bind(client);
iframe.sendKeyEvent = client.sendKeyEvent.bind(client);
return iframe;
}