blob: 1cfa2cc9472654f1bead7c1181d83d253500866d [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.
/**
* @fileoverview Logic to process PDFs
*/
goog.provide('cvox.PdfProcessor');
/**
* Process PDFs created with Chrome's built-in PDF plug-in, which has an
* accessibility hook.
*/
cvox.PdfProcessor.processEmbeddedPdfs = function() {
if (window.location.hash == '#original') {
return;
}
var es = document.querySelectorAll('embed[type="application/pdf"]');
for (var i = 0; i < es.length; i++) {
var e = es[i];
if (typeof e.accessibility === 'function') {
var infoJSON = e.accessibility();
var info = cvox.ChromeVoxJSON.parse(infoJSON);
if (!info.loaded) {
window.setTimeout(cvox.PdfProcessor.processEmbeddedPdfs, 100);
continue;
}
if (!info.copyable) {
cvox.ChromeVox.tts.speak(
'Unable to access copy-protected PDF. Skipping.');
continue;
}
var div = document.createElement('DIV');
var headerDiv = document.createElement('DIV');
headerDiv.style.position = 'relative';
headerDiv.style.background = 'white';
headerDiv.style.margin = '20pt';
headerDiv.style.padding = '20pt';
headerDiv.style.border = '1px solid #000';
var filename = e.src.substr(e.src.lastIndexOf('/') + 1);
document.title = filename;
var html = cvox.ChromeVox.msgs.getMsg(
'pdf_header', [filename, e.src + '#original']);
headerDiv.innerHTML = html;
// Set up a handler to reload the page when 'Show original' is clicked.
var showLink = headerDiv.getElementsByTagName('a')[0];
showLink.addEventListener('click', function() {
window.location.href = e.src + '#original';
window.location.reload();
}, true);
div.appendChild(headerDiv);
// Document Styles
div.style.position = 'relative';
div.style.background = '#CCC';
div.style.paddingTop = '1pt';
div.style.paddingBottom = '1pt';
div.style.width = '100%';
div.style.minHeight = '100%';
var displayPage = function(i) {
var json = e.accessibility(i);
var page = cvox.ChromeVoxJSON.parse(json);
var pageDiv = document.createElement('DIV');
var pageAnchor = document.createElement('A');
// Page Achor Setup
pageAnchor.name = 'page' + i;
// Page Styles
pageDiv.style.position = 'relative';
pageDiv.style.background = 'white';
pageDiv.style.margin = 'auto';
pageDiv.style.marginTop = '20pt';
pageDiv.style.marginBottom = '20pt';
pageDiv.style.height = page.height + 'pt';
pageDiv.style.width = page.width + 'pt';
pageDiv.style.boxShadow = '0pt 0pt 10pt #333';
// Text Nodes
var texts = page['textBox'];
for (var j = 0; j < texts.length; j++) {
var text = texts[j];
var textSpan = document.createElement('Span');
// Text Styles
textSpan.style.position = 'absolute';
textSpan.style.left = text.left + 'pt';
textSpan.style.top = text.top + 'pt';
textSpan.style.fontSize = (0.8 * text.height) + 'pt';
// Text Content
for (var k = 0; k < text['textNodes'].length; k++) {
var node = text['textNodes'][k];
if (node.type == 'text') {
textSpan.appendChild(document.createTextNode(node.text));
} else if (node.type == 'url') {
var a = document.createElement('A');
a.href = node.url;
a.appendChild(document.createTextNode(node.text));
textSpan.appendChild(a);
}
}
pageDiv.appendChild(textSpan);
}
div.appendChild(pageAnchor);
div.appendChild(pageDiv);
if (i < info['numberOfPages'] - 1) {
window.setTimeout(function() { displayPage(i + 1); }, 0);
} else {
// NOTE(deboer): In the case of 'native' pdfs loaded directly
// from a URL, we can not delete them outright. Doing so exposes a
// bug where all keyboard events are lost. We set it to
// 'display: none' instead.
e.style.display = 'none';
e.parentNode.appendChild(div);
// TODO(stoarca): Why are we resetting the navigationManager?
// This function is too big and confusing, it needs to be cleaned up.
cvox.ChromeVox.navigationManager.reset();
}
};
window.setTimeout(function() { displayPage(0); }, 0);
}
}
};