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.
5 cr.define('chrome.sync.about_tab', function() {
6 // Contains the latest snapshot of sync about info.
7 chrome.sync.aboutInfo = {};
9 function highlightIfChanged(node, oldVal, newVal) {
10 function clearHighlight() {
11 this.removeAttribute('highlighted');
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.addEventListener
20 node.addEventListener('webkitAnimationEnd', clearHighlight, false);
21 node.setAttribute('highlighted', '');
25 function refreshAboutInfo(aboutInfo) {
26 chrome.sync.aboutInfo = aboutInfo;
27 var aboutInfoDiv = $('about-info');
28 jstProcess(new JsEvalContext(aboutInfo), aboutInfoDiv);
31 function onAboutInfoUpdatedEvent(e) {
32 refreshAboutInfo(e.details);
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
40 function isScrolledToBottom(elem) {
41 return elem.scrollHeight - elem.scrollTop == elem.clientHeight;
45 * Helper to scroll an element to its bottom limit.
46 * @param {Element} elem element to be scrolled
48 function scrollToBottom(elem) {
49 elem.scrollTop = elem.scrollHeight - elem.clientHeight;
52 /** Container for accumulated sync protocol events. */
53 var protocolEvents = [];
55 /** We may receive re-delivered events. Keep a record of ones we've seen. */
56 var knownEventTimestamps = {};
59 * Callback for incoming protocol events.
60 * @param {Event} e The protocol event.
62 function onReceivedProtocolEvent(e) {
63 var details = e.details;
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)) {
71 knownEventTimestamps[details.time] = true;
72 protocolEvents.push(details);
74 var trafficContainer = $('traffic-event-container');
76 // Scroll to the bottom if we were already at the bottom. Otherwise, leave
77 // the scrollbar alone.
78 var shouldScrollDown = isScrolledToBottom(trafficContainer);
80 var context = new JsEvalContext({ events: protocolEvents });
81 jstProcess(context, trafficContainer);
84 scrollToBottom(trafficContainer);
88 * Initializes state and callbacks for the protocol event log UI.
90 function initProtocolEventLog() {
91 chrome.sync.events.addEventListener(
92 'onProtocolEvent', onReceivedProtocolEvent);
94 // Make the prototype jscontent element disappear.
95 jstProcess({}, $('traffic-event-container'));
99 * Initializes listeners for status dump and import UI.
101 function initStatusDumpButton() {
102 $('status-data').hidden = true;
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;
113 data += new Date().toString() + '\n';
117 data += JSON.stringify(aboutInfo, null, 2) + '\n';
119 $('status-text').value = data;
120 $('status-data').hidden = false;
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.';
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.';
139 data = data.substr(firstBrace);
141 // Remove listeners to prevent sync events from overwriting imported data.
142 chrome.sync.events.removeEventListener(
143 'onAboutInfoUpdated',
144 onAboutInfoUpdatedEvent);
146 var aboutInfo = JSON.parse(data);
147 refreshAboutInfo(aboutInfo);
152 * Toggles the given traffic event entry div's "expanded" state.
153 * @param {MouseEvent} e the click event that triggered the toggle.
155 function expandListener(e) {
156 e.target.classList.toggle('traffic-event-entry-expanded');
160 * Attaches a listener to the given traffic event entry div.
161 * @param {HTMLElement} element the element to attach the listener to.
163 function addExpandListener(element) {
164 element.addEventListener('click', expandListener, false);
168 initStatusDumpButton();
169 initProtocolEventLog();
171 chrome.sync.events.addEventListener(
172 'onAboutInfoUpdated',
173 onAboutInfoUpdatedEvent);
175 // Register to receive a stream of event notifications.
176 chrome.sync.registerForEvents();
178 // Request an about info update event to initialize the page.
179 chrome.sync.requestUpdatedAboutInfo();
184 addExpandListener: addExpandListener,
185 highlightIfChanged: highlightIfChanged
189 document.addEventListener(
190 'DOMContentLoaded', chrome.sync.about_tab.onLoad, false);