Browse Source

Merge pull request #196 from fancycode/pdfjs_sandbox

Run pdf.js rendering in sandboxed iframe
pull/200/head
Simon Eisenmann 10 years ago
parent
commit
044102a5bd
  1. 7
      build/build.js
  2. 11
      src/styles/components/_presentation.scss
  3. 214
      static/js/directives/pdfcanvas.js
  4. 25
      static/js/directives/presentation.js
  5. 2
      static/js/directives/youtubevideo.js
  6. 281
      static/js/sandboxes/pdf.js
  7. 1
      static/js/sandboxes/youtube.js
  8. 20
      static/js/services/sandbox.js
  9. 34
      static/partials/pdfcanvas_sandbox.html

7
build/build.js

@ -83,6 +83,13 @@ @@ -83,6 +83,13 @@
override: {
skipModuleInsertion: true
}
},
{
name: 'sandboxes/pdf',
dir: './out/sandboxes',
override: {
skipModuleInsertion: true
}
}
]
})

11
src/styles/components/_presentation.scss

@ -197,12 +197,13 @@ @@ -197,12 +197,13 @@
.canvasContainer {
height: 100%;
width: 100%;
}
overflow: hidden;
canvas {
display: block;
margin: 0 auto;
position: relative;
iframe {
border: 0;
height: 100%;
width: 100%;
}
}
.odfcanvas {

214
static/js/directives/pdfcanvas.js

@ -20,9 +20,9 @@ @@ -20,9 +20,9 @@
*/
"use strict";
define(['require', 'underscore', 'jquery'], function(require, _, $) {
define(['require', 'underscore', 'jquery', 'text!partials/pdfcanvas_sandbox.html'], function(require, _, $, sandboxTemplate) {
return ["$window", "$compile", "translation", "safeApply", function($window, $compile, translation, safeApply) {
return ["$window", "$compile", "$http", "translation", "safeApply", 'restURL', 'sandbox', function($window, $compile, $http, translation, safeApply, restURL, sandbox) {
var pdfjs = null;
@ -30,28 +30,71 @@ define(['require', 'underscore', 'jquery'], function(require, _, $) { @@ -30,28 +30,71 @@ define(['require', 'underscore', 'jquery'], function(require, _, $) {
var container = $($element);
var PDFCanvas = function(scope, canvases) {
var pdfCanvas;
var template = sandboxTemplate;
template = template.replace(/__PARENT_ORIGIN__/g, $window.location.protocol + "//" + $window.location.host);
template = template.replace(/__PDFJS_SANDBOX_JS_URL__/g, restURL.createAbsoluteUrl(require.toUrl('sandboxes/pdf') + ".js"));
template = template.replace(/__PDFJS_URL__/g, restURL.createAbsoluteUrl(require.toUrl('pdf') + ".js"));
template = template.replace(/__PDFJS_WORKER_URL__/g, restURL.createAbsoluteUrl(require.toUrl('pdf.worker') + ".js"));
template = template.replace(/__PDFJS_COMPATIBILITY_URL__/g, restURL.createAbsoluteUrl(require.toUrl('libs/pdf/compatibility') + ".js"));
var sandboxApi = sandbox.createSandbox($("iframe", container)[0], template);
sandboxApi.e.on("message", function(event, message) {
var msg = message.data;
var data = msg[msg.type] || {};
switch (msg.type) {
case "ready":
break;
case "pdfjs.loading":
$scope.$apply(function(scope) {
scope.$emit("presentationLoading", data.source);
});
break;
case "pdfjs.loaded":
pdfCanvas._pdfLoaded(data.source, data.doc);
break;
case "pdfjs.loadError":
pdfCanvas._pdfLoadError(data.source, data.error);
break;
case "pdfjs.pageLoaded":
pdfCanvas._pageLoaded(data.page);
break;
case "pdfjs.pageLoadError":
pdfCanvas._pageLoadError(data.page, data.error);
break;
case "pdfjs.renderingPage":
$scope.$apply(function(scope) {
scope.$emit("presentationPageRendering", data.page);
});
break;
case "pdfjs.pageRendered":
pdfCanvas._pageRendered(data.page);
break;
case "pdfjs.pageRenderError":
pdfCanvas._pageRenderError(data.page, data.error);
break;
case "pdfjs.keyUp":
$scope.$apply(function(scope) {
scope.$emit("keyUp", data.key);
});
break;
default:
console.log("Unknown message received", message);
break;
}
});
var PDFCanvas = function(scope) {
this.scope = scope;
this.canvases = canvases;
this.doc = null;
this.currentPage = null;
this.currentPageNumber = null;
this.pendingPageNumber = null;
this.renderTask = null;
this.url = null;
};
PDFCanvas.prototype._close = function() {
this._stopRendering();
if (this.currentPage) {
this.currentPage.destroy();
this.currentPage = null;
}
if (this.doc) {
this.doc.cleanup();
this.doc.destroy();
this.doc = null;
}
PDFCanvas.prototype.close = function() {
sandboxApi.postMessage("closeFile", {"close": true});
if (this.url) {
URL.revokeObjectURL(this.url);
this.url = null;
@ -59,20 +102,13 @@ define(['require', 'underscore', 'jquery'], function(require, _, $) { @@ -59,20 +102,13 @@ define(['require', 'underscore', 'jquery'], function(require, _, $) {
this.pendingPageNumber = null;
this.currentPageNumber = -1;
this.maxPageNumber = -1;
// clear visible canvas so it's empty when we show the next document
var canvas = this.canvases[this.scope.canvasIndex];
canvas.getContext("2d").clearRect(0, 0, canvas.width, canvas.height);
};
PDFCanvas.prototype.close = function() {
this._close();
};
PDFCanvas.prototype.open = function(presentation) {
this.scope.$emit("presentationOpening", presentation);
presentation.open(_.bind(function(source) {
console.log("Loading PDF from", source);
this._close();
this.close();
if (typeof source === "string") {
// got a url
this._openFile(source);
@ -100,7 +136,6 @@ define(['require', 'underscore', 'jquery'], function(require, _, $) { @@ -100,7 +136,6 @@ define(['require', 'underscore', 'jquery'], function(require, _, $) {
this.doc = doc;
this.maxPageNumber = doc.numPages;
this.currentPageNumber = -1;
console.log("PDF loaded", doc);
scope.$emit("presentationLoaded", source, doc);
}, this));
};
@ -127,43 +162,30 @@ define(['require', 'underscore', 'jquery'], function(require, _, $) { @@ -127,43 +162,30 @@ define(['require', 'underscore', 'jquery'], function(require, _, $) {
}, this));
};
PDFCanvas.prototype._doOpenFile = function(source) {
this.scope.$emit("presentationLoading", source);
pdfjs.getDocument(source).then(_.bind(function(doc) {
this._pdfLoaded(source, doc);
}, this), _.bind(function(error, exception) {
this._pdfLoadError(source, error, exception);
}, this));
};
PDFCanvas.prototype._openFile = function(source) {
if (pdfjs === null) {
// load pdf.js lazily
require(['pdf'], _.bind(function(pdf) {
pdf.workerSrc = require.toUrl('pdf.worker') + ".js";
console.log("Using pdf.js " + pdf.version + " (build " + pdf.build + ")");
pdfjs = pdf;
this._doOpenFile(source);
if (typeof(source) === "string") {
// we can't load urls from inside the sandbox, do so here and transmit the contents
$http.get(source, {
responseType: "arraybuffer"
}).then(_.bind(function(response) {
this._openFile(response.data);
}, this), _.bind(function(error) {
this._pdfLoadError(source, error);
}, this));
} else {
this._doOpenFile(source);
return;
}
console.log("Opening file", source);
sandboxApi.postMessage("openFile", {"source": source});
};
PDFCanvas.prototype._pageLoaded = function(page, pageObject) {
PDFCanvas.prototype._pageLoaded = function(page) {
this.scope.$apply(_.bind(function(scope) {
console.log("Got page", pageObject);
scope.$emit("presentationPageLoaded", page, pageObject);
this.currentPage = pageObject;
this.drawPage(pageObject);
scope.$emit("presentationPageLoaded", page);
}, this));
};
PDFCanvas.prototype._pageLoadError = function(page, error, exception) {
console.error("Could not load page", page, error, exception);
PDFCanvas.prototype._pageLoadError = function(page, error) {
var loadErrorMessage;
if (error) {
loadErrorMessage = translation._("An error occurred while loading the PDF page (%s).", error);
@ -181,36 +203,19 @@ define(['require', 'underscore', 'jquery'], function(require, _, $) { @@ -181,36 +203,19 @@ define(['require', 'underscore', 'jquery'], function(require, _, $) {
}
console.log("Showing page", page, "/", this.maxPageNumber);
if (this.currentPage) {
this.currentPage.destroy();
this.currentPage = null;
}
this.currentPageNumber = page;
this.scope.$emit("presentationPageLoading", page);
this.doc.getPage(page).then(_.bind(function(pageObject) {
this._pageLoaded(page, pageObject);
}, this), _.bind(function(error, exception) {
this._pageLoadError(page, error, exception);
}, this));
sandboxApi.postMessage("loadPage", {"page": page});
};
PDFCanvas.prototype._pageRendered = function(pageObject) {
this.renderTask = null;
PDFCanvas.prototype._pageRendered = function(page) {
this.scope.$apply(_.bind(function(scope) {
console.log("Rendered page", pageObject.pageNumber);
this.scope.$emit("presentationPageRendered", pageObject.pageNumber, this.maxPageNumber);
// ...and flip the buffers...
scope.canvasIndex = 1 - scope.canvasIndex;
this.scope.$emit("presentationPageRendered", page, this.maxPageNumber);
this.showQueuedPage();
}, this));
};
PDFCanvas.prototype._pageRenderError = function(pageObject, error, exception) {
if (error === "cancelled") {
return;
}
console.error("Could not render page", pageObject, error, exception);
this.renderTask = null;
PDFCanvas.prototype._pageRenderError = function(page, error) {
var loadErrorMessage;
if (error) {
loadErrorMessage = translation._("An error occurred while rendering the PDF page (%s).", error);
@ -218,59 +223,12 @@ define(['require', 'underscore', 'jquery'], function(require, _, $) { @@ -218,59 +223,12 @@ define(['require', 'underscore', 'jquery'], function(require, _, $) {
loadErrorMessage = translation._("An unknown error occurred while rendering the PDF page.");
}
this.scope.$apply(_.bind(function(scope) {
scope.$emit("presentationPageRenderError", pageObject.pageNumber, this.maxPageNumber, loadErrorMessage);
}, this));
};
PDFCanvas.prototype._stopRendering = function() {
if (this.renderTask) {
if (this.renderTask.internalRenderTask && this.renderTask.internalRenderTask.cancel) {
this.renderTask.internalRenderTask.cancel();
}
this.renderTask = null;
}
}
PDFCanvas.prototype.drawPage = function(pageObject) {
var pdfView = pageObject.view;
var pdfWidth = pdfView[2] - pdfView[0];
var pdfHeight = pdfView[3] - pdfView[1];
var w = container.width();
var h = container.height();
var scale = w / pdfWidth;
if (pdfHeight * scale > h) {
scale = container.height() / pdfHeight;
}
// use double-buffering to avoid flickering while
// the new page is rendered...
var canvas = this.canvases[1 - this.scope.canvasIndex];
var viewport = pageObject.getViewport(scale);
canvas.width = Math.round(viewport.width);
canvas.height = Math.round(viewport.height);
var renderContext = {
canvasContext: canvas.getContext("2d"),
viewport: viewport
};
console.log("Rendering page", pageObject);
this.scope.$emit("presentationPageRendering", pageObject.pageNumber);
// TODO(fancycode): also render images in different resolutions for subscribed peers and send to them when ready
this._stopRendering();
var renderTask = pageObject.render(renderContext);
this.renderTask = renderTask;
renderTask.promise.then(_.bind(function() {
this._pageRendered(pageObject);
}, this), _.bind(function(error, exception) {
this._pageRenderError(pageObject, error, exception);
scope.$emit("presentationPageRenderError", page, this.maxPageNumber, loadErrorMessage);
}, this));
};
PDFCanvas.prototype.redrawPage = function() {
if (this.currentPage !== null) {
this.drawPage(this.currentPage);
}
sandboxApi.postMessage("redrawPage", {"redraw": true});
};
PDFCanvas.prototype.showPage = function(page) {
@ -290,10 +248,7 @@ define(['require', 'underscore', 'jquery'], function(require, _, $) { @@ -290,10 +248,7 @@ define(['require', 'underscore', 'jquery'], function(require, _, $) {
}
};
$scope.canvasIndex = 0;
var canvases = container.find("canvas");
var pdfCanvas = new PDFCanvas($scope, canvases);
pdfCanvas = new PDFCanvas($scope);
$scope.$watch("currentPresentation", function(presentation, previousPresentation) {
if (presentation) {
@ -311,6 +266,7 @@ define(['require', 'underscore', 'jquery'], function(require, _, $) { @@ -311,6 +266,7 @@ define(['require', 'underscore', 'jquery'], function(require, _, $) {
$scope.$on("$destroy", function() {
pdfCanvas.close();
pdfCanvas = null;
sandboxApi.destroy();
});
$scope.$watch("currentPageNumber", function(page, oldValue) {
@ -333,7 +289,7 @@ define(['require', 'underscore', 'jquery'], function(require, _, $) { @@ -333,7 +289,7 @@ define(['require', 'underscore', 'jquery'], function(require, _, $) {
return {
restrict: 'E',
replace: true,
template: '<div class="canvasContainer"><canvas ng-hide="canvasIndex"></canvas><canvas ng-show="canvasIndex"></canvas></div>',
template: '<div class="canvasContainer"><iframe allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true" sandbox="allow-scripts allow-same-origin"></iframe></div>',
controller: controller
};

25
static/js/directives/presentation.js

@ -715,29 +715,32 @@ define(['jquery', 'underscore', 'text!partials/presentation.html', 'bigscreen'], @@ -715,29 +715,32 @@ define(['jquery', 'underscore', 'text!partials/presentation.html', 'bigscreen'],
});
});
$(document).on("keyup", function(event) {
if (!$scope.layout.presentation) {
return;
}
if ($(event.target).is("input,textarea,select")) {
return;
}
$scope.$apply(function() {
switch (event.keyCode) {
$scope.$on("keyUp", function(event, keyCode) {
switch (keyCode) {
case 37:
// left arrow
$scope.prevPage();
event.preventDefault();
break;
case 39:
// right arrow
case 32:
// space
$scope.nextPage();
event.preventDefault();
break;
}
})
$(document).on("keyup", function(event) {
if (!$scope.layout.presentation) {
return;
}
if ($(event.target).is("input,textarea,select")) {
return;
}
$scope.$apply(function(scope) {
scope.$emit("keyUp", event.keyCode);
});
event.preventDefault();
});
$scope.$watch("layout.presentation", function(newval, oldval) {

2
static/js/directives/youtubevideo.js

@ -115,6 +115,8 @@ define(['require', 'jquery', 'underscore', 'moment', 'text!partials/youtubevideo @@ -115,6 +115,8 @@ define(['require', 'jquery', 'underscore', 'moment', 'text!partials/youtubevideo
var msg = message.data;
var data = msg[msg.type] || {};
switch (msg.type) {
case "ready":
break;
case "youtube.apiReady":
$scope.$apply(function() {
console.log("YouTube IFrame ready");

281
static/js/sandboxes/pdf.js

@ -0,0 +1,281 @@ @@ -0,0 +1,281 @@
/*
* Spreed WebRTC.
* Copyright (C) 2013-2015 struktur AG
*
* This file is part of Spreed WebRTC.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
"use strict";
(function () {
var script = document.getElementsByTagName("script")[0];
var PARENT_ORIGIN = script.getAttribute("data-parent-origin");
var PDFJS_URL = script.getAttribute("data-pdfjs-url");
var PDFJS_WORKER_URL = script.getAttribute("data-pdfjs-worker-url");
var PDFJS_COMPATIBILITY_URL = script.getAttribute("data-pdfjs-compatibility-url");
var container = document.getElementById("container");
var pdfScript = null;
var pdfjs = null;
var PdfJsSandbox = function(window) {
this.head = document.getElementsByTagName('head')[0];
this.canvases = document.getElementsByTagName('canvas');
this.window = window;
this.doc = null;
this.currentPage = null;
this.canvasIndex = 0;
this.renderTask = null;
};
PdfJsSandbox.prototype.postMessage = function(type, message) {
var msg = {"type": type};
msg[type] = message;
this.window.parent.postMessage(msg, PARENT_ORIGIN);
};
PdfJsSandbox.prototype.openFile = function(source) {
if (!pdfScript) {
var that = this;
var compat = document.createElement('script');
compat.type = "text/javascript";
compat.src = PDFJS_COMPATIBILITY_URL;
this.head.appendChild(compat);
pdfScript = document.createElement('script');
pdfScript.type = "text/javascript";
pdfScript.src = PDFJS_URL;
pdfScript.onerror = function(evt) {
that.postMessage("pdfjs.error", {"msgid": "loadScriptFailed"});
that.head.removeChild(pdfScript);
pdfScript = null;
};
pdfScript.onload = function(evt) {
pdfjs = that.window.PDFJS;
if (PDFJS_WORKER_URL) {
// NOTE: the worker script won't actually be run inside a
// real Worker object as it can't be loaded cross-domain
// from the sandboxed iframe ("data:" vs. "https").
pdfjs.workerSrc = PDFJS_WORKER_URL;
}
console.log("Using pdf.js " + pdfjs.version + " (build " + pdfjs.build + ")");
that._doOpenFile(source);
};
this.head.appendChild(pdfScript);
} else {
this._doOpenFile(source);
}
};
PdfJsSandbox.prototype.closeFile = function() {
this._stopRendering();
if (this.currentPage) {
this.currentPage.destroy();
this.currentPage = null;
}
if (this.doc) {
this.doc.cleanup();
this.doc.destroy();
this.doc = null;
}
// clear visible canvas so it's empty when we show the next document
var canvas = this.canvases[this.canvasIndex];
canvas.getContext("2d").clearRect(0, 0, canvas.width, canvas.height);
};
PdfJsSandbox.prototype._doOpenFile = function(source) {
var that = this;
this.postMessage("pdfjs.loading", {"source": source});
pdfjs.getDocument(source).then(function(doc) {
that._pdfLoaded(source, doc);
}, function(error, exception) {
that._pdfLoadError(source, error, exception);
});
};
PdfJsSandbox.prototype._pdfLoaded = function(source, doc) {
console.log("PDF loaded", doc);
this.doc = doc;
this.postMessage("pdfjs.loaded", {"source": source, "doc": {"numPages": doc.numPages}});
};
PdfJsSandbox.prototype._pdfLoadError = function(source, error, exception) {
this.postMessage("pdfjs.loadError", {"source": source, "error": error});
};
PdfJsSandbox.prototype.loadPage = function(page) {
if (this.currentPage) {
this.currentPage.destroy();
this.currentPage = null;
}
var that = this;
this.doc.getPage(page).then(function(pageObject) {
that._pageLoaded(page, pageObject);
}, function(error, exception) {
that._pageLoadError(page, error, exception);
});
};
PdfJsSandbox.prototype._pageLoaded = function(page, pageObject) {
console.log("Got page", pageObject);
this.currentPage = pageObject;
this.postMessage("pdfjs.pageLoaded", {"page": page});
this.drawPage(pageObject);
};
PdfJsSandbox.prototype._pageLoadError = function(page, error, exception) {
console.error("Could not load page", page, error, exception);
this.postMessage("pdfjs.pageLoadError", {"page": page, "error": error});
};
PdfJsSandbox.prototype._stopRendering = function() {
if (this.renderTask) {
if (this.renderTask.internalRenderTask && this.renderTask.internalRenderTask.cancel) {
this.renderTask.internalRenderTask.cancel();
}
this.renderTask = null;
}
}
PdfJsSandbox.prototype.drawPage = function(pageObject) {
var pdfView = pageObject.view;
var pdfWidth = pdfView[2] - pdfView[0];
var pdfHeight = pdfView[3] - pdfView[1];
var w = container.offsetWidth;
var h = container.offsetHeight;
var scale = w / pdfWidth;
if (pdfHeight * scale > h) {
scale = container.offsetHeight / pdfHeight;
}
// use double-buffering to avoid flickering while
// the new page is rendered...
var canvas = this.canvases[1 - this.canvasIndex];
var viewport = pageObject.getViewport(scale);
canvas.width = Math.round(viewport.width);
canvas.height = Math.round(viewport.height);
var renderContext = {
canvasContext: canvas.getContext("2d"),
viewport: viewport
};
console.log("Rendering page", pageObject);
this.postMessage("pdfjs.renderingPage", {"page": pageObject.pageNumber});
// TODO(fancycode): also render images in different resolutions for subscribed peers and send to them when ready
this._stopRendering();
var renderTask = pageObject.render(renderContext);
this.renderTask = renderTask;
var that = this;
renderTask.promise.then(function() {
that._pageRendered(pageObject);
}, function(error, exception) {
that._pageRenderError(pageObject, error, exception);
});
};
PdfJsSandbox.prototype._pageRendered = function(pageObject) {
this.renderTask = null;
console.log("Rendered page", pageObject.pageNumber);
this.postMessage("pdfjs.pageRendered", {"page": pageObject.pageNumber});
// ...and flip the buffers...
this.canvases[this.canvasIndex].style.display = "none";
this.canvasIndex = 1 - this.canvasIndex;
this.canvases[this.canvasIndex].style.display = "block";
};
PdfJsSandbox.prototype._pageRenderError = function(pageObject, error, exception) {
if (error === "cancelled") {
return;
}
console.error("Could not render page", pageObject, error, exception);
this.renderTask = null;
this.postMessage("pdfjs.pageRenderError", {"page": pageObject.pageNumber, "error": error});
};
PdfJsSandbox.prototype.redrawPage = function() {
if (this.currentPage !== null) {
this.drawPage(this.currentPage);
}
};
var sandbox = new PdfJsSandbox(window);
window.addEventListener("message", function(event) {
if (event.origin !== PARENT_ORIGIN) {
// only accept messages from spreed-webrtc
return;
}
var msg = event.data;
var data = msg[msg.type] || {};
switch (msg.type) {
case "openFile":
sandbox.openFile(data.source);
break;
case "closeFile":
sandbox.closeFile();
break;
case "loadPage":
sandbox.loadPage(data.page);
break;
case "redrawPage":
sandbox.redrawPage();
break;
default:
console.log("Unknown message received", event);
break;
}
}, false);
document.addEventListener("keyup", function(event) {
sandbox.postMessage("pdfjs.keyUp", {"key": event.keyCode});
event.preventDefault();
});
var toggleFullscreen = function(elem) {
var fullScreenElement = document.fullscreenElement || document.msFullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.webkitCurrentFullScreenElement;
if (fullScreenElement) {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
} else {
if (elem.requestFullscreen) {
elem.requestFullscreen();
} else if (elem.webkitRequestFullscreen) {
elem.webkitRequestFullscreen();
} else if (elem.mozRequestFullScreen) {
elem.mozRequestFullScreen();
} else if (elem.msRequestFullscreen) {
elem.msRequestFullscreen();
}
}
};
container.addEventListener("dblclick", function(event) {
toggleFullscreen(container);
});
console.log("pdf.js sandbox ready.");
sandbox.postMessage("ready", {"ready": true});
})();

1
static/js/sandboxes/youtube.js

@ -244,5 +244,6 @@ @@ -244,5 +244,6 @@
}, false);
console.log("YouTube sandbox ready.");
sandbox.postMessage("ready", {"ready": true});
})();

20
static/js/services/sandbox.js

@ -30,6 +30,8 @@ define(["jquery", "underscore"], function($, _) { @@ -30,6 +30,8 @@ define(["jquery", "underscore"], function($, _) {
this.target = this.iframe.contentWindow;
this.e = $({});
this.handler = _.bind(this.onPostMessageReceived, this);
this.ready = false;
this.pending_messages = [];
$window.addEventListener("message", this.handler, false);
};
@ -46,10 +48,28 @@ define(["jquery", "underscore"], function($, _) { @@ -46,10 +48,28 @@ define(["jquery", "underscore"], function($, _) {
return;
}
if (event.data.type === "ready") {
this.ready = true;
this._sendPendingMessages();
}
this.e.triggerHandler("message", [event]);
};
Sandbox.prototype._sendPendingMessages = function() {
var i;
for (i=0; i<this.pending_messages.length; i++) {
var entry = this.pending_messages[i];
this.postMessage(entry[0], entry[1]);
}
this.pending_messages = [];
};
Sandbox.prototype.postMessage = function(type, message) {
if (!this.ready) {
this.pending_messages.push([type, message]);
return;
}
var msg = {"type": type}
msg[type] = message;
this.target.postMessage(msg, "*");

34
static/partials/pdfcanvas_sandbox.html

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
<!DOCTYPE html>
<html>
<head>
<title>pdf.js Sandbox</title>
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src __PARENT_ORIGIN__ 'unsafe-eval'; img-src 'self'; style-src 'unsafe-inline'">
<style type="text/css">
html, body {
height:100%;
}
body {
margin:0;
padding:0;
max-width:100%;
max-height:100%;
overflow:hidden;
}
#container {
width:100%;
height:100%;
}
canvas {
margin:0 auto;
position:relative;
display:none;
}
</style>
</head>
<body>
<div id="container">
<canvas id="canvas0"></canvas><canvas id="canvas1"></canvas>
</div>
<script src="__PDFJS_SANDBOX_JS_URL__" data-parent-origin="__PARENT_ORIGIN__" data-pdfjs-url="__PDFJS_URL__" data-pdfjs-worker-url="__PDFJS_WORKER_URL__" data-pdfjs-compatibility-url="__PDFJS_COMPATIBILITY_URL__"></script>
</body>
</html>
Loading…
Cancel
Save