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 |