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
;