1 // Copyright (c) 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 var mode; 6 var enabled = false; 7 var scheme = ''; 8 var timeoutId = null; 9 10 var filterMap = { 11 '0': 'url("#hc_extension_off")', 12 '1': 'url("#hc_extension_highcontrast")', 13 '2': 'url("#hc_extension_grayscale")', 14 '3': 'url("#hc_extension_invert")', 15 '4': 'url("#hc_extension_invert_grayscale")', 16 '5': 'url("#hc_extension_yellow_on_black")' 17 }; 18 19 var svgContent = '<svg xmlns="http://www.w3.org/2000/svg" version="1.1"><defs><filter id="hc_extension_off"><feComponentTransfer><feFuncR type="table" tableValues="0 1"/><feFuncG type="table" tableValues="0 1"/><feFuncB type="table" tableValues="0 1"/></feComponentTransfer></filter><filter id="hc_extension_highcontrast"><feComponentTransfer><feFuncR type="gamma" exponent="3.0"/><feFuncG type="gamma" exponent="3.0"/><feFuncB type="gamma" exponent="3.0"/></feComponentTransfer></filter><filter id="hc_extension_highcontrast_back"><feComponentTransfer><feFuncR type="gamma" exponent="0.33"/><feFuncG type="gamma" exponent="0.33"/><feFuncB type="gamma" exponent="0.33"/></feComponentTransfer></filter><filter id="hc_extension_grayscale"><feColorMatrix type="matrix" values="0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0 0 0 1 0"/><feComponentTransfer><feFuncR type="gamma" exponent="3"/><feFuncG type="gamma" exponent="3"/><feFuncB type="gamma" exponent="3"/></feComponentTransfer></filter><filter id="hc_extension_grayscale_back"><feComponentTransfer><feFuncR type="gamma" exponent="0.33"/><feFuncG type="gamma" exponent="0.33"/><feFuncB type="gamma" exponent="0.33"/></feComponentTransfer></filter><filter id="hc_extension_invert"><feComponentTransfer><feFuncR type="gamma" amplitude="-1" exponent="3" offset="1"/><feFuncG type="gamma" amplitude="-1" exponent="3" offset="1"/><feFuncB type="gamma" amplitude="-1" exponent="3" offset="1"/></feComponentTransfer></filter><filter id="hc_extension_invert_back"><feComponentTransfer><feFuncR type="table" tableValues="1 0"/><feFuncG type="table" tableValues="1 0"/><feFuncB type="table" tableValues="1 0"/></feComponentTransfer><feComponentTransfer><feFuncR type="gamma" exponent="1.7"/><feFuncG type="gamma" exponent="1.7"/><feFuncB type="gamma" exponent="1.7"/></feComponentTransfer></filter><filter id="hc_extension_invert_grayscale"><feColorMatrix type="matrix" values="0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0 0 0 1 0"/><feComponentTransfer><feFuncR type="gamma" amplitude="-1" exponent="3" offset="1"/><feFuncG type="gamma" amplitude="-1" exponent="3" offset="1"/><feFuncB type="gamma" amplitude="-1" exponent="3" offset="1"/></feComponentTransfer></filter><filter id="hc_extension_yellow_on_black"><feComponentTransfer><feFuncR type="gamma" amplitude="-1" exponent="3" offset="1"/><feFuncG type="gamma" amplitude="-1" exponent="3" offset="1"/><feFuncB type="gamma" amplitude="-1" exponent="3" offset="1"/></feComponentTransfer><feColorMatrix type="matrix" values="0.3 0.5 0.2 0 0 0.3 0.5 0.2 0 0 0 0 0 0 0 0 0 0 1 0"/></filter><filter id="hc_extension_yellow_on_black_back"><feComponentTransfer><feFuncR type="table" tableValues="1 0"/><feFuncG type="table" tableValues="1 0"/><feFuncB type="table" tableValues="1 0"/></feComponentTransfer><feComponentTransfer><feFuncR type="gamma" exponent="0.33"/><feFuncG type="gamma" exponent="0.33"/><feFuncB type="gamma" exponent="0.33"/></feComponentTransfer></filter></defs></svg>'; 20 21 function addSvgIfMissing() { 22 var wrap = document.getElementById('hc_extension_svg_filters'); 23 if (wrap) 24 return; 25 wrap = document.createElement('span'); 26 wrap.id = 'hc_extension_svg_filters'; 27 wrap.setAttribute('hidden', ''); 28 wrap.innerHTML = svgContent; 29 document.body.appendChild(wrap); 30 } 31 32 function update() { 33 var html = document.documentElement; 34 if (enabled) { 35 if (!document.body) { 36 window.setTimeout(update, 100); 37 return; 38 } 39 addSvgIfMissing(); 40 if (html.getAttribute('hc') != mode + scheme) 41 html.setAttribute('hc', mode + scheme); 42 if (html.getAttribute('hcx') != scheme) 43 html.setAttribute('hcx', scheme); 44 45 if (window == window.top) { 46 window.scrollBy(0, 1); 47 window.scrollBy(0, -1); 48 } 49 50 /** 51 if (mode == 'a') { 52 html.style.webkitFilter = filterMap[scheme]; 53 } 54 else { 55 html.style.webkitFilter = 'none'; 56 }**/ 57 58 } else { 59 html.setAttribute('hc', mode + '0'); 60 html.setAttribute('hcx', '0'); 61 window.setTimeout(function() { 62 html.removeAttribute('hc'); 63 html.removeAttribute('hcx'); 64 }, 0); 65 } 66 } 67 68 function onExtensionMessage(request) { 69 if (enabled != request.enabled || scheme != request.scheme) { 70 enabled = request.enabled; 71 scheme = request.scheme; 72 update(); 73 } 74 } 75 76 function onEvent(evt) { 77 if (evt.keyCode == 122 /* F11 */ && 78 evt.shiftKey) { 79 chrome.extension.sendRequest({'toggle_global': true}); 80 evt.stopPropagation(); 81 evt.preventDefault(); 82 return false; 83 } 84 if (evt.keyCode == 123 /* F12 */ && 85 evt.shiftKey) { 86 chrome.extension.sendRequest({'toggle_site': true}); 87 evt.stopPropagation(); 88 evt.preventDefault(); 89 return false; 90 } 91 return true; 92 } 93 94 function init() { 95 if (window == window.top) { 96 mode = 'a'; 97 } else { 98 mode = 'b'; 99 } 100 chrome.extension.onRequest.addListener(onExtensionMessage); 101 chrome.extension.sendRequest({'init': true}, onExtensionMessage); 102 document.addEventListener('keydown', onEvent, false); 103 104 // Work around bug that causes filter to be lost when the HTML element's attributes change. 105 var html = document.documentElement; 106 var config = { attributes: true, childList: false, characterData: false }; 107 var observer = new MutationObserver(function(mutations) { 108 observer.disconnect(); 109 html.removeAttribute('hc'); 110 html.removeAttribute('hcx'); 111 window.setTimeout(function() { 112 update(); 113 window.setTimeout(function() { 114 observer.observe(html, config); 115 }, 0); 116 }, 0); 117 }); 118 observer.observe(html, config); 119 } 120 121 init(); 122