OLD | NEW |
(Empty) | |
| 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. |
| 4 |
| 5 /** This view displays summary statistics on bandwidth usage. */ |
| 6 var BandwidthView = (function() { |
| 7 'use strict'; |
| 8 |
| 9 // We inherit from DivView. |
| 10 var superClass = DivView; |
| 11 |
| 12 /** |
| 13 * @constructor |
| 14 */ |
| 15 function BandwidthView() { |
| 16 assertFirstConstructorCall(BandwidthView); |
| 17 |
| 18 // Call superclass's constructor. |
| 19 superClass.call(this, BandwidthView.MAIN_BOX_ID); |
| 20 |
| 21 g_browser.addSessionNetworkStatsObserver(this, true); |
| 22 g_browser.addHistoricNetworkStatsObserver(this, true); |
| 23 |
| 24 // Register to receive data reduction proxy info. |
| 25 g_browser.addDataReductionProxyInfoObserver(this, true); |
| 26 |
| 27 // Register to receive bad proxy info. |
| 28 g_browser.addBadProxiesObserver(this, true); |
| 29 |
| 30 this.sessionNetworkStats_ = null; |
| 31 this.historicNetworkStats_ = null; |
| 32 } |
| 33 |
| 34 BandwidthView.TAB_ID = 'tab-handle-bandwidth'; |
| 35 BandwidthView.TAB_NAME = 'Bandwidth'; |
| 36 BandwidthView.TAB_HASH = '#bandwidth'; |
| 37 |
| 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'; |
| 49 BandwidthView.SAVINGS_TBODY_ID = 'bandwidth-savings-tbody'; |
| 50 |
| 51 cr.addSingletonGetter(BandwidthView); |
| 52 |
| 53 BandwidthView.prototype = { |
| 54 // Inherit the superclass's methods. |
| 55 __proto__: superClass.prototype, |
| 56 |
| 57 data_reduction_proxy_config_: null, |
| 58 last_bypass_: null, |
| 59 bad_proxy_config_: null, |
| 60 |
| 61 onLoadLogFinish: function(data) { |
| 62 return this.onBadProxiesChanged(data.badProxies) && |
| 63 this.onDataReductionProxyInfoChanged(data.dataReductionProxyInfo) && |
| 64 (this.onSessionNetworkStatsChanged(data.sessionNetworkStats) || |
| 65 this.onHistoricNetworkStatsChanged(data.historicNetworkStats)); |
| 66 }, |
| 67 |
| 68 /** |
| 69 * Retains information on bandwidth usage this session. |
| 70 */ |
| 71 onSessionNetworkStatsChanged: function(sessionNetworkStats) { |
| 72 this.sessionNetworkStats_ = sessionNetworkStats; |
| 73 return this.updateBandwidthUsageTable_(); |
| 74 }, |
| 75 |
| 76 /** |
| 77 * Displays information on bandwidth usage this session and over the |
| 78 * browser's lifetime. |
| 79 */ |
| 80 onHistoricNetworkStatsChanged: function(historicNetworkStats) { |
| 81 this.historicNetworkStats_ = historicNetworkStats; |
| 82 return this.updateBandwidthUsageTable_(); |
| 83 }, |
| 84 |
| 85 /** |
| 86 * Updates the UI based on receiving changes in information about the |
| 87 * data reduction proxy summary. |
| 88 */ |
| 89 onDataReductionProxyInfoChanged: function(info) { |
| 90 $(BandwidthView.EVENTS_TBODY_ID).innerHTML = ''; |
| 91 |
| 92 if (!info) |
| 93 return false; |
| 94 |
| 95 if (info.enabled) { |
| 96 $(BandwidthView.ENABLED_ID).innerText = 'Enabled'; |
| 97 $(BandwidthView.PROBE_STATUS_ID).innerText = |
| 98 info.probe != null ? info.probe : 'N/A'; |
| 99 this.last_bypass_ = info.last_bypass; |
| 100 this.data_reduction_proxy_config_ = info.proxy_config.params; |
| 101 } else { |
| 102 $(BandwidthView.ENABLED_ID).innerText = 'Disabled'; |
| 103 $(BandwidthView.PROBE_STATUS_ID).innerText = 'N/A'; |
| 104 this.data_reduction_proxy_config_ = null; |
| 105 } |
| 106 |
| 107 this.updateDataReductionProxyConfig_(); |
| 108 |
| 109 for (var eventIndex = info.events.length - 1; eventIndex >= 0; |
| 110 --eventIndex) { |
| 111 var event = info.events[eventIndex]; |
| 112 var headerRow = addNode($(BandwidthView.EVENTS_TBODY_ID), 'tr'); |
| 113 var detailsRow = addNode($(BandwidthView.EVENTS_TBODY_ID), 'tr'); |
| 114 |
| 115 var timeCell = addNode(headerRow, 'td'); |
| 116 var actionCell = addNode(headerRow, 'td'); |
| 117 var detailsCell = addNode(detailsRow, 'td'); |
| 118 detailsCell.colSpan = 2; |
| 119 detailsCell.className = 'data-reduction-proxy-view-events-details'; |
| 120 var eventTime = timeutil.convertTimeTicksToDate(event.time); |
| 121 timeutil.addNodeWithDate(timeCell, eventTime); |
| 122 this.buildEventRow_(event, actionCell, detailsCell); |
| 123 } |
| 124 |
| 125 return true; |
| 126 }, |
| 127 |
| 128 /** |
| 129 * Updates the UI based on receiving changes in information about bad |
| 130 * proxy servers. |
| 131 */ |
| 132 onBadProxiesChanged: function(badProxies) { |
| 133 if (!badProxies) |
| 134 return false; |
| 135 |
| 136 var newBadProxies = []; |
| 137 if (badProxies.length == 0) { |
| 138 this.last_bypass_ = null; |
| 139 } else { |
| 140 for (var i = 0; i < badProxies.length; ++i) { |
| 141 var entry = badProxies[i]; |
| 142 newBadProxies[entry.proxy_uri] = entry.bad_until; |
| 143 } |
| 144 } |
| 145 this.bad_proxy_config_ = newBadProxies; |
| 146 this.updateDataReductionProxyConfig_(); |
| 147 |
| 148 return true; |
| 149 }, |
| 150 |
| 151 /** |
| 152 * Update the bandwidth usage table. Returns false on failure. |
| 153 */ |
| 154 updateBandwidthUsageTable_: function() { |
| 155 var sessionNetworkStats = this.sessionNetworkStats_; |
| 156 var historicNetworkStats = this.historicNetworkStats_; |
| 157 if (!sessionNetworkStats || !historicNetworkStats) |
| 158 return false; |
| 159 |
| 160 var sessionOriginal = sessionNetworkStats.session_original_content_length; |
| 161 var sessionReceived = sessionNetworkStats.session_received_content_length; |
| 162 var historicOriginal = |
| 163 historicNetworkStats.historic_original_content_length; |
| 164 var historicReceived = |
| 165 historicNetworkStats.historic_received_content_length; |
| 166 |
| 167 var rows = []; |
| 168 rows.push({ |
| 169 title: 'Original (KB)', |
| 170 sessionValue: bytesToRoundedKilobytes_(sessionOriginal), |
| 171 historicValue: bytesToRoundedKilobytes_(historicOriginal) |
| 172 }); |
| 173 rows.push({ |
| 174 title: 'Received (KB)', |
| 175 sessionValue: bytesToRoundedKilobytes_(sessionReceived), |
| 176 historicValue: bytesToRoundedKilobytes_(historicReceived) |
| 177 }); |
| 178 rows.push({ |
| 179 title: 'Savings (KB)', |
| 180 sessionValue: |
| 181 bytesToRoundedKilobytes_(sessionOriginal - sessionReceived), |
| 182 historicValue: |
| 183 bytesToRoundedKilobytes_(historicOriginal - historicReceived) |
| 184 }); |
| 185 rows.push({ |
| 186 title: 'Savings (%)', |
| 187 sessionValue: getPercentSavings_(sessionOriginal, sessionReceived), |
| 188 historicValue: getPercentSavings_(historicOriginal, |
| 189 historicReceived) |
| 190 }); |
| 191 |
| 192 var tbody = $(BandwidthView.SAVINGS_TBODY_ID); |
| 193 tbody.innerHTML = ''; |
| 194 |
| 195 // Fill in the bandwidth savings table. |
| 196 for (var i = 0; i < rows.length; ++i) { |
| 197 var r = rows[i]; |
| 198 var tr = addNode(tbody, 'tr'); |
| 199 |
| 200 addNodeWithText(tr, 'td', r.title); |
| 201 addNodeWithText(tr, 'td', r.sessionValue); |
| 202 addNodeWithText(tr, 'td', r.historicValue); |
| 203 } |
| 204 |
| 205 return true; |
| 206 }, |
| 207 |
| 208 /** |
| 209 * Renders a Data Reduction Proxy event into the event tbody |
| 210 */ |
| 211 buildEventRow_: function(event, actionCell, detailsCell) { |
| 212 if (event.type == EventType.DATA_REDUCTION_PROXY_ENABLED && |
| 213 event.params.enabled == 0) { |
| 214 addTextNode(actionCell, 'DISABLED'); |
| 215 } else { |
| 216 var actionText = |
| 217 EventTypeNames[event.type].replace('DATA_REDUCTION_PROXY_', ''); |
| 218 if (event.phase == EventPhase.PHASE_BEGIN || |
| 219 event.phase == EventPhase.PHASE_END) { |
| 220 actionText = actionText + ' (' + |
| 221 getKeyWithValue(EventPhase, event.phase) |
| 222 .replace('PHASE_', '') + ')'; |
| 223 } |
| 224 |
| 225 addTextNode(actionCell, actionText); |
| 226 this.createEventTable_(event.params, detailsCell); |
| 227 } |
| 228 }, |
| 229 |
| 230 /** |
| 231 * Updates the data reduction proxy summary block. |
| 232 */ |
| 233 updateDataReductionProxyConfig_: function() { |
| 234 $(BandwidthView.PROXY_CONFIG_ID).innerHTML = ''; |
| 235 $(BandwidthView.BYPASS_STATE_ID).innerHTML = ''; |
| 236 setNodeDisplay($(BandwidthView.BYPASS_STATE_CONTAINER_ID), false); |
| 237 |
| 238 if (this.data_reduction_proxy_config_) { |
| 239 var hasBypassedProxy = false; |
| 240 var now = timeutil.getCurrentTimeTicks(); |
| 241 |
| 242 if (this.last_bypass_ && |
| 243 this.hasTimePassedLogTime_(+this.last_bypass_.params.expiration)) { |
| 244 // Best effort on iterating the config to search for a bad proxy. |
| 245 // A server could exist in a string member of |
| 246 // data_reduction_proxy_config_ or within an array of servers in an |
| 247 // array member of data_reduction_proxy_config_. As such, search |
| 248 // through all string members and string arrays. |
| 249 for (var key in this.data_reduction_proxy_config_) { |
| 250 var value = this.data_reduction_proxy_config_[key]; |
| 251 if (typeof value == 'string') { |
| 252 if (this.isMarkedAsBad_(value)) { |
| 253 hasBypassedProxy = true; |
| 254 break; |
| 255 } |
| 256 } else if (value instanceof Array) { |
| 257 for (var index = 1; index < value.length; index++) { |
| 258 if (this.isMarkedAsBad_(value[index])) { |
| 259 hasBypassedProxy = true; |
| 260 } |
| 261 } |
| 262 |
| 263 if (hasBypassedProxy) { |
| 264 break; |
| 265 } |
| 266 } |
| 267 } |
| 268 } |
| 269 |
| 270 if (hasBypassedProxy) { |
| 271 this.createEventTable_(this.last_bypass_.params, |
| 272 $(BandwidthView.BYPASS_STATE_ID)); |
| 273 } |
| 274 |
| 275 this.createEventTable_(this.data_reduction_proxy_config_, |
| 276 $(BandwidthView.PROXY_CONFIG_ID)); |
| 277 setNodeDisplay($(BandwidthView.BYPASS_STATE_CONTAINER_ID), |
| 278 hasBypassedProxy); |
| 279 } |
| 280 }, |
| 281 |
| 282 /** |
| 283 * Checks to see if a proxy server is in marked as bad. |
| 284 */ |
| 285 isMarkedAsBad_: function(proxy) { |
| 286 for (var entry in this.bad_proxy_config_) { |
| 287 if (entry == proxy && |
| 288 this.hasTimePassedLogTime_(this.bad_proxy_config_[entry])) { |
| 289 return true; |
| 290 } |
| 291 } |
| 292 |
| 293 return false; |
| 294 }, |
| 295 |
| 296 /** |
| 297 * Checks to see if a given time in ticks has passed the time of the |
| 298 * the log. For real time viewing, this is "now", but for loaded logs, it |
| 299 * is the time at which the logs were taken. |
| 300 */ |
| 301 hasTimePassedLogTime_: function(timeTicks) { |
| 302 var logTime; |
| 303 if (MainView.isViewingLoadedLog() && ClientInfo.numericDate) { |
| 304 logTime = ClientInfo.numericDate; |
| 305 } else { |
| 306 logTime = timeutil.getCurrentTime(); |
| 307 } |
| 308 |
| 309 return timeutil.convertTimeTicksToTime(timeTicks) > logTime; |
| 310 }, |
| 311 |
| 312 /** |
| 313 * Creates a table of the object obj. Certain keys are special cased for |
| 314 * ease of readability. |
| 315 */ |
| 316 createEventTable_: function(obj, parentNode) { |
| 317 if (Object.keys(obj).length > 0) { |
| 318 var tableNode = addNode(parentNode, 'table'); |
| 319 tableNode.className = 'borderless-table'; |
| 320 for (var key in obj) { |
| 321 var value = obj[key]; |
| 322 if (value != null && value.toString() != '') { |
| 323 if (key == 'net_error') { |
| 324 if (value == 0) { |
| 325 value = 'OK'; |
| 326 } else { |
| 327 value = netErrorToString(value); |
| 328 } |
| 329 } else if (key == 'bypass_type') { |
| 330 value = getKeyWithValue(DataReductionProxyBypassEventType, value); |
| 331 } else if (key == 'bypass_action_type') { |
| 332 value = getKeyWithValue(DataReductionProxyBypassActionType, |
| 333 value); |
| 334 } else if (key == 'expiration') { |
| 335 value = timeutil.convertTimeTicksToDate(value); |
| 336 } |
| 337 var tableRow = addNode(tableNode, 'tr'); |
| 338 addNodeWithText(tableRow, 'td', key); |
| 339 addNodeWithText(tableRow, 'td', value); |
| 340 } |
| 341 } |
| 342 } |
| 343 } |
| 344 }; |
| 345 |
| 346 /** |
| 347 * Converts bytes to kilobytes rounded to one decimal place. |
| 348 */ |
| 349 function bytesToRoundedKilobytes_(val) { |
| 350 return (val / 1024).toFixed(1); |
| 351 } |
| 352 |
| 353 /** |
| 354 * Returns bandwidth savings as a percent rounded to one decimal place. |
| 355 */ |
| 356 function getPercentSavings_(original, received) { |
| 357 if (original > 0) { |
| 358 return ((original - received) * 100 / original).toFixed(1); |
| 359 } |
| 360 return '0.0'; |
| 361 } |
| 362 |
| 363 return BandwidthView; |
| 364 })(); |
OLD | NEW |