pdf_processor.js revision cedac228d2dd51db4b79ea1e72c7f249408ee061
1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5 6/** 7 * @fileoverview Logic to process PDFs 8 */ 9 10goog.provide('cvox.PdfProcessor'); 11 12/** 13 * Process PDFs created with Chrome's built-in PDF plug-in, which has an 14 * accessibility hook. 15 */ 16cvox.PdfProcessor.processEmbeddedPdfs = function() { 17 if (window.location.hash == '#original') { 18 return; 19 } 20 21 var es = document.querySelectorAll('embed[type="application/pdf"]'); 22 for (var i = 0; i < es.length; i++) { 23 var e = es[i]; 24 if (typeof e.accessibility === 'function') { 25 var infoJSON = e.accessibility(); 26 var info = cvox.ChromeVoxJSON.parse(infoJSON); 27 28 if (!info.loaded) { 29 window.setTimeout(cvox.PdfProcessor.processEmbeddedPdfs, 100); 30 continue; 31 } 32 if (!info.copyable) { 33 cvox.ChromeVox.tts.speak( 34 'Unable to access copy-protected PDF. Skipping.'); 35 continue; 36 } 37 38 var div = document.createElement('DIV'); 39 40 var headerDiv = document.createElement('DIV'); 41 headerDiv.style.position = 'relative'; 42 headerDiv.style.background = 'white'; 43 headerDiv.style.margin = '20pt'; 44 headerDiv.style.padding = '20pt'; 45 headerDiv.style.border = '1px solid #000'; 46 var filename = e.src.substr(e.src.lastIndexOf('/') + 1); 47 document.title = filename; 48 var html = cvox.ChromeVox.msgs.getMsg( 49 'pdf_header', [filename, e.src + '#original']); 50 headerDiv.innerHTML = html; 51 // Set up a handler to reload the page when 'Show original' is clicked. 52 var showLink = headerDiv.getElementsByTagName('a')[0]; 53 showLink.addEventListener('click', function() { 54 window.location.href = e.src + '#original'; 55 window.location.reload(); 56 }, true); 57 div.appendChild(headerDiv); 58 59 // Document Styles 60 div.style.position = 'relative'; 61 div.style.background = '#CCC'; 62 div.style.paddingTop = '1pt'; 63 div.style.paddingBottom = '1pt'; 64 div.style.width = '100%'; 65 div.style.minHeight = '100%'; 66 67 var displayPage = function(i) { 68 var json = e.accessibility(i); 69 var page = cvox.ChromeVoxJSON.parse(json); 70 var pageDiv = document.createElement('DIV'); 71 var pageAnchor = document.createElement('A'); 72 73 // Page Achor Setup 74 pageAnchor.name = 'page' + i; 75 76 // Page Styles 77 pageDiv.style.position = 'relative'; 78 pageDiv.style.background = 'white'; 79 pageDiv.style.margin = 'auto'; 80 pageDiv.style.marginTop = '20pt'; 81 pageDiv.style.marginBottom = '20pt'; 82 pageDiv.style.height = page.height + 'pt'; 83 pageDiv.style.width = page.width + 'pt'; 84 pageDiv.style.boxShadow = '0pt 0pt 10pt #333'; 85 86 // Text Nodes 87 var texts = page['textBox']; 88 for (var j = 0; j < texts.length; j++) { 89 var text = texts[j]; 90 var textSpan = document.createElement('Span'); 91 92 // Text Styles 93 textSpan.style.position = 'absolute'; 94 textSpan.style.left = text.left + 'pt'; 95 textSpan.style.top = text.top + 'pt'; 96 textSpan.style.fontSize = (0.8 * text.height) + 'pt'; 97 98 // Text Content 99 for (var k = 0; k < text['textNodes'].length; k++) { 100 var node = text['textNodes'][k]; 101 if (node.type == 'text') { 102 textSpan.appendChild(document.createTextNode(node.text)); 103 } else if (node.type == 'url') { 104 var a = document.createElement('A'); 105 a.href = node.url; 106 a.appendChild(document.createTextNode(node.text)); 107 textSpan.appendChild(a); 108 } 109 } 110 111 pageDiv.appendChild(textSpan); 112 } 113 div.appendChild(pageAnchor); 114 div.appendChild(pageDiv); 115 116 if (i < info['numberOfPages'] - 1) { 117 window.setTimeout(function() { displayPage(i + 1); }, 0); 118 } else { 119 // NOTE(deboer): In the case of 'native' pdfs loaded directly 120 // from a URL, we can not delete them outright. Doing so exposes a 121 // bug where all keyboard events are lost. We set it to 122 // 'display: none' instead. 123 e.style.display = 'none'; 124 e.parentNode.appendChild(div); 125 126 // TODO(stoarca): Why are we resetting the navigationManager? 127 // This function is too big and confusing, it needs to be cleaned up. 128 cvox.ChromeVox.navigationManager.reset(); 129 } 130 }; 131 132 window.setTimeout(function() { displayPage(0); }, 0); 133 } 134 } 135}; 136