/* * 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 . * */ "use strict"; define(['require', 'underscore', 'jquery'], function(require, _, $) { return ["$window", "$compile", "$http", "translation", "safeApply", 'restURL', 'sandbox', function($window, $compile, $http, translation, safeApply, restURL, sandbox) { var pdfjs = null; var controller = ['$scope', '$element', '$attrs', function($scope, $element, $attrs) { var container = $($element); var pdfCanvas; var url = restURL.sandbox("pdfcanvas"); var sandboxApi = sandbox.createSandbox(container, null, url, "allow-scripts", null, { allowfullscreen: true, mozallowfullscreen: true, webkitallowfullscreen: true }); 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.doc = null; this.currentPageNumber = null; this.pendingPageNumber = null; this.url = null; }; PDFCanvas.prototype.close = function() { sandboxApi.postMessage("closeFile", {"close": true}); if (this.url) { URL.revokeObjectURL(this.url); this.url = null; } this.pendingPageNumber = null; this.currentPageNumber = -1; this.maxPageNumber = -1; }; PDFCanvas.prototype.open = function(presentation) { this.scope.$emit("presentationOpening", presentation); presentation.open(_.bind(function(source) { console.log("Loading PDF from", source); this.close(); if (typeof source === "string") { // got a url this._openFile(source); return; } var fp = source.file || source; if (typeof URL !== "undefined" && URL.createObjectURL) { this.url = URL.createObjectURL(fp); this._openFile(this.url); } else { var fileReader = new FileReader(); fileReader.onload = _.bind(function(evt) { var buffer = evt.target.result; var uint8Array = new Uint8Array(buffer); this._openFile(uint8Array); }, this); fileReader.readAsArrayBuffer(fp); } }, this)); }; PDFCanvas.prototype._pdfLoaded = function(source, doc) { this.scope.$apply(_.bind(function(scope) { this.doc = doc; this.maxPageNumber = doc.numPages; this.currentPageNumber = -1; scope.$emit("presentationLoaded", source, doc); }, this)); }; PDFCanvas.prototype._pdfLoadError = function(source, error, exception) { var loadErrorMessage; switch (error) { case "InvalidPDFException": loadErrorMessage = translation._("Could not load PDF: Please make sure to select a PDF document."); break; case "MissingPDFException": loadErrorMessage = translation._("Could not load PDF: Missing PDF file."); break; default: if (error) { loadErrorMessage = translation._("An error occurred while loading the PDF (%s).", error); } else { loadErrorMessage = translation._("An unknown error occurred while loading the PDF."); } break; } this.scope.$apply(_.bind(function(scope) { scope.$emit("presentationLoadError", source, loadErrorMessage); }, this)); }; PDFCanvas.prototype._openFile = function(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)); return; } console.log("Opening file", source); sandboxApi.postMessage("openFile", {"source": source}); }; PDFCanvas.prototype._pageLoaded = function(page) { this.scope.$apply(_.bind(function(scope) { scope.$emit("presentationPageLoaded", page); }, this)); }; PDFCanvas.prototype._pageLoadError = function(page, error) { var loadErrorMessage; if (error) { loadErrorMessage = translation._("An error occurred while loading the PDF page (%s).", error); } else { loadErrorMessage = translation._("An unknown error occurred while loading the PDF page."); } this.scope.$apply(_.bind(function(scope) { scope.$emit("presentationPageLoadError", page, loadErrorMessage); }, this)); }; PDFCanvas.prototype._showPage = function(page) { if (page === this.currentPageNumber) { return; } console.log("Showing page", page, "/", this.maxPageNumber); this.currentPageNumber = page; this.scope.$emit("presentationPageLoading", page); sandboxApi.postMessage("loadPage", {"page": page}); }; PDFCanvas.prototype._pageRendered = function(page) { this.scope.$apply(_.bind(function(scope) { this.scope.$emit("presentationPageRendered", page, this.maxPageNumber); this.showQueuedPage(); }, this)); }; PDFCanvas.prototype._pageRenderError = function(page, error) { var loadErrorMessage; if (error) { loadErrorMessage = translation._("An error occurred while rendering the PDF page (%s).", error); } else { loadErrorMessage = translation._("An unknown error occurred while rendering the PDF page."); } this.scope.$apply(_.bind(function(scope) { scope.$emit("presentationPageRenderError", page, this.maxPageNumber, loadErrorMessage); }, this)); }; PDFCanvas.prototype.redrawPage = function() { sandboxApi.postMessage("redrawPage", {"redraw": true}); }; PDFCanvas.prototype.showPage = function(page) { if (page >= 1 && page <= this.maxPageNumber) { if (!this.doc) { this.pendingPageNumber = page; } else { this._showPage(page); } } }; PDFCanvas.prototype.showQueuedPage = function() { if (this.pendingPageNumber !== null) { this._showPage(this.pendingPageNumber); this.pendingPageNumber = null; } }; pdfCanvas = new PDFCanvas($scope); $scope.$watch("currentPresentation", function(presentation, previousPresentation) { if (presentation) { safeApply($scope, function(scope) { pdfCanvas.open(presentation); }); } else { if (previousPresentation) { previousPresentation.close(); } pdfCanvas.close(); } }); $scope.$on("$destroy", function() { pdfCanvas.close(); pdfCanvas = null; sandboxApi.destroy(); }); $scope.$watch("currentPageNumber", function(page, oldValue) { if (page === oldValue) { // no change return; } pdfCanvas.showPage(page); }); $($window).on("resize", function() { $scope.$apply(function(scope) { pdfCanvas.redrawPage(); }); }); }]; return { restrict: 'E', replace: true, template: '
', controller: controller }; }]; });