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);