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 /** This view displays summary statistics on bandwidth usage. */
6 var BandwidthView = (function() {
9 // We inherit from DivView.
10 var superClass = DivView;
15 function BandwidthView() {
16 assertFirstConstructorCall(BandwidthView);
18 // Call superclass's constructor.
19 superClass.call(this, BandwidthView.MAIN_BOX_ID);
21 g_browser.addSessionNetworkStatsObserver(this, true);
22 g_browser.addHistoricNetworkStatsObserver(this, true);
24 // Register to receive data reduction proxy info.
25 g_browser.addDataReductionProxyInfoObserver(this, true);
27 // Register to receive bad proxy info.
28 g_browser.addBadProxiesObserver(this, true);
30 this.sessionNetworkStats_ = null;
31 this.historicNetworkStats_ = null;
34 BandwidthView.TAB_ID = 'tab-handle-bandwidth';
35 BandwidthView.TAB_NAME = 'Bandwidth';
36 BandwidthView.TAB_HASH = '#bandwidth';
38 // IDs for special HTML elements in bandwidth_view.html
39 BandwidthView.MAIN_BOX_ID = 'bandwidth-view-tab-content';
40 BandwidthView.ENABLED_ID = 'data-reduction-proxy-enabled';
41 BandwidthView.PROXY_CONFIG_ID = 'data-reduction-proxy-config';
42 BandwidthView.PROBE_STATUS_ID = 'data-reduction-proxy-probe-status';
43 BandwidthView.BYPASS_STATE_CONTAINER_ID =
44 'data-reduction-proxy-bypass-state-container';
45 BandwidthView.BYPASS_STATE_ID = 'data-reduction-proxy-bypass-state-details';
46 BandwidthView.EVENTS_TBODY_ID = 'data-reduction-proxy-view-events-tbody';
47 BandwidthView.EVENTS_UL = 'data-reduction-proxy-view-events-list';
48 BandwidthView.STATS_BOX_ID = 'bandwidth-stats-table';
50 cr.addSingletonGetter(BandwidthView);
52 BandwidthView.prototype = {
53 // Inherit the superclass's methods.
54 __proto__: superClass.prototype,
56 data_reduction_proxy_config_: null,
58 bad_proxy_config_: null,
60 onLoadLogFinish: function(data) {
61 return this.onBadProxiesChanged(data.badProxies) &&
62 this.onDataReductionProxyInfoChanged(data.dataReductionProxyInfo) &&
63 (this.onSessionNetworkStatsChanged(data.sessionNetworkStats) ||
64 this.onHistoricNetworkStatsChanged(data.historicNetworkStats));
68 * Retains information on bandwidth usage this session.
70 onSessionNetworkStatsChanged: function(sessionNetworkStats) {
71 this.sessionNetworkStats_ = sessionNetworkStats;
72 return this.updateBandwidthUsageTable_();
76 * Displays information on bandwidth usage this session and over the
79 onHistoricNetworkStatsChanged: function(historicNetworkStats) {
80 this.historicNetworkStats_ = historicNetworkStats;
81 return this.updateBandwidthUsageTable_();
85 * Updates the UI based on receiving changes in information about the
86 * data reduction proxy summary.
88 onDataReductionProxyInfoChanged: function(info) {
89 $(BandwidthView.EVENTS_TBODY_ID).innerHTML = '';
95 $(BandwidthView.ENABLED_ID).innerText = 'Enabled';
96 $(BandwidthView.PROBE_STATUS_ID).innerText =
97 info.probe != null ? info.probe : 'N/A';
98 this.last_bypass_ = info.last_bypass;
99 this.data_reduction_proxy_config_ = info.proxy_config.params;
101 $(BandwidthView.ENABLED_ID).innerText = 'Disabled';
102 $(BandwidthView.PROBE_STATUS_ID).innerText = 'N/A';
103 this.data_reduction_proxy_config_ = null;
106 this.updateDataReductionProxyConfig_();
108 for (var eventIndex = info.events.length - 1; eventIndex >= 0;
110 var event = info.events[eventIndex];
111 var headerRow = addNode($(BandwidthView.EVENTS_TBODY_ID), 'tr');
112 var detailsRow = addNode($(BandwidthView.EVENTS_TBODY_ID), 'tr');
114 var timeCell = addNode(headerRow, 'td');
115 var actionCell = addNode(headerRow, 'td');
116 var detailsCell = addNode(detailsRow, 'td');
117 detailsCell.colSpan = 2;
118 detailsCell.className = 'data-reduction-proxy-view-events-details';
119 var eventTime = timeutil.convertTimeTicksToDate(event.time);
120 timeutil.addNodeWithDate(timeCell, eventTime);
121 this.buildEventRow_(event, actionCell, detailsCell);
128 * Updates the UI based on receiving changes in information about bad
131 onBadProxiesChanged: function(badProxies) {
135 var newBadProxies = [];
136 if (badProxies.length == 0) {
137 this.last_bypass_ = null;
139 for (var i = 0; i < badProxies.length; ++i) {
140 var entry = badProxies[i];
141 newBadProxies[entry.proxy_uri] = entry.bad_until;
144 this.bad_proxy_config_ = newBadProxies;
145 this.updateDataReductionProxyConfig_();
151 * Update the bandwidth usage table. Returns false on failure.
153 updateBandwidthUsageTable_: function() {
154 var sessionNetworkStats = this.sessionNetworkStats_;
155 var historicNetworkStats = this.historicNetworkStats_;
156 if (!sessionNetworkStats || !historicNetworkStats)
159 var sessionOriginal = sessionNetworkStats.session_original_content_length;
160 var sessionReceived = sessionNetworkStats.session_received_content_length;
161 var historicOriginal =
162 historicNetworkStats.historic_original_content_length;
163 var historicReceived =
164 historicNetworkStats.historic_received_content_length;
168 title: 'Original (KB)',
169 sessionValue: bytesToRoundedKilobytes_(sessionOriginal),
170 historicValue: bytesToRoundedKilobytes_(historicOriginal)
173 title: 'Received (KB)',
174 sessionValue: bytesToRoundedKilobytes_(sessionReceived),
175 historicValue: bytesToRoundedKilobytes_(historicReceived)
178 title: 'Savings (KB)',
180 bytesToRoundedKilobytes_(sessionOriginal - sessionReceived),
182 bytesToRoundedKilobytes_(historicOriginal - historicReceived)
185 title: 'Savings (%)',
186 sessionValue: getPercentSavings_(sessionOriginal, sessionReceived),
187 historicValue: getPercentSavings_(historicOriginal,
191 var input = new JsEvalContext({rows: rows});
192 jstProcess(input, $(BandwidthView.STATS_BOX_ID));
197 * Renders a Data Reduction Proxy event into the event tbody
199 buildEventRow_: function(event, actionCell, detailsCell) {
200 if (event.type == EventType.DATA_REDUCTION_PROXY_ENABLED &&
201 event.params.enabled == 0) {
202 addTextNode(actionCell, 'DISABLED');
205 EventTypeNames[event.type].replace('DATA_REDUCTION_PROXY_', '');
206 if (event.phase == EventPhase.PHASE_BEGIN ||
207 event.phase == EventPhase.PHASE_END) {
208 actionText = actionText + ' (' +
209 getKeyWithValue(EventPhase, event.phase)
210 .replace('PHASE_', '') + ')';
213 addTextNode(actionCell, actionText);
214 this.createEventTable_(event.params, detailsCell);
219 * Updates the data reduction proxy summary block.
221 updateDataReductionProxyConfig_: function() {
222 $(BandwidthView.PROXY_CONFIG_ID).innerHTML = '';
223 $(BandwidthView.BYPASS_STATE_ID).innerHTML = '';
224 setNodeDisplay($(BandwidthView.BYPASS_STATE_CONTAINER_ID), false);
226 if (this.data_reduction_proxy_config_) {
227 var hasBypassedProxy = false;
228 var now = timeutil.getCurrentTimeTicks();
230 if (this.last_bypass_ &&
231 this.hasTimePassedLogTime_(+this.last_bypass_.params.expiration)) {
232 // Best effort on iterating the config to search for a bad proxy.
233 // A server could exist in a string member of
234 // data_reduction_proxy_config_ or within an array of servers in an
235 // array member of data_reduction_proxy_config_. As such, search
236 // through all string members and string arrays.
237 for (var key in this.data_reduction_proxy_config_) {
238 var value = this.data_reduction_proxy_config_[key];
239 if (typeof value == 'string') {
240 if (this.isMarkedAsBad_(value)) {
241 hasBypassedProxy = true;
244 } else if (value instanceof Array) {
245 for (var index = 1; index < value.length; index++) {
246 if (this.isMarkedAsBad_(value[index])) {
247 hasBypassedProxy = true;
251 if (hasBypassedProxy) {
258 if (hasBypassedProxy) {
259 this.createEventTable_(this.last_bypass_.params,
260 $(BandwidthView.BYPASS_STATE_ID));
263 this.createEventTable_(this.data_reduction_proxy_config_,
264 $(BandwidthView.PROXY_CONFIG_ID));
265 setNodeDisplay($(BandwidthView.BYPASS_STATE_CONTAINER_ID),
271 * Checks to see if a proxy server is in marked as bad.
273 isMarkedAsBad_: function(proxy) {
274 for (var entry in this.bad_proxy_config_) {
275 if (entry == proxy &&
276 this.hasTimePassedLogTime_(this.bad_proxy_config_[entry])) {
285 * Checks to see if a given time in ticks has passed the time of the
286 * the log. For real time viewing, this is "now", but for loaded logs, it
287 * is the time at which the logs were taken.
289 hasTimePassedLogTime_: function(timeTicks) {
291 if (MainView.isViewingLoadedLog() && ClientInfo.numericDate) {
292 logTime = ClientInfo.numericDate;
294 logTime = timeutil.getCurrentTime();
297 return timeutil.convertTimeTicksToTime(timeTicks) > logTime;
301 * Creates a table of the object obj. Certain keys are special cased for
302 * ease of readability.
304 createEventTable_: function(obj, parentNode) {
305 if (Object.keys(obj).length > 0) {
306 var tableNode = addNode(parentNode, 'table');
307 tableNode.className = 'borderless-table';
308 for (var key in obj) {
309 var value = obj[key];
310 if (value != null && value.toString() != '') {
311 if (key == 'net_error') {
315 value = netErrorToString(value);
317 } else if (key == 'bypass_type') {
318 value = getKeyWithValue(DataReductionProxyBypassEventType, value);
319 } else if (key == 'bypass_action_type') {
320 value = getKeyWithValue(DataReductionProxyBypassActionType,
322 } else if (key == 'expiration') {
323 value = timeutil.convertTimeTicksToDate(value);
325 var tableRow = addNode(tableNode, 'tr');
326 addNodeWithText(tableRow, 'td', key);
327 addNodeWithText(tableRow, 'td', value);
335 * Converts bytes to kilobytes rounded to one decimal place.
337 function bytesToRoundedKilobytes_(val) {
338 return (val / 1024).toFixed(1);
342 * Returns bandwidth savings as a percent rounded to one decimal place.
344 function getPercentSavings_(original, received) {
346 return ((original - received) * 100 / original).toFixed(1);
351 return BandwidthView;