/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ /* Copyright 2012 Mozilla Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ 'use strict'; /* * A Test Driver for PDF.js */ // Disable worker support for running test as // https://github.com/mozilla/pdf.js/pull/764#issuecomment-2638944 // "firefox-bin: Fatal IO error 12 (Cannot allocate memory) on X server :1." // PDFJS.disableWorker = true; var appPath, browser, canvas, currentTaskIdx, manifest, stdout; var inFlightRequests = 0; function queryParams() { var qs = window.location.search.substring(1); var kvs = qs.split('&'); var params = { }; for (var i = 0; i < kvs.length; ++i) { var kv = kvs[i].split('='); params[unescape(kv[0])] = unescape(kv[1]); } return params; } function load() { var params = queryParams(); browser = params.browser; var manifestFile = params.manifestFile; appPath = params.path; canvas = document.createElement('canvas'); canvas.mozOpaque = true; stdout = document.getElementById('stdout'); log('load...\n'); log('Harness thinks this browser is "' + browser + '" with path "' + appPath + '"\n'); log('Fetching manifest "' + manifestFile + '"... '); var r = new XMLHttpRequest(); r.open('GET', manifestFile, false); r.onreadystatechange = function loadOnreadystatechange(e) { if (r.readyState == 4) { log('done\n'); manifest = JSON.parse(r.responseText); currentTaskIdx = 0; nextTask(); } }; r.send(null); } function cleanup() { // Clear out all the stylesheets since a new one is created for each font. while (document.styleSheets.length > 0) { var styleSheet = document.styleSheets[0]; while (styleSheet.cssRules.length > 0) styleSheet.deleteRule(0); var ownerNode = styleSheet.ownerNode; ownerNode.parentNode.removeChild(ownerNode); } var guard = document.getElementById('content-end'); var body = document.body; while (body.lastChild !== guard) body.removeChild(body.lastChild); // Wipe out the link to the pdfdoc so it can be GC'ed. for (var i = 0; i < manifest.length; i++) { if (manifest[i].pdfDoc) { manifest[i].pdfDoc.destroy(); delete manifest[i].pdfDoc; } } } function exceptionToString(e) { if (typeof e !== 'object') return String(e); if (!('message' in e)) return JSON.stringify(e); return e.message + ('stack' in e ? ' at ' + e.stack.split('\n')[0] : ''); } function nextTask() { cleanup(); if (currentTaskIdx == manifest.length) { done(); return; } var task = manifest[currentTaskIdx]; task.round = 0; log('Loading file "' + task.file + '"\n'); var absoluteUrl = combineUrl(window.location.href, task.file); getPdf(absoluteUrl, function nextTaskGetPdf(data) { var failure; function continuation() { task.pageNum = task.firstPage || 1; nextPage(task, failure); } try { var promise = PDFJS.getDocument(data); promise.then(function(doc) { task.pdfDoc = doc; continuation(); }, function(e) { failure = 'load PDF doc : ' + e; continuation(); }); return; } catch (e) { failure = 'load PDF doc : ' + exceptionToString(e); } continuation(); }); } function isLastPage(task) { var limit = task.pageLimit || 0; if (!limit || limit > task.pdfDoc.numPages) limit = task.pdfDoc.numPages; return task.pageNum > limit; } function canvasToDataURL() { return canvas.toDataURL('image/png'); } function nextPage(task, loadError) { var failure = loadError || ''; if (!task.pdfDoc) { sendTaskResult(canvasToDataURL(), task, failure); log('done' + (failure ? ' (failed !: ' + failure + ')' : '') + '\n'); ++currentTaskIdx; nextTask(); return; } if (isLastPage(task)) { if (++task.round < task.rounds) { log(' Round ' + (1 + task.round) + '\n'); task.pageNum = 1; } else { ++currentTaskIdx; nextTask(); return; } } if (task.skipPages && task.skipPages.indexOf(task.pageNum) >= 0) { log(' skipping page ' + task.pageNum + '/' + task.pdfDoc.numPages + '... '); // empty the canvas canvas.width = 1; canvas.height = 1; clear(canvas.getContext('2d')); snapshotCurrentPage(task, ''); return; } var page = null; if (!failure) { try { log(' loading page ' + task.pageNum + '/' + task.pdfDoc.numPages + '... '); var ctx = canvas.getContext('2d'); task.pdfDoc.getPage(task.pageNum).then(function(page) { var pdfToCssUnitsCoef = 96.0 / 72.0; var viewport = page.getViewport(pdfToCssUnitsCoef); canvas.width = viewport.width; canvas.height = viewport.height; clear(ctx); // using the text layer builder that does nothing to test // text layer creation operations var textLayerBuilder = { beginLayout: function nullTextLayerBuilderBeginLayout() {}, endLayout: function nullTextLayerBuilderEndLayout() {}, appendText: function nullTextLayerBuilderAppendText(text, fontName, fontSize) {} }; var renderContext = { canvasContext: ctx, textLayer: textLayerBuilder, viewport: viewport }; var completeRender = (function(error) { page.destroy(); snapshotCurrentPage(task, error); }); page.render(renderContext).then(function() { completeRender(false); }, function(error) { completeRender('render : ' + error); }); }, function(error) { snapshotCurrentPage(task, 'render : ' + error); }); } catch (e) { failure = 'page setup : ' + exceptionToString(e); snapshotCurrentPage(task, failure); } } } function snapshotCurrentPage(task, failure) { log('done, snapshotting... '); sendTaskResult(canvasToDataURL(), task, failure); log('done' + (failure ? ' (failed !: ' + failure + ')' : '') + '\n'); // Set up the next request var backoff = (inFlightRequests > 0) ? inFlightRequests * 10 : 0; setTimeout( function snapshotCurrentPageSetTimeout() { ++task.pageNum; nextPage(task); }, backoff ); } function sendQuitRequest() { var r = new XMLHttpRequest(); r.open('POST', '/tellMeToQuit?path=' + escape(appPath), false); r.send(null); } function quitApp() { log('Done !'); document.body.innerHTML = 'Tests are finished.