| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 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 cr.define('chrome.sync.about_tab', function() { | |
| 6 // Contains the latest snapshot of sync about info. | |
| 7 chrome.sync.aboutInfo = {}; | |
| 8 | |
| 9 function highlightIfChanged(node, oldVal, newVal) { | |
| 10 function clearHighlight() { | |
| 11 this.removeAttribute('highlighted'); | |
| 12 } | |
| 13 | |
| 14 var oldStr = oldVal.toString(); | |
| 15 var newStr = newVal.toString(); | |
| 16 if (oldStr != '' && oldStr != newStr) { | |
| 17 // Note the addListener function does not end up creating duplicate | |
| 18 // listeners. There can be only one listener per event at a time. | |
| 19 // Reference: https://developer.mozilla.org/en/DOM/element.addEventListene
r | |
| 20 node.addEventListener('webkitAnimationEnd', clearHighlight, false); | |
| 21 node.setAttribute('highlighted', ''); | |
| 22 } | |
| 23 } | |
| 24 | |
| 25 function refreshAboutInfo(aboutInfo) { | |
| 26 chrome.sync.aboutInfo = aboutInfo; | |
| 27 var aboutInfoDiv = $('about-info'); | |
| 28 jstProcess(new JsEvalContext(aboutInfo), aboutInfoDiv); | |
| 29 } | |
| 30 | |
| 31 function onAboutInfoUpdatedEvent(e) { | |
| 32 refreshAboutInfo(e.details); | |
| 33 } | |
| 34 | |
| 35 /** | |
| 36 * Helper to determine if an element is scrolled to its bottom limit. | |
| 37 * @param {Element} elem element to check | |
| 38 * @return {boolean} true if the element is scrolled to the bottom | |
| 39 */ | |
| 40 function isScrolledToBottom(elem) { | |
| 41 return elem.scrollHeight - elem.scrollTop == elem.clientHeight; | |
| 42 } | |
| 43 | |
| 44 /** | |
| 45 * Helper to scroll an element to its bottom limit. | |
| 46 * @param {Element} elem element to be scrolled | |
| 47 */ | |
| 48 function scrollToBottom(elem) { | |
| 49 elem.scrollTop = elem.scrollHeight - elem.clientHeight; | |
| 50 } | |
| 51 | |
| 52 /** Container for accumulated sync protocol events. */ | |
| 53 var protocolEvents = []; | |
| 54 | |
| 55 /** We may receive re-delivered events. Keep a record of ones we've seen. */ | |
| 56 var knownEventTimestamps = {}; | |
| 57 | |
| 58 /** | |
| 59 * Callback for incoming protocol events. | |
| 60 * @param {Event} e The protocol event. | |
| 61 */ | |
| 62 function onReceivedProtocolEvent(e) { | |
| 63 var details = e.details; | |
| 64 | |
| 65 // Return early if we've seen this event before. Assumes that timestamps | |
| 66 // are sufficiently high resolution to uniquely identify an event. | |
| 67 if (knownEventTimestamps.hasOwnProperty(details.time)) { | |
| 68 return; | |
| 69 } | |
| 70 | |
| 71 knownEventTimestamps[details.time] = true; | |
| 72 protocolEvents.push(details); | |
| 73 | |
| 74 var trafficContainer = $('traffic-event-container'); | |
| 75 | |
| 76 // Scroll to the bottom if we were already at the bottom. Otherwise, leave | |
| 77 // the scrollbar alone. | |
| 78 var shouldScrollDown = isScrolledToBottom(trafficContainer); | |
| 79 | |
| 80 var context = new JsEvalContext({ events: protocolEvents }); | |
| 81 jstProcess(context, trafficContainer); | |
| 82 | |
| 83 if (shouldScrollDown) | |
| 84 scrollToBottom(trafficContainer); | |
| 85 } | |
| 86 | |
| 87 /** | |
| 88 * Initializes state and callbacks for the protocol event log UI. | |
| 89 */ | |
| 90 function initProtocolEventLog() { | |
| 91 chrome.sync.events.addEventListener( | |
| 92 'onProtocolEvent', onReceivedProtocolEvent); | |
| 93 | |
| 94 // Make the prototype jscontent element disappear. | |
| 95 jstProcess({}, $('traffic-event-container')); | |
| 96 } | |
| 97 | |
| 98 /** | |
| 99 * Initializes listeners for status dump and import UI. | |
| 100 */ | |
| 101 function initStatusDumpButton() { | |
| 102 $('status-data').hidden = true; | |
| 103 | |
| 104 var dumpStatusButton = $('dump-status'); | |
| 105 dumpStatusButton.addEventListener('click', function(event) { | |
| 106 var aboutInfo = chrome.sync.aboutInfo; | |
| 107 if (!$('include-ids').checked) { | |
| 108 aboutInfo.details = chrome.sync.aboutInfo.details.filter(function(el) { | |
| 109 return !el.is_sensitive; | |
| 110 }); | |
| 111 } | |
| 112 var data = ''; | |
| 113 data += new Date().toString() + '\n'; | |
| 114 data += '======\n'; | |
| 115 data += 'Status\n'; | |
| 116 data += '======\n'; | |
| 117 data += JSON.stringify(aboutInfo, null, 2) + '\n'; | |
| 118 | |
| 119 $('status-text').value = data; | |
| 120 $('status-data').hidden = false; | |
| 121 }); | |
| 122 | |
| 123 var importStatusButton = $('import-status'); | |
| 124 importStatusButton.addEventListener('click', function(event) { | |
| 125 $('status-data').hidden = false; | |
| 126 if ($('status-text').value.length == 0) { | |
| 127 $('status-text').value = | |
| 128 'Paste sync status dump here then click import.'; | |
| 129 return; | |
| 130 } | |
| 131 | |
| 132 // First remove any characters before the '{'. | |
| 133 var data = $('status-text').value; | |
| 134 var firstBrace = data.indexOf('{'); | |
| 135 if (firstBrace < 0) { | |
| 136 $('status-text').value = 'Invalid sync status dump.'; | |
| 137 return; | |
| 138 } | |
| 139 data = data.substr(firstBrace); | |
| 140 | |
| 141 // Remove listeners to prevent sync events from overwriting imported data. | |
| 142 chrome.sync.events.removeEventListener( | |
| 143 'onAboutInfoUpdated', | |
| 144 onAboutInfoUpdatedEvent); | |
| 145 | |
| 146 var aboutInfo = JSON.parse(data); | |
| 147 refreshAboutInfo(aboutInfo); | |
| 148 }); | |
| 149 } | |
| 150 | |
| 151 /** | |
| 152 * Toggles the given traffic event entry div's "expanded" state. | |
| 153 * @param {MouseEvent} e the click event that triggered the toggle. | |
| 154 */ | |
| 155 function expandListener(e) { | |
| 156 e.target.classList.toggle('traffic-event-entry-expanded'); | |
| 157 } | |
| 158 | |
| 159 /** | |
| 160 * Attaches a listener to the given traffic event entry div. | |
| 161 * @param {HTMLElement} element the element to attach the listener to. | |
| 162 */ | |
| 163 function addExpandListener(element) { | |
| 164 element.addEventListener('click', expandListener, false); | |
| 165 } | |
| 166 | |
| 167 function onLoad() { | |
| 168 initStatusDumpButton(); | |
| 169 initProtocolEventLog(); | |
| 170 | |
| 171 chrome.sync.events.addEventListener( | |
| 172 'onAboutInfoUpdated', | |
| 173 onAboutInfoUpdatedEvent); | |
| 174 | |
| 175 // Register to receive a stream of event notifications. | |
| 176 chrome.sync.registerForEvents(); | |
| 177 | |
| 178 // Request an about info update event to initialize the page. | |
| 179 chrome.sync.requestUpdatedAboutInfo(); | |
| 180 } | |
| 181 | |
| 182 return { | |
| 183 onLoad: onLoad, | |
| 184 addExpandListener: addExpandListener, | |
| 185 highlightIfChanged: highlightIfChanged | |
| 186 }; | |
| 187 }); | |
| 188 | |
| 189 document.addEventListener( | |
| 190 'DOMContentLoaded', chrome.sync.about_tab.onLoad, false); | |
| OLD | NEW |