OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 /** This view displays summary statistics on bandwidth usage. */ | 5 /** This view displays summary statistics on bandwidth usage. */ |
6 var BandwidthView = (function() { | 6 var BandwidthView = (function() { |
7 'use strict'; | 7 'use strict'; |
8 | 8 |
9 // We inherit from DivView. | 9 // We inherit from DivView. |
10 var superClass = DivView; | 10 var superClass = DivView; |
11 | 11 |
12 /** | 12 /** |
13 * @constructor | 13 * @constructor |
14 */ | 14 */ |
15 function BandwidthView() { | 15 function BandwidthView() { |
16 assertFirstConstructorCall(BandwidthView); | 16 assertFirstConstructorCall(BandwidthView); |
17 | 17 |
18 // Call superclass's constructor. | 18 // Call superclass's constructor. |
19 superClass.call(this, BandwidthView.MAIN_BOX_ID); | 19 superClass.call(this, BandwidthView.MAIN_BOX_ID); |
20 | 20 |
21 g_browser.addSessionNetworkStatsObserver(this, true); | 21 g_browser.addSessionNetworkStatsObserver(this, true); |
22 g_browser.addHistoricNetworkStatsObserver(this, true); | 22 g_browser.addHistoricNetworkStatsObserver(this, true); |
23 | 23 |
24 // Register to receive data reduction proxy info. | |
25 g_browser.addDataReductionProxyInfoObserver(this, true); | |
26 | |
27 // Register to receive proxy settings. | |
28 g_browser.addProxySettingsObserver(this, true); | |
29 | |
30 // Register to receive bad proxy info. | |
31 g_browser.addBadProxiesObserver(this, true); | |
32 | |
24 this.sessionNetworkStats_ = null; | 33 this.sessionNetworkStats_ = null; |
25 this.historicNetworkStats_ = null; | 34 this.historicNetworkStats_ = null; |
26 } | 35 } |
27 | 36 |
28 BandwidthView.TAB_ID = 'tab-handle-bandwidth'; | 37 BandwidthView.TAB_ID = 'tab-handle-bandwidth'; |
29 BandwidthView.TAB_NAME = 'Bandwidth'; | 38 BandwidthView.TAB_NAME = 'Bandwidth'; |
30 BandwidthView.TAB_HASH = '#bandwidth'; | 39 BandwidthView.TAB_HASH = '#bandwidth'; |
31 | 40 |
32 // IDs for special HTML elements in bandwidth_view.html | 41 // IDs for special HTML elements in bandwidth_view.html |
33 BandwidthView.MAIN_BOX_ID = 'bandwidth-view-tab-content'; | 42 BandwidthView.MAIN_BOX_ID = 'bandwidth-view-tab-content'; |
43 BandwidthView.ENABLED_ID = 'data-reduction-proxy-enabled'; | |
44 BandwidthView.PRIMARY_PROXY_ID = 'data-reduction-proxy-primary'; | |
45 BandwidthView.SECONDARY_PROXY_ID = 'data-reduction-proxy-secondary'; | |
46 BandwidthView.CANARY_STATUS_ID = 'data-reduction-proxy-canary-status'; | |
47 BandwidthView.BYPASS_STATE_ID = 'data-reduction-proxy-bypass-state'; | |
48 BandwidthView.BYPASS_STATE_CONTAINER_ID = | |
49 'data-reduction-proxy-bypass-state-container'; | |
50 BandwidthView.EVENTS_TBODY_ID = 'data-reduction-proxy-view-events-tbody'; | |
51 BandwidthView.EVENTS_UL = 'data-reduction-proxy-view-events-list'; | |
52 BandwidthView.STATS_BOX_ID = 'bandwidth-stats-table'; | |
34 | 53 |
35 cr.addSingletonGetter(BandwidthView); | 54 cr.addSingletonGetter(BandwidthView); |
36 | 55 |
37 BandwidthView.prototype = { | 56 BandwidthView.prototype = { |
38 // Inherit the superclass's methods. | 57 // Inherit the superclass's methods. |
39 __proto__: superClass.prototype, | 58 __proto__: superClass.prototype, |
40 | 59 |
60 data_reduction_proxy_config_: null, | |
61 last_bypass_: null, | |
62 proxy_config_: null, | |
63 bad_proxy_config_: null, | |
64 | |
41 onLoadLogFinish: function(data) { | 65 onLoadLogFinish: function(data) { |
42 // Even though this information is included in log dumps, there's no real | 66 return this.onBadProxiesChanged(data.badProxies) && |
43 // reason to display it when debugging a loaded log file. | 67 this.onProxySettingsChanged(data.proxySettings) && |
44 return false; | 68 this.onDataReductionProxyInfoChanged(data.dataReductionProxyInfo) && |
69 (this.onSessionNetworkStatsChanged(data.sessionNetworkStats) || | |
70 this.onHistoricNetworkStatsChanged(data.historicNetworkStats)); | |
45 }, | 71 }, |
46 | 72 |
47 /** | 73 /** |
48 * Retains information on bandwidth usage this session. | 74 * Retains information on bandwidth usage this session. |
49 */ | 75 */ |
50 onSessionNetworkStatsChanged: function(sessionNetworkStats) { | 76 onSessionNetworkStatsChanged: function(sessionNetworkStats) { |
51 this.sessionNetworkStats_ = sessionNetworkStats; | 77 this.sessionNetworkStats_ = sessionNetworkStats; |
52 return this.updateBandwidthUsageTable_(); | 78 return this.updateBandwidthUsageTable_(); |
53 }, | 79 }, |
54 | 80 |
55 /** | 81 /** |
56 * Displays information on bandwidth usage this session and over the | 82 * Displays information on bandwidth usage this session and over the |
57 * browser's lifetime. | 83 * browser's lifetime. |
58 */ | 84 */ |
59 onHistoricNetworkStatsChanged: function(historicNetworkStats) { | 85 onHistoricNetworkStatsChanged: function(historicNetworkStats) { |
60 this.historicNetworkStats_ = historicNetworkStats; | 86 this.historicNetworkStats_ = historicNetworkStats; |
61 return this.updateBandwidthUsageTable_(); | 87 return this.updateBandwidthUsageTable_(); |
62 }, | 88 }, |
63 | 89 |
64 /** | 90 /** |
91 * Updates the UI based on receiving changes in information about the | |
92 * data reduction proxy summary. | |
93 */ | |
94 onDataReductionProxyInfoChanged: function(info) { | |
95 $(BandwidthView.EVENTS_TBODY_ID).innerHTML = ''; | |
96 | |
97 if (!info) | |
98 return false; | |
99 | |
100 if (info.enabled) { | |
101 $(BandwidthView.ENABLED_ID).innerText = 'Enabled'; | |
102 $(BandwidthView.CANARY_STATUS_ID).innerText = | |
103 info.canary != null ? info.canary : 'N/A'; | |
104 this.last_bypass_ = info.last_bypass != null ? | |
105 this.parseBypassEvent_(info.last_bypass) : null; | |
106 this.data_reduction_proxy_config_ = info.proxy_config.params; | |
107 } else { | |
108 $(BandwidthView.ENABLED_ID).innerText = 'Disabled'; | |
109 $(BandwidthView.CANARY_STATUS_ID).innerText = 'N/A'; | |
110 this.data_reduction_proxy_config_ = null; | |
111 } | |
112 | |
113 this.updateDataReductionProxyConfig_(); | |
114 | |
115 for (var eventIndex = info.events.length - 1; eventIndex >= 0; | |
116 --eventIndex) { | |
117 var event = info.events[eventIndex]; | |
118 var headerRow = addNode($(BandwidthView.EVENTS_TBODY_ID), 'tr'); | |
119 var detailsRow = addNode($(BandwidthView.EVENTS_TBODY_ID), 'tr'); | |
120 | |
121 var timeCell = addNode(headerRow, 'td'); | |
122 var actionCell = addNode(headerRow, 'td'); | |
123 var detailsCell = addNode(detailsRow, 'td'); | |
124 detailsCell.colSpan = 2; | |
125 detailsCell.className = 'data-reduction-proxy-view-events-details'; | |
126 var eventTime = timeutil.convertTimeTicksToDate(event.time); | |
127 timeutil.addNodeWithDate(timeCell, eventTime); | |
128 | |
129 switch (event.type) { | |
130 case EventType.DATA_REDUCTION_PROXY_ENABLED: | |
131 this.buildEnabledRow_(event, actionCell, detailsCell); | |
132 break; | |
133 case EventType.DATA_REDUCTION_PROXY_CANARY_REQUEST: | |
134 this.buildCanaryRow_(event, actionCell, detailsCell); | |
135 break; | |
136 case EventType.DATA_REDUCTION_PROXY_CANARY_RESPONSE_RECEIVED: | |
137 this.buildCanaryResponseRow_(event, actionCell, detailsCell); | |
138 break; | |
139 case EventType.DATA_REDUCTION_PROXY_BYPASS_REQUESTED: | |
140 this.buildBypassRow_(event, actionCell, detailsCell); | |
141 break; | |
142 case EventType.DATA_REDUCTION_PROXY_FALLBACK: | |
143 this.buildFallbackRow_(event, actionCell, detailsCell); | |
144 break; | |
145 } | |
146 } | |
147 | |
148 return true; | |
149 }, | |
150 | |
151 /** | |
152 * Updates the UI based on receiving changes in information about the | |
153 * proxy settings. | |
154 */ | |
155 onProxySettingsChanged: function(proxySettings) { | |
156 var newProxySettings = []; | |
157 var effectiveSettings = proxySettings.effective; | |
158 if (effectiveSettings && effectiveSettings.proxy_per_scheme) { | |
159 for (var scheme in effectiveSettings.proxy_per_scheme) { | |
160 var schemeSettings = effectiveSettings.proxy_per_scheme[scheme]; | |
161 if (scheme != 'fallback') { | |
162 for (var i = 0; i < schemeSettings.length; ++i) { | |
163 var proxyUri = schemeSettings[i]; | |
164 if (proxyUri != 'direct://') | |
165 newProxySettings.push(proxyUri); | |
166 } | |
167 } | |
168 } | |
169 } | |
170 this.proxy_config_ = newProxySettings; | |
171 this.updateDataReductionProxyConfig_(); | |
172 | |
173 return true; | |
174 }, | |
175 | |
176 /** | |
177 * Updates the UI based on receiving changes in information about bad | |
178 * proxy servers. | |
179 */ | |
180 onBadProxiesChanged: function(badProxies) { | |
181 var newBadProxies = []; | |
182 if (badProxies.length == 0) { | |
183 this.last_bypass_ = null; | |
184 } else { | |
185 for (var i = 0; i < badProxies.length; ++i) { | |
186 var entry = badProxies[i]; | |
187 newBadProxies[entry.proxy_uri] = entry.bad_until; | |
188 } | |
189 } | |
190 this.bad_proxy_config_ = newBadProxies; | |
191 this.updateDataReductionProxyConfig_(); | |
192 | |
193 return true; | |
194 }, | |
195 | |
196 /** | |
65 * Update the bandwidth usage table. Returns false on failure. | 197 * Update the bandwidth usage table. Returns false on failure. |
66 */ | 198 */ |
67 updateBandwidthUsageTable_: function() { | 199 updateBandwidthUsageTable_: function() { |
68 var sessionNetworkStats = this.sessionNetworkStats_; | 200 var sessionNetworkStats = this.sessionNetworkStats_; |
69 var historicNetworkStats = this.historicNetworkStats_; | 201 var historicNetworkStats = this.historicNetworkStats_; |
70 if (!sessionNetworkStats || !historicNetworkStats) | 202 if (!sessionNetworkStats || !historicNetworkStats) |
71 return false; | 203 return false; |
72 | 204 |
73 var sessionOriginal = sessionNetworkStats.session_original_content_length; | 205 var sessionOriginal = sessionNetworkStats.session_original_content_length; |
74 var sessionReceived = sessionNetworkStats.session_received_content_length; | 206 var sessionReceived = sessionNetworkStats.session_received_content_length; |
(...skipping 21 matching lines...) Expand all Loading... | |
96 bytesToRoundedKilobytes_(historicOriginal - historicReceived) | 228 bytesToRoundedKilobytes_(historicOriginal - historicReceived) |
97 }); | 229 }); |
98 rows.push({ | 230 rows.push({ |
99 title: 'Savings (%)', | 231 title: 'Savings (%)', |
100 sessionValue: getPercentSavings_(sessionOriginal, sessionReceived), | 232 sessionValue: getPercentSavings_(sessionOriginal, sessionReceived), |
101 historicValue: getPercentSavings_(historicOriginal, | 233 historicValue: getPercentSavings_(historicOriginal, |
102 historicReceived) | 234 historicReceived) |
103 }); | 235 }); |
104 | 236 |
105 var input = new JsEvalContext({rows: rows}); | 237 var input = new JsEvalContext({rows: rows}); |
106 jstProcess(input, $(BandwidthView.MAIN_BOX_ID)); | 238 jstProcess(input, $(BandwidthView.STATS_BOX_ID)); |
107 return true; | 239 return true; |
240 }, | |
241 | |
242 /** | |
243 * Renders a data reduction proxy enabled/disabled event into the event | |
244 * tbody. | |
245 */ | |
246 buildEnabledRow_: function(event, actionCell, detailsCell) { | |
247 if (event.params.enabled == 1) { | |
248 addTextNode(actionCell, 'Proxy: Enabled'); | |
249 var proxyWrapper = addNode(detailsCell, 'div'); | |
250 addNodeWithText(proxyWrapper, 'div', 'Proxy configuration:'); | |
251 | |
252 if (event.params.primary_origin != null && | |
253 event.params.primary_origin.trim() != '') { | |
254 var proxyText = 'Primary: ' + event.params.primary_origin; | |
255 if (event.params.primary_restricted != null && | |
256 event.params.primary_restricted) { | |
257 proxyText += ' (restricted)'; | |
258 } | |
259 addNodeWithText(proxyWrapper, 'div', proxyText); | |
260 } | |
261 | |
262 if (event.params.fallback_origin != null && | |
263 event.params.fallback_origin.trim() != '') { | |
264 var proxyText = 'Fallback: ' + event.params.fallback_origin; | |
265 if (event.params.fallback_restricted != null && | |
266 event.params.fallback_restricted) { | |
267 proxyText += ' (restricted)'; | |
268 } | |
269 addNodeWithText(proxyWrapper, 'div', proxyText); | |
270 } | |
271 | |
272 if (event.params.ssl_origin != null && | |
273 event.params.ssl_origin.trim() != '') { | |
274 addNodeWithText(proxyWrapper, 'div', | |
275 'SSL: ' + event.params.ssl_origin); | |
276 } | |
277 } else { | |
278 addTextNode(actionCell, 'Proxy: Disabled'); | |
279 } | |
280 }, | |
281 | |
282 /** | |
283 * Renders a data reduction proxy canary request event into the event | |
284 * tbody. | |
285 */ | |
286 buildCanaryRow_: function(event, actionCell, detailsCell) { | |
287 if (event.phase == EventPhase.PHASE_BEGIN) { | |
288 addTextNode(actionCell, 'Canary request sent'); | |
289 addTextNode(detailsCell, 'URL: ' + event.params.url); | |
290 } else if (event.phase == EventPhase.PHASE_END) { | |
291 addTextNode(actionCell, 'Canary request completed'); | |
292 if (event.params.net_error == 0) { | |
293 addTextNode(detailsCell, 'Result: OK'); | |
294 } else { | |
295 addTextNode(detailsCell, | |
296 'Result: ' + netErrorToString(event.params.net_error)); | |
297 } | |
298 } | |
299 }, | |
300 | |
301 /** | |
302 * Renders a data reduction proxy canary response event into the event | |
303 * tbody. | |
304 */ | |
305 buildCanaryResponseRow_: function(event, actionCell, detailsCell) { | |
306 addTextNode(actionCell, 'Canary response received'); | |
307 }, | |
308 | |
309 /** | |
310 * Renders a data reduction proxy bypass event into the event tbody. | |
311 */ | |
312 buildBypassRow_: function(event, actionCell, detailsCell) { | |
313 var parsedBypass = this.parseBypassEvent_(event); | |
314 | |
315 addTextNode(actionCell, | |
316 'Bypass received (' + parsedBypass.bypass_reason + ')'); | |
317 var bypassWrapper = addNode(detailsCell, 'div'); | |
318 addNodeWithText(bypassWrapper, 'div', 'URL: ' + parsedBypass.origin_url); | |
319 addNodeWithText( | |
320 bypassWrapper, 'div', | |
321 'Bypassed for ' + parsedBypass.bypass_duration_seconds + ' seconds.'); | |
322 }, | |
323 | |
324 /** | |
325 * Renders a data reduction proxy fallback event into the event tbody. | |
326 */ | |
327 buildFallbackRow_: function(event, actionCell, detailsCell) { | |
328 addTextNode(actionCell, 'Proxy fallback'); | |
329 }, | |
330 | |
331 /** | |
332 * Parses a data reduction proxy bypass event for use in the summary and | |
333 * in the event tbody. | |
334 */ | |
335 parseBypassEvent_: function(event) { | |
336 var reason; | |
337 if (event.params.action != null) { | |
338 reason = event.params.action; | |
339 } else { | |
340 reason = getKeyWithValue( | |
341 DataReductionProxyBypassEventType, event.params.bypass_type); | |
342 } | |
343 | |
344 var parsedBypass = { | |
345 bypass_reason: reason, | |
346 origin_url: event.params.url, | |
347 bypass_duration_seconds: event.params.bypass_duration_seconds, | |
348 bypass_expiration: event.params.expiration, | |
349 }; | |
350 | |
351 return parsedBypass; | |
352 }, | |
353 | |
354 /** | |
355 * Updates the data reduction proxy summary block. | |
356 */ | |
357 updateDataReductionProxyConfig_: function() { | |
358 $(BandwidthView.PRIMARY_PROXY_ID).innerHTML = ''; | |
359 $(BandwidthView.SECONDARY_PROXY_ID).innerHTML = ''; | |
360 setNodeDisplay($(BandwidthView.BYPASS_STATE_CONTAINER_ID), false); | |
361 | |
362 if (this.data_reduction_proxy_config_) { | |
363 var primaryProxy = ''; | |
364 var secondaryProxy = ''; | |
365 var hasBypassedProxy = false; | |
366 var now = timeutil.getCurrentTimeTicks(); | |
367 | |
368 if (this.last_bypass_ && +this.last_bypass_.bypass_expiration > now) { | |
369 var input = new JsEvalContext(this.last_bypass_); | |
370 jstProcess(input, $(BandwidthView.BYPASS_STATE_CONTAINER_ID)); | |
371 } else { | |
372 var input = new JsEvalContext(); | |
373 jstProcess(input, $(BandwidthView.BYPASS_STATE_CONTAINER_ID)); | |
374 } | |
375 | |
376 if (this.data_reduction_proxy_config_.ssl_origin) { | |
377 if (this.isMarkedAsBad_(this.data_reduction_proxy_config_.ssl_origin)) | |
378 hasBypassedProxy = true; | |
379 | |
380 primaryProxy = 'HTTPS Tunnel: ' + this.buildProxyString_( | |
381 this.data_reduction_proxy_config_.ssl_origin, false); | |
382 } | |
383 | |
384 if (this.data_reduction_proxy_config_.primary_origin) { | |
385 if (this.isMarkedAsBad_( | |
386 this.data_reduction_proxy_config_.primary_origin)) | |
387 hasBypassedProxy = true; | |
388 | |
389 var proxyString = this.buildProxyString_( | |
390 this.data_reduction_proxy_config_.primary_origin, | |
391 this.data_reduction_proxy_config_.primary_restricted); | |
392 | |
393 if (primaryProxy == '') | |
394 primaryProxy = proxyString; | |
395 else | |
396 secondaryProxy = proxyString; | |
397 } | |
398 | |
399 if (this.data_reduction_proxy_config_.fallback_origin) { | |
400 if (this.isMarkedAsBad_( | |
401 this.data_reduction_proxy_config_.fallback_origin)) | |
402 hasBypassedProxy = true; | |
403 | |
404 var proxyString = this.buildProxyString_( | |
405 this.data_reduction_proxy_config_.fallback_origin, | |
406 this.data_reduction_proxy_config_.fallback_restricted); | |
407 | |
408 if (primaryProxy == '') | |
409 primaryProxy = proxyString; | |
410 else if (secondaryProxy == '') | |
411 secondaryProxy = proxyString; | |
412 } | |
413 | |
414 $(BandwidthView.PRIMARY_PROXY_ID).innerText = primaryProxy; | |
415 $(BandwidthView.SECONDARY_PROXY_ID).innerText = secondaryProxy; | |
416 if (hasBypassedProxy) | |
417 setNodeDisplay($(BandwidthView.BYPASS_STATE_CONTAINER_ID), true); | |
418 } | |
419 }, | |
420 | |
421 /** | |
422 * Takes a data reduction proxy configuration and renders to a friendly | |
423 * string. | |
424 */ | |
425 buildProxyString_: function(proxy, restricted) { | |
426 var configured = this.isConfigured_(proxy); | |
427 var markedAsBad = this.isMarkedAsBad_(proxy); | |
428 var proxyString = ''; | |
429 if (restricted) { | |
430 proxyString += proxy + ' (RESTRICTED)'; | |
431 } else if (configured) { | |
432 proxyString += proxy; | |
433 if (markedAsBad) { | |
434 proxyString += ' (BYPASSED)'; | |
435 } else { | |
436 proxyString += ' (ACTIVE)'; | |
437 } | |
438 } | |
439 | |
440 return proxyString; | |
441 }, | |
442 | |
443 /** | |
444 * Checks to see if a proxy server is in the current configuration. | |
445 */ | |
446 isConfigured_: function(proxy) { | |
447 for (var index in this.proxy_config_) { | |
448 var entry = this.proxy_config_[index]; | |
449 if (entry == proxy) | |
450 return true; | |
451 } | |
452 | |
453 return false; | |
454 }, | |
455 | |
456 /** | |
457 * Checks to see if a proxy server is in marked as bad. | |
458 */ | |
459 isMarkedAsBad_: function(proxy) { | |
460 for (var entry in this.bad_proxy_config_) { | |
461 if (entry == proxy && | |
462 this.hasTimePassedLogTime_(this.bad_proxy_config_[entry])) | |
463 return true; | |
mmenke
2014/12/10 21:09:43
nit: +braces
jeremyim
2014/12/11 05:24:21
Done.
| |
464 } | |
465 | |
466 return false; | |
467 }, | |
468 | |
469 /** | |
470 * Checks to see if a given time in ticks has passed the time of the | |
471 * the log. For real time viewing, this is "now", but for loaded logs, it | |
472 * is the time at which the logs were taken. | |
473 */ | |
474 hasTimePassedLogTime_: function(timeTicks) { | |
475 var logTime; | |
476 if (MainView.isViewingLoadedLog() && ClientInfo.numericDate) { | |
477 logTime = ClientInfo.numericDate; | |
478 } else { | |
479 logTime = timeutil.getCurrentTime(); | |
480 } | |
481 | |
482 return timeutil.convertTimeTicksToTime(timeTicks) > logTime; | |
108 } | 483 } |
109 }; | 484 }; |
110 | 485 |
111 /** | 486 /** |
112 * Converts bytes to kilobytes rounded to one decimal place. | 487 * Converts bytes to kilobytes rounded to one decimal place. |
113 */ | 488 */ |
114 function bytesToRoundedKilobytes_(val) { | 489 function bytesToRoundedKilobytes_(val) { |
115 return (val / 1024).toFixed(1); | 490 return (val / 1024).toFixed(1); |
116 } | 491 } |
117 | 492 |
118 /** | 493 /** |
119 * Returns bandwidth savings as a percent rounded to one decimal place. | 494 * Returns bandwidth savings as a percent rounded to one decimal place. |
120 */ | 495 */ |
121 function getPercentSavings_(original, received) { | 496 function getPercentSavings_(original, received) { |
122 if (original > 0) { | 497 if (original > 0) { |
123 return ((original - received) * 100 / original).toFixed(1); | 498 return ((original - received) * 100 / original).toFixed(1); |
124 } | 499 } |
125 return '0.0'; | 500 return '0.0'; |
126 } | 501 } |
127 | 502 |
128 return BandwidthView; | 503 return BandwidthView; |
129 })(); | 504 })(); |
OLD | NEW |