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_event_: 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 // Even though this information is included in log dumps, there's no real |
43 // reason to display it when debugging a loaded log file. | 67 // reason to display it when debugging a loaded log file. |
44 return false; | 68 return false; |
45 }, | 69 }, |
46 | 70 |
47 /** | 71 /** |
48 * Retains information on bandwidth usage this session. | 72 * Retains information on bandwidth usage this session. |
49 */ | 73 */ |
50 onSessionNetworkStatsChanged: function(sessionNetworkStats) { | 74 onSessionNetworkStatsChanged: function(sessionNetworkStats) { |
51 this.sessionNetworkStats_ = sessionNetworkStats; | 75 this.sessionNetworkStats_ = sessionNetworkStats; |
52 return this.updateBandwidthUsageTable_(); | 76 return this.updateBandwidthUsageTable_(); |
53 }, | 77 }, |
54 | 78 |
55 /** | 79 /** |
56 * Displays information on bandwidth usage this session and over the | 80 * Displays information on bandwidth usage this session and over the |
57 * browser's lifetime. | 81 * browser's lifetime. |
58 */ | 82 */ |
59 onHistoricNetworkStatsChanged: function(historicNetworkStats) { | 83 onHistoricNetworkStatsChanged: function(historicNetworkStats) { |
60 this.historicNetworkStats_ = historicNetworkStats; | 84 this.historicNetworkStats_ = historicNetworkStats; |
61 return this.updateBandwidthUsageTable_(); | 85 return this.updateBandwidthUsageTable_(); |
62 }, | 86 }, |
63 | 87 |
88 onDataReductionProxyInfoChanged: function(info) { | |
89 $(BandwidthView.EVENTS_TBODY_ID).innerHTML = ''; | |
90 | |
91 if (!info) | |
92 { | |
bengr
2014/12/02 23:55:32
Move up a line.
jeremyim
2014/12/03 08:10:36
Done.
| |
93 return false; | |
94 } | |
95 | |
96 if (info.enabled == 'true') { | |
97 $(BandwidthView.ENABLED_ID).innerText = 'Enabled'; | |
98 if (info.canary != null) { | |
99 $(BandwidthView.CANARY_STATUS_ID).innerText = info.canary; | |
100 } | |
101 if (info.last_bypass != null) { | |
102 this.last_bypass_ = this.parseBypassEvent_(info.last_bypass); | |
103 } | |
104 this.data_reduction_proxy_config_ = info.proxy_config.params; | |
105 } else { | |
106 $(BandwidthView.ENABLED_ID).innerText = 'Disabled'; | |
107 $(BandwidthView.CANARY_STATUS_ID).innerText = 'N/A'; | |
108 this.data_reduction_proxy_config_ = null; | |
109 } | |
110 | |
111 this.updateDataReductionProxyConfig_(); | |
112 | |
113 for (var eventIndex in info.events) { | |
114 var event = info.events[eventIndex]; | |
115 var headerRow = addNode($(BandwidthView.EVENTS_TBODY_ID), 'tr'); | |
116 var detailsRow = addNode($(BandwidthView.EVENTS_TBODY_ID), 'tr'); | |
117 | |
118 var timeCell = addNode(headerRow, 'td'); | |
119 var actionCell = addNode(headerRow, 'td'); | |
120 var detailsCell = addNode(detailsRow, 'td'); | |
121 detailsCell.colSpan = 2; | |
122 detailsCell.className = 'data-reduction-proxy-view-events-details'; | |
123 var eventTime = timeutil.convertTimeTicksToDate(event.time); | |
124 timeutil.addNodeWithDate(timeCell, eventTime); | |
125 | |
126 switch (event.type) { | |
127 case EventType.DATA_REDUCTION_PROXY_ENABLED: | |
128 this.buildEnabledRow_(event, actionCell, detailsCell); | |
129 break; | |
130 case EventType.DATA_REDUCTION_PROXY_CANARY_REQUEST: | |
131 this.buildCanaryRow_(event, actionCell, detailsCell); | |
132 break; | |
133 case EventType.DATA_REDUCTION_PROXY_CANARY_RESPONSE_RECEIVED: | |
134 this.buildCanaryResponseRow_(event, actionCell, detailsCell); | |
135 break; | |
136 case EventType.DATA_REDUCTION_PROXY_BYPASS_REQUESTED: | |
137 this.buildBypassRow_(event, actionCell, detailsCell); | |
138 break; | |
139 case EventType.DATA_REDUCTION_PROXY_FALLBACK: | |
140 this.buildFallbackRow_(event, actionCell, detailsCell); | |
141 break; | |
142 } | |
143 } | |
144 }, | |
145 | |
146 onProxySettingsChanged: function(proxySettings) { | |
147 var newProxySettings = []; | |
148 var effectiveSettings = proxySettings.effective; | |
149 if (effectiveSettings && effectiveSettings.proxy_per_scheme) { | |
150 for (var scheme in effectiveSettings.proxy_per_scheme) { | |
151 var schemeSettings = effectiveSettings.proxy_per_scheme[scheme]; | |
152 if (scheme != 'fallback') { | |
153 for (var i = 0; i < schemeSettings.length; ++i) { | |
154 var proxyUri = schemeSettings[i]; | |
155 if (proxyUri != 'direct://') { | |
156 newProxySettings.push(proxyUri); | |
157 } | |
158 } | |
159 } | |
160 } | |
161 } | |
162 this.proxy_config_ = newProxySettings; | |
163 this.updateDataReductionProxyConfig_(); | |
164 }, | |
165 | |
166 onBadProxiesChanged: function(badProxies) { | |
167 var newBadProxies = []; | |
168 if (badProxies.length == 0) { | |
169 this.last_bypass_ = null; | |
170 } else { | |
171 for (var i = 0; i < badProxies.length; ++i) { | |
172 var entry = badProxies[i]; | |
173 newBadProxies[entry.proxy_uri] = entry.bad_until; | |
174 } | |
175 } | |
176 this.bad_proxy_config_ = newBadProxies; | |
177 this.updateDataReductionProxyConfig_(); | |
178 }, | |
179 | |
64 /** | 180 /** |
65 * Update the bandwidth usage table. Returns false on failure. | 181 * Update the bandwidth usage table. Returns false on failure. |
66 */ | 182 */ |
67 updateBandwidthUsageTable_: function() { | 183 updateBandwidthUsageTable_: function() { |
68 var sessionNetworkStats = this.sessionNetworkStats_; | 184 var sessionNetworkStats = this.sessionNetworkStats_; |
69 var historicNetworkStats = this.historicNetworkStats_; | 185 var historicNetworkStats = this.historicNetworkStats_; |
70 if (!sessionNetworkStats || !historicNetworkStats) | 186 if (!sessionNetworkStats || !historicNetworkStats) |
71 return false; | 187 return false; |
72 | 188 |
73 var sessionOriginal = sessionNetworkStats.session_original_content_length; | 189 var sessionOriginal = sessionNetworkStats.session_original_content_length; |
(...skipping 22 matching lines...) Expand all Loading... | |
96 bytesToRoundedKilobytes_(historicOriginal - historicReceived) | 212 bytesToRoundedKilobytes_(historicOriginal - historicReceived) |
97 }); | 213 }); |
98 rows.push({ | 214 rows.push({ |
99 title: 'Savings (%)', | 215 title: 'Savings (%)', |
100 sessionValue: getPercentSavings_(sessionOriginal, sessionReceived), | 216 sessionValue: getPercentSavings_(sessionOriginal, sessionReceived), |
101 historicValue: getPercentSavings_(historicOriginal, | 217 historicValue: getPercentSavings_(historicOriginal, |
102 historicReceived) | 218 historicReceived) |
103 }); | 219 }); |
104 | 220 |
105 var input = new JsEvalContext({rows: rows}); | 221 var input = new JsEvalContext({rows: rows}); |
106 jstProcess(input, $(BandwidthView.MAIN_BOX_ID)); | 222 jstProcess(input, $(BandwidthView.STATS_BOX_ID)); |
107 return true; | 223 return true; |
224 }, | |
225 | |
226 buildEnabledRow_: function(event, actionCell, detailsCell) { | |
227 if (event.params.enabled == 1) { | |
228 addTextNode(actionCell, 'Proxy: Enabled'); | |
229 var proxyWrapper = addNode(detailsCell, 'div'); | |
230 addNodeWithText(proxyWrapper, 'div', 'Proxy configuration:'); | |
231 | |
232 if (event.params.primary_origin != null && | |
233 event.params.primary_origin.trim() != '') { | |
234 var proxyText = 'Primary: ' + event.params.primary_origin; | |
235 if (event.params.primary_restricted != null && | |
236 event.params.primary_restricted) { | |
237 proxyText += ' (restricted)'; | |
238 } | |
239 addNodeWithText(proxyWrapper, 'div', proxyText); | |
240 } | |
241 | |
242 if (event.params.fallback_origin != null && | |
243 event.params.fallback_origin.trim() != '') { | |
244 var proxyText = 'Fallback: ' + event.params.fallback_origin; | |
245 if (event.params.fallback_restricted != null && | |
246 event.params.fallback_restricted) { | |
247 proxyText += ' (restricted)'; | |
248 } | |
249 addNodeWithText(proxyWrapper, 'div', proxyText); | |
250 } | |
251 | |
252 if (event.params.ssl_origin != null && | |
253 event.params.ssl_origin.trim() != '') { | |
254 addNodeWithText(proxyWrapper, 'div', | |
255 'SSL: ' + event.params.ssl_origin); | |
256 } | |
257 } else { | |
258 addTextNode(actionCell, 'Proxy: Disabled'); | |
259 } | |
260 }, | |
261 | |
262 buildCanaryRow_: function(event, actionCell, detailsCell) { | |
263 if (event.phase == EventPhase.PHASE_BEGIN) { | |
264 addTextNode(actionCell, 'Canary request sent'); | |
265 addTextNode(detailsCell, 'URL: ' + event.params.url); | |
266 } else if (event.phase == EventPhase.PHASE_END) { | |
267 addTextNode(actionCell, 'Canary request completed'); | |
268 if (event.params.net_error == 0) { | |
269 addTextNode(detailsCell, 'Result: OK'); | |
270 } else { | |
271 addTextNode(detailsCell, | |
272 'Result: ' + netErrorToString(event.params.net_error)); | |
273 } | |
274 } | |
275 }, | |
276 | |
277 buildCanaryResponseRow_: function(event, actionCell, detailsCell) { | |
278 addTextNode(actionCell, 'Canary response received'); | |
279 }, | |
280 | |
281 buildBypassRow_: function(event, actionCell, detailsCell) { | |
282 var parsedBypass = this.parseBypassEvent_(event); | |
283 | |
284 addTextNode(actionCell, | |
285 'Bypass received (' + parsedBypass.bypass_reason + ')'); | |
286 var bypassWrapper = addNode(detailsCell, 'div'); | |
287 addNodeWithText(bypassWrapper, 'div', 'URL: ' + parsedBypass.origin_url); | |
288 addNodeWithText( | |
289 bypassWrapper, 'div', | |
290 'Bypassed for ' + parsedBypass.bypass_duration_seconds + ' seconds.'); | |
291 }, | |
292 | |
293 buildFallbackRow_: function(event, actionCell, detailsCell) { | |
294 addTextNode(actionCell, 'Proxy fallback'); | |
295 }, | |
296 | |
297 parseBypassEvent_: function(event) { | |
bengr
2014/12/02 23:55:32
Is this how the net events are visualized? It woul
jeremyim
2014/12/03 08:10:37
Net events uses the constants dictionary to perfor
| |
298 var reason; | |
299 if (event.params.action != null) { | |
300 reason = event.params.action; | |
301 } else { | |
302 switch (event.params.bypass_type) { | |
303 case 0: | |
304 reason = 'Bypass current request'; | |
305 break; | |
306 case 1: | |
307 reason = 'Bypass for short period'; | |
308 break; | |
309 case 2: | |
310 reason = 'Bypass for medium period'; | |
311 break; | |
312 case 3: | |
313 reason = 'Bypass for long period'; | |
314 break; | |
315 case 4: | |
316 reason = 'Missing Via Header 4xx'; | |
317 break; | |
318 case 5: | |
319 reason = 'Missing Via Header non-4xx'; | |
320 break; | |
321 case 6: | |
322 reason = '407'; | |
323 break; | |
324 case 7: | |
325 reason = '500'; | |
326 break; | |
327 case 8: | |
328 reason = '502'; | |
329 break; | |
330 case 9: | |
331 reason = '503'; | |
332 break; | |
333 case 10: | |
334 reason = 'Network error'; | |
335 break; | |
336 default: | |
337 reason = 'Unknown error'; | |
338 break; | |
339 } | |
340 } | |
341 | |
342 var parsedBypass = | |
343 { | |
bengr
2014/12/02 23:55:32
Move up a line.
jeremyim
2014/12/03 08:10:37
Done.
| |
344 bypass_reason: reason, | |
345 origin_url: event.params.url, | |
346 bypass_duration_seconds: event.params.bypass_duration_seconds, | |
347 bypass_expiration: event.params.expiration, | |
348 }; | |
349 | |
350 return parsedBypass; | |
351 }, | |
352 | |
353 updateDataReductionProxyConfig_: function() { | |
354 $(BandwidthView.PRIMARY_PROXY_ID).innerHTML = ''; | |
355 $(BandwidthView.SECONDARY_PROXY_ID).innerHTML = ''; | |
356 setNodeDisplay($(BandwidthView.BYPASS_STATE_CONTAINER_ID), false); | |
357 | |
358 if (this.data_reduction_proxy_config_) { | |
359 var primaryProxy = ''; | |
360 var secondaryProxy = ''; | |
361 var now = timeutil.getCurrentTimeTicks(); | |
362 | |
363 if (this.last_bypass_ && +this.last_bypass_.bypass_expiration > now) { | |
364 var input = new JsEvalContext(this.last_bypass_); | |
365 jstProcess(input, $(BandwidthView.BYPASS_STATE_CONTAINER_ID)); | |
366 } else { | |
367 var input = new JsEvalContext(); | |
368 jstProcess(input, $(BandwidthView.BYPASS_STATE_CONTAINER_ID)); | |
369 } | |
370 | |
371 if (this.data_reduction_proxy_config_.ssl_origin) { | |
372 primaryProxy = 'HTTPS Tunnel: ' + this.buildProxyString_( | |
373 this.data_reduction_proxy_config_.ssl_origin, false); | |
374 } | |
375 | |
376 if (this.data_reduction_proxy_config_.primary_origin) { | |
377 var proxyString = this.buildProxyString_( | |
378 this.data_reduction_proxy_config_.primary_origin, | |
379 this.data_reduction_proxy_config_.primary_restricted); | |
380 | |
381 if (primaryProxy == '') { | |
382 primaryProxy = proxyString; | |
383 } else { | |
384 secondaryProxy = proxyString; | |
385 } | |
386 } | |
387 | |
388 if (this.data_reduction_proxy_config_.fallback_origin) { | |
389 var proxyString = this.buildProxyString_( | |
390 this.data_reduction_proxy_config_.fallback_origin, | |
391 this.data_reduction_proxy_config_.fallback_restricted); | |
392 | |
393 if (primaryProxy == '') { | |
394 primaryProxy = proxyString; | |
395 } else if (secondaryProxy == '') { | |
396 secondaryProxy = proxyString; | |
397 } | |
398 } | |
399 | |
400 $(BandwidthView.PRIMARY_PROXY_ID).innerText = primaryProxy; | |
401 $(BandwidthView.SECONDARY_PROXY_ID).innerText = secondaryProxy; | |
402 } | |
403 }, | |
404 | |
405 buildProxyString_: function(proxy, restricted) { | |
406 var normalizedProxy = this.normalize_(proxy); | |
407 var configured = this.isConfigured_(normalizedProxy); | |
408 var bypassed = this.isBypassed_(normalizedProxy); | |
409 var proxyString = ''; | |
410 if (restricted) { | |
411 proxyString += proxy + ' (RESTRICTED)'; | |
412 } | |
413 else if (configured) { | |
414 proxyString += proxy; | |
415 if (bypassed) { | |
416 proxyString += ' (BYPASSED)'; | |
417 setNodeDisplay($(BandwidthView.BYPASS_STATE_CONTAINER_ID), true); | |
418 } else { | |
419 proxyString += ' (ACTIVE)'; | |
420 } | |
421 } | |
422 | |
423 return proxyString; | |
424 }, | |
425 | |
426 normalize_: function(proxy) { | |
427 function startsWith(str, prefix) { | |
428 return str.lastIndexOf(prefix, 0) == 0; | |
429 } | |
430 | |
431 function strContains(str, substr, startIndex) { | |
432 return str.indexOf(substr, startIndex) != -1; | |
433 } | |
434 | |
435 function endsWith(str, suffix) { | |
436 return str.indexOf(suffix, str.length - suffix.length) !== -1; | |
437 } | |
438 | |
439 function stripSuffix(str, suffix) { | |
440 if (!endsWith(str, suffix)) | |
441 return str; | |
442 return str.substring(str, str.length - suffix.length); | |
443 } | |
444 | |
445 var normalized = stripSuffix(proxy, '/'); | |
446 | |
447 if (startsWith(normalized, 'http://')) { | |
448 normalized = normalized.substr(7); | |
449 } | |
450 | |
451 if (startsWith(normalized, 'https://')) { | |
452 if (!strContains(normalized, ':', 7)) { | |
453 normalized += ':443'; | |
454 } | |
455 } else if (!strContains(normalized, ':', 0)) { | |
456 normalized += ':80'; | |
457 } | |
458 | |
459 return normalized; | |
460 }, | |
461 | |
462 isConfigured_: function(proxy) { | |
463 for (var index in this.proxy_config_) { | |
464 var entry = this.proxy_config_[index]; | |
465 if (entry == proxy) { | |
466 return true; | |
467 } | |
468 } | |
469 | |
470 return false; | |
471 }, | |
472 | |
473 isBypassed_: function(proxy) { | |
474 var now = timeutil.getCurrentTimeTicks(); | |
475 for (var entry in this.bad_proxy_config_) { | |
476 if (entry == proxy && this.bad_proxy_config_[entry] > now) { | |
477 return true; | |
478 } | |
479 } | |
480 | |
481 return false; | |
108 } | 482 } |
109 }; | 483 }; |
110 | 484 |
111 /** | 485 /** |
112 * Converts bytes to kilobytes rounded to one decimal place. | 486 * Converts bytes to kilobytes rounded to one decimal place. |
113 */ | 487 */ |
114 function bytesToRoundedKilobytes_(val) { | 488 function bytesToRoundedKilobytes_(val) { |
115 return (val / 1024).toFixed(1); | 489 return (val / 1024).toFixed(1); |
116 } | 490 } |
117 | 491 |
118 /** | 492 /** |
119 * Returns bandwidth savings as a percent rounded to one decimal place. | 493 * Returns bandwidth savings as a percent rounded to one decimal place. |
120 */ | 494 */ |
121 function getPercentSavings_(original, received) { | 495 function getPercentSavings_(original, received) { |
122 if (original > 0) { | 496 if (original > 0) { |
123 return ((original - received) * 100 / original).toFixed(1); | 497 return ((original - received) * 100 / original).toFixed(1); |
124 } | 498 } |
125 return '0.0'; | 499 return '0.0'; |
126 } | 500 } |
127 | 501 |
128 return BandwidthView; | 502 return BandwidthView; |
129 })(); | 503 })(); |
OLD | NEW |