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
5var mode;
6var enabled = false;
7var scheme = '';
8var timeoutId = null;
9
10var 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
19var 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
21function 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
32function 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
68function onExtensionMessage(request) {
69  if (enabled != request.enabled || scheme != request.scheme) {
70    enabled = request.enabled;
71    scheme = request.scheme;
72    update();
73  }
74}
75
76function 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
94function 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
121init();
122