Chromium Code Reviews| Index: chrome/browser/resources/net_internals/bandwidth_view.js |
| diff --git a/chrome/browser/resources/net_internals/bandwidth_view.js b/chrome/browser/resources/net_internals/bandwidth_view.js |
| index 9f0e4e61cb95a1d8f67fee60365adb2352f5d267..399881e4ce435bcb4a94201cf168135d82239bba 100644 |
| --- a/chrome/browser/resources/net_internals/bandwidth_view.js |
| +++ b/chrome/browser/resources/net_internals/bandwidth_view.js |
| @@ -21,6 +21,15 @@ var BandwidthView = (function() { |
| g_browser.addSessionNetworkStatsObserver(this, true); |
| g_browser.addHistoricNetworkStatsObserver(this, true); |
| + // Register to receive data reduction proxy info. |
| + g_browser.addDataReductionProxyInfoObserver(this, true); |
| + |
| + // Register to receive proxy settings. |
| + g_browser.addProxySettingsObserver(this, true); |
| + |
| + // Register to receive bad proxy info. |
| + g_browser.addBadProxiesObserver(this, true); |
| + |
| this.sessionNetworkStats_ = null; |
| this.historicNetworkStats_ = null; |
| } |
| @@ -31,6 +40,16 @@ var BandwidthView = (function() { |
| // IDs for special HTML elements in bandwidth_view.html |
| BandwidthView.MAIN_BOX_ID = 'bandwidth-view-tab-content'; |
| + BandwidthView.ENABLED_ID = 'data-reduction-proxy-enabled'; |
| + BandwidthView.PRIMARY_PROXY_ID = 'data-reduction-proxy-primary'; |
| + BandwidthView.SECONDARY_PROXY_ID = 'data-reduction-proxy-secondary'; |
| + BandwidthView.CANARY_STATUS_ID = 'data-reduction-proxy-canary-status'; |
| + BandwidthView.BYPASS_STATE_ID = 'data-reduction-proxy-bypass-state'; |
| + BandwidthView.BYPASS_STATE_CONTAINER_ID = |
| + 'data-reduction-proxy-bypass-state-container'; |
| + BandwidthView.EVENTS_TBODY_ID = 'data-reduction-proxy-view-events-tbody'; |
| + BandwidthView.EVENTS_UL = 'data-reduction-proxy-view-events-list'; |
| + BandwidthView.STATS_BOX_ID = 'bandwidth-stats-table'; |
| cr.addSingletonGetter(BandwidthView); |
| @@ -38,6 +57,11 @@ var BandwidthView = (function() { |
| // Inherit the superclass's methods. |
| __proto__: superClass.prototype, |
| + data_reduction_proxy_config_: null, |
| + last_bypass_event_: null, |
| + proxy_config_: null, |
| + bad_proxy_config_: null, |
| + |
| onLoadLogFinish: function(data) { |
| // Even though this information is included in log dumps, there's no real |
| // reason to display it when debugging a loaded log file. |
| @@ -61,6 +85,98 @@ var BandwidthView = (function() { |
| return this.updateBandwidthUsageTable_(); |
| }, |
| + onDataReductionProxyInfoChanged: function(info) { |
| + $(BandwidthView.EVENTS_TBODY_ID).innerHTML = ''; |
| + |
| + if (!info) |
| + { |
|
bengr
2014/12/02 23:55:32
Move up a line.
jeremyim
2014/12/03 08:10:36
Done.
|
| + return false; |
| + } |
| + |
| + if (info.enabled == 'true') { |
| + $(BandwidthView.ENABLED_ID).innerText = 'Enabled'; |
| + if (info.canary != null) { |
| + $(BandwidthView.CANARY_STATUS_ID).innerText = info.canary; |
| + } |
| + if (info.last_bypass != null) { |
| + this.last_bypass_ = this.parseBypassEvent_(info.last_bypass); |
| + } |
| + this.data_reduction_proxy_config_ = info.proxy_config.params; |
| + } else { |
| + $(BandwidthView.ENABLED_ID).innerText = 'Disabled'; |
| + $(BandwidthView.CANARY_STATUS_ID).innerText = 'N/A'; |
| + this.data_reduction_proxy_config_ = null; |
| + } |
| + |
| + this.updateDataReductionProxyConfig_(); |
| + |
| + for (var eventIndex in info.events) { |
| + var event = info.events[eventIndex]; |
| + var headerRow = addNode($(BandwidthView.EVENTS_TBODY_ID), 'tr'); |
| + var detailsRow = addNode($(BandwidthView.EVENTS_TBODY_ID), 'tr'); |
| + |
| + var timeCell = addNode(headerRow, 'td'); |
| + var actionCell = addNode(headerRow, 'td'); |
| + var detailsCell = addNode(detailsRow, 'td'); |
| + detailsCell.colSpan = 2; |
| + detailsCell.className = 'data-reduction-proxy-view-events-details'; |
| + var eventTime = timeutil.convertTimeTicksToDate(event.time); |
| + timeutil.addNodeWithDate(timeCell, eventTime); |
| + |
| + switch (event.type) { |
| + case EventType.DATA_REDUCTION_PROXY_ENABLED: |
| + this.buildEnabledRow_(event, actionCell, detailsCell); |
| + break; |
| + case EventType.DATA_REDUCTION_PROXY_CANARY_REQUEST: |
| + this.buildCanaryRow_(event, actionCell, detailsCell); |
| + break; |
| + case EventType.DATA_REDUCTION_PROXY_CANARY_RESPONSE_RECEIVED: |
| + this.buildCanaryResponseRow_(event, actionCell, detailsCell); |
| + break; |
| + case EventType.DATA_REDUCTION_PROXY_BYPASS_REQUESTED: |
| + this.buildBypassRow_(event, actionCell, detailsCell); |
| + break; |
| + case EventType.DATA_REDUCTION_PROXY_FALLBACK: |
| + this.buildFallbackRow_(event, actionCell, detailsCell); |
| + break; |
| + } |
| + } |
| + }, |
| + |
| + onProxySettingsChanged: function(proxySettings) { |
| + var newProxySettings = []; |
| + var effectiveSettings = proxySettings.effective; |
| + if (effectiveSettings && effectiveSettings.proxy_per_scheme) { |
| + for (var scheme in effectiveSettings.proxy_per_scheme) { |
| + var schemeSettings = effectiveSettings.proxy_per_scheme[scheme]; |
| + if (scheme != 'fallback') { |
| + for (var i = 0; i < schemeSettings.length; ++i) { |
| + var proxyUri = schemeSettings[i]; |
| + if (proxyUri != 'direct://') { |
| + newProxySettings.push(proxyUri); |
| + } |
| + } |
| + } |
| + } |
| + } |
| + this.proxy_config_ = newProxySettings; |
| + this.updateDataReductionProxyConfig_(); |
| + }, |
| + |
| + onBadProxiesChanged: function(badProxies) { |
| + var newBadProxies = []; |
| + if (badProxies.length == 0) { |
| + this.last_bypass_ = null; |
| + } else { |
| + for (var i = 0; i < badProxies.length; ++i) { |
| + var entry = badProxies[i]; |
| + newBadProxies[entry.proxy_uri] = entry.bad_until; |
| + } |
| + } |
| + this.bad_proxy_config_ = newBadProxies; |
| + this.updateDataReductionProxyConfig_(); |
| + }, |
| + |
| /** |
| * Update the bandwidth usage table. Returns false on failure. |
| */ |
| @@ -103,8 +219,266 @@ var BandwidthView = (function() { |
| }); |
| var input = new JsEvalContext({rows: rows}); |
| - jstProcess(input, $(BandwidthView.MAIN_BOX_ID)); |
| + jstProcess(input, $(BandwidthView.STATS_BOX_ID)); |
| return true; |
| + }, |
| + |
| + buildEnabledRow_: function(event, actionCell, detailsCell) { |
| + if (event.params.enabled == 1) { |
| + addTextNode(actionCell, 'Proxy: Enabled'); |
| + var proxyWrapper = addNode(detailsCell, 'div'); |
| + addNodeWithText(proxyWrapper, 'div', 'Proxy configuration:'); |
| + |
| + if (event.params.primary_origin != null && |
| + event.params.primary_origin.trim() != '') { |
| + var proxyText = 'Primary: ' + event.params.primary_origin; |
| + if (event.params.primary_restricted != null && |
| + event.params.primary_restricted) { |
| + proxyText += ' (restricted)'; |
| + } |
| + addNodeWithText(proxyWrapper, 'div', proxyText); |
| + } |
| + |
| + if (event.params.fallback_origin != null && |
| + event.params.fallback_origin.trim() != '') { |
| + var proxyText = 'Fallback: ' + event.params.fallback_origin; |
| + if (event.params.fallback_restricted != null && |
| + event.params.fallback_restricted) { |
| + proxyText += ' (restricted)'; |
| + } |
| + addNodeWithText(proxyWrapper, 'div', proxyText); |
| + } |
| + |
| + if (event.params.ssl_origin != null && |
| + event.params.ssl_origin.trim() != '') { |
| + addNodeWithText(proxyWrapper, 'div', |
| + 'SSL: ' + event.params.ssl_origin); |
| + } |
| + } else { |
| + addTextNode(actionCell, 'Proxy: Disabled'); |
| + } |
| + }, |
| + |
| + buildCanaryRow_: function(event, actionCell, detailsCell) { |
| + if (event.phase == EventPhase.PHASE_BEGIN) { |
| + addTextNode(actionCell, 'Canary request sent'); |
| + addTextNode(detailsCell, 'URL: ' + event.params.url); |
| + } else if (event.phase == EventPhase.PHASE_END) { |
| + addTextNode(actionCell, 'Canary request completed'); |
| + if (event.params.net_error == 0) { |
| + addTextNode(detailsCell, 'Result: OK'); |
| + } else { |
| + addTextNode(detailsCell, |
| + 'Result: ' + netErrorToString(event.params.net_error)); |
| + } |
| + } |
| + }, |
| + |
| + buildCanaryResponseRow_: function(event, actionCell, detailsCell) { |
| + addTextNode(actionCell, 'Canary response received'); |
| + }, |
| + |
| + buildBypassRow_: function(event, actionCell, detailsCell) { |
| + var parsedBypass = this.parseBypassEvent_(event); |
| + |
| + addTextNode(actionCell, |
| + 'Bypass received (' + parsedBypass.bypass_reason + ')'); |
| + var bypassWrapper = addNode(detailsCell, 'div'); |
| + addNodeWithText(bypassWrapper, 'div', 'URL: ' + parsedBypass.origin_url); |
| + addNodeWithText( |
| + bypassWrapper, 'div', |
| + 'Bypassed for ' + parsedBypass.bypass_duration_seconds + ' seconds.'); |
| + }, |
| + |
| + buildFallbackRow_: function(event, actionCell, detailsCell) { |
| + addTextNode(actionCell, 'Proxy fallback'); |
| + }, |
| + |
| + 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
|
| + var reason; |
| + if (event.params.action != null) { |
| + reason = event.params.action; |
| + } else { |
| + switch (event.params.bypass_type) { |
| + case 0: |
| + reason = 'Bypass current request'; |
| + break; |
| + case 1: |
| + reason = 'Bypass for short period'; |
| + break; |
| + case 2: |
| + reason = 'Bypass for medium period'; |
| + break; |
| + case 3: |
| + reason = 'Bypass for long period'; |
| + break; |
| + case 4: |
| + reason = 'Missing Via Header 4xx'; |
| + break; |
| + case 5: |
| + reason = 'Missing Via Header non-4xx'; |
| + break; |
| + case 6: |
| + reason = '407'; |
| + break; |
| + case 7: |
| + reason = '500'; |
| + break; |
| + case 8: |
| + reason = '502'; |
| + break; |
| + case 9: |
| + reason = '503'; |
| + break; |
| + case 10: |
| + reason = 'Network error'; |
| + break; |
| + default: |
| + reason = 'Unknown error'; |
| + break; |
| + } |
| + } |
| + |
| + var parsedBypass = |
| + { |
|
bengr
2014/12/02 23:55:32
Move up a line.
jeremyim
2014/12/03 08:10:37
Done.
|
| + bypass_reason: reason, |
| + origin_url: event.params.url, |
| + bypass_duration_seconds: event.params.bypass_duration_seconds, |
| + bypass_expiration: event.params.expiration, |
| + }; |
| + |
| + return parsedBypass; |
| + }, |
| + |
| + updateDataReductionProxyConfig_: function() { |
| + $(BandwidthView.PRIMARY_PROXY_ID).innerHTML = ''; |
| + $(BandwidthView.SECONDARY_PROXY_ID).innerHTML = ''; |
| + setNodeDisplay($(BandwidthView.BYPASS_STATE_CONTAINER_ID), false); |
| + |
| + if (this.data_reduction_proxy_config_) { |
| + var primaryProxy = ''; |
| + var secondaryProxy = ''; |
| + var now = timeutil.getCurrentTimeTicks(); |
| + |
| + if (this.last_bypass_ && +this.last_bypass_.bypass_expiration > now) { |
| + var input = new JsEvalContext(this.last_bypass_); |
| + jstProcess(input, $(BandwidthView.BYPASS_STATE_CONTAINER_ID)); |
| + } else { |
| + var input = new JsEvalContext(); |
| + jstProcess(input, $(BandwidthView.BYPASS_STATE_CONTAINER_ID)); |
| + } |
| + |
| + if (this.data_reduction_proxy_config_.ssl_origin) { |
| + primaryProxy = 'HTTPS Tunnel: ' + this.buildProxyString_( |
| + this.data_reduction_proxy_config_.ssl_origin, false); |
| + } |
| + |
| + if (this.data_reduction_proxy_config_.primary_origin) { |
| + var proxyString = this.buildProxyString_( |
| + this.data_reduction_proxy_config_.primary_origin, |
| + this.data_reduction_proxy_config_.primary_restricted); |
| + |
| + if (primaryProxy == '') { |
| + primaryProxy = proxyString; |
| + } else { |
| + secondaryProxy = proxyString; |
| + } |
| + } |
| + |
| + if (this.data_reduction_proxy_config_.fallback_origin) { |
| + var proxyString = this.buildProxyString_( |
| + this.data_reduction_proxy_config_.fallback_origin, |
| + this.data_reduction_proxy_config_.fallback_restricted); |
| + |
| + if (primaryProxy == '') { |
| + primaryProxy = proxyString; |
| + } else if (secondaryProxy == '') { |
| + secondaryProxy = proxyString; |
| + } |
| + } |
| + |
| + $(BandwidthView.PRIMARY_PROXY_ID).innerText = primaryProxy; |
| + $(BandwidthView.SECONDARY_PROXY_ID).innerText = secondaryProxy; |
| + } |
| + }, |
| + |
| + buildProxyString_: function(proxy, restricted) { |
| + var normalizedProxy = this.normalize_(proxy); |
| + var configured = this.isConfigured_(normalizedProxy); |
| + var bypassed = this.isBypassed_(normalizedProxy); |
| + var proxyString = ''; |
| + if (restricted) { |
| + proxyString += proxy + ' (RESTRICTED)'; |
| + } |
| + else if (configured) { |
| + proxyString += proxy; |
| + if (bypassed) { |
| + proxyString += ' (BYPASSED)'; |
| + setNodeDisplay($(BandwidthView.BYPASS_STATE_CONTAINER_ID), true); |
| + } else { |
| + proxyString += ' (ACTIVE)'; |
| + } |
| + } |
| + |
| + return proxyString; |
| + }, |
| + |
| + normalize_: function(proxy) { |
| + function startsWith(str, prefix) { |
| + return str.lastIndexOf(prefix, 0) == 0; |
| + } |
| + |
| + function strContains(str, substr, startIndex) { |
| + return str.indexOf(substr, startIndex) != -1; |
| + } |
| + |
| + function endsWith(str, suffix) { |
| + return str.indexOf(suffix, str.length - suffix.length) !== -1; |
| + } |
| + |
| + function stripSuffix(str, suffix) { |
| + if (!endsWith(str, suffix)) |
| + return str; |
| + return str.substring(str, str.length - suffix.length); |
| + } |
| + |
| + var normalized = stripSuffix(proxy, '/'); |
| + |
| + if (startsWith(normalized, 'http://')) { |
| + normalized = normalized.substr(7); |
| + } |
| + |
| + if (startsWith(normalized, 'https://')) { |
| + if (!strContains(normalized, ':', 7)) { |
| + normalized += ':443'; |
| + } |
| + } else if (!strContains(normalized, ':', 0)) { |
| + normalized += ':80'; |
| + } |
| + |
| + return normalized; |
| + }, |
| + |
| + isConfigured_: function(proxy) { |
| + for (var index in this.proxy_config_) { |
| + var entry = this.proxy_config_[index]; |
| + if (entry == proxy) { |
| + return true; |
| + } |
| + } |
| + |
| + return false; |
| + }, |
| + |
| + isBypassed_: function(proxy) { |
| + var now = timeutil.getCurrentTimeTicks(); |
| + for (var entry in this.bad_proxy_config_) { |
| + if (entry == proxy && this.bad_proxy_config_[entry] > now) { |
| + return true; |
| + } |
| + } |
| + |
| + return false; |
| } |
| }; |