Index: netlog_viewer/proxy_view.js |
diff --git a/netlog_viewer/proxy_view.js b/netlog_viewer/proxy_view.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..10534137408b393a27e1040eb996a1ebd98c41cd |
--- /dev/null |
+++ b/netlog_viewer/proxy_view.js |
@@ -0,0 +1,187 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+/** |
+ * This view displays information on the proxy setup: |
+ * |
+ * - Shows the current proxy settings. |
+ * - Has a button to reload these settings. |
+ * - Shows the list of proxy hostnames that are cached as "bad". |
+ * - Has a button to clear the cached bad proxies. |
+ */ |
+var ProxyView = (function() { |
+ 'use strict'; |
+ |
+ // We inherit from DivView. |
+ var superClass = DivView; |
+ |
+ /** |
+ * @constructor |
+ */ |
+ function ProxyView() { |
+ assertFirstConstructorCall(ProxyView); |
+ |
+ // Call superclass's constructor. |
+ superClass.call(this, ProxyView.MAIN_BOX_ID); |
+ |
+ // Hook up the UI components. |
+ $(ProxyView.RELOAD_SETTINGS_BUTTON_ID).onclick = |
+ g_browser.sendReloadProxySettings.bind(g_browser); |
+ $(ProxyView.CLEAR_BAD_PROXIES_BUTTON_ID).onclick = |
+ g_browser.sendClearBadProxies.bind(g_browser); |
+ |
+ // Register to receive proxy information as it changes. |
+ g_browser.addProxySettingsObserver(this, true); |
+ g_browser.addBadProxiesObserver(this, true); |
+ } |
+ |
+ ProxyView.TAB_ID = 'tab-handle-proxy'; |
+ ProxyView.TAB_NAME = 'Proxy'; |
+ ProxyView.TAB_HASH = '#proxy'; |
+ |
+ // IDs for special HTML elements in proxy_view.html |
+ ProxyView.MAIN_BOX_ID = 'proxy-view-tab-content'; |
+ ProxyView.ORIGINAL_SETTINGS_DIV_ID = 'proxy-view-original-settings'; |
+ ProxyView.EFFECTIVE_SETTINGS_DIV_ID = 'proxy-view-effective-settings'; |
+ ProxyView.ORIGINAL_CONTENT_DIV_ID = 'proxy-view-original-content'; |
+ ProxyView.EFFECTIVE_CONTENT_DIV_ID = 'proxy-view-effective-content'; |
+ ProxyView.RELOAD_SETTINGS_BUTTON_ID = 'proxy-view-reload-settings'; |
+ ProxyView.BAD_PROXIES_DIV_ID = 'proxy-view-bad-proxies-div'; |
+ ProxyView.BAD_PROXIES_TBODY_ID = 'proxy-view-bad-proxies-tbody'; |
+ ProxyView.CLEAR_BAD_PROXIES_BUTTON_ID = 'proxy-view-clear-bad-proxies'; |
+ ProxyView.SOCKS_HINTS_DIV_ID = 'proxy-view-socks-hints'; |
+ ProxyView.SOCKS_HINTS_FLAG_DIV_ID = 'proxy-view-socks-hints-flag'; |
+ |
+ cr.addSingletonGetter(ProxyView); |
+ |
+ ProxyView.prototype = { |
+ // Inherit the superclass's methods. |
+ __proto__: superClass.prototype, |
+ |
+ onLoadLogFinish: function(data) { |
+ return this.onProxySettingsChanged(data.proxySettings) && |
+ this.onBadProxiesChanged(data.badProxies); |
+ }, |
+ |
+ onProxySettingsChanged: function(proxySettings) { |
+ $(ProxyView.ORIGINAL_SETTINGS_DIV_ID).innerHTML = ''; |
+ $(ProxyView.EFFECTIVE_SETTINGS_DIV_ID).innerHTML = ''; |
+ this.updateSocksHints_(null); |
+ |
+ if (!proxySettings) |
+ return false; |
+ |
+ // Both |original| and |effective| are dictionaries describing the |
+ // settings. |
+ var original = proxySettings.original; |
+ var effective = proxySettings.effective; |
+ |
+ var originalStr = proxySettingsToString(original); |
+ var effectiveStr = proxySettingsToString(effective); |
+ |
+ setNodeDisplay($(ProxyView.ORIGINAL_CONTENT_DIV_ID), |
+ originalStr != effectiveStr); |
+ |
+ $(ProxyView.ORIGINAL_SETTINGS_DIV_ID).innerText = originalStr; |
+ $(ProxyView.EFFECTIVE_SETTINGS_DIV_ID).innerText = effectiveStr; |
+ |
+ this.updateSocksHints_(effective); |
+ |
+ return true; |
+ }, |
+ |
+ onBadProxiesChanged: function(badProxies) { |
+ $(ProxyView.BAD_PROXIES_TBODY_ID).innerHTML = ''; |
+ setNodeDisplay($(ProxyView.BAD_PROXIES_DIV_ID), |
+ badProxies && badProxies.length > 0); |
+ |
+ if (!badProxies) |
+ return false; |
+ |
+ // Add a table row for each bad proxy entry. |
+ for (var i = 0; i < badProxies.length; ++i) { |
+ var entry = badProxies[i]; |
+ var badUntilDate = timeutil.convertTimeTicksToDate(entry.bad_until); |
+ |
+ var tr = addNode($(ProxyView.BAD_PROXIES_TBODY_ID), 'tr'); |
+ |
+ var nameCell = addNode(tr, 'td'); |
+ var badUntilCell = addNode(tr, 'td'); |
+ |
+ addTextNode(nameCell, entry.proxy_uri); |
+ timeutil.addNodeWithDate(badUntilCell, badUntilDate); |
+ } |
+ return true; |
+ }, |
+ |
+ updateSocksHints_: function(proxySettings) { |
+ setNodeDisplay($(ProxyView.SOCKS_HINTS_DIV_ID), false); |
+ |
+ if (!proxySettings) |
+ return; |
+ |
+ var socksProxy = getSingleSocks5Proxy_(proxySettings.single_proxy); |
+ if (!socksProxy) |
+ return; |
+ |
+ // Suggest a recommended --host-resolver-rules. |
+ // NOTE: This does not compensate for any proxy bypass rules. If the |
+ // proxy settings include proxy bypasses the user may need to expand the |
+ // exclusions for host resolving. |
+ var hostResolverRules = 'MAP * ~NOTFOUND , EXCLUDE ' + socksProxy.host; |
+ var hostResolverRulesFlag = '--host-resolver-rules="' + |
+ hostResolverRules + '"'; |
+ |
+ // TODO(eroman): On Linux the ClientInfo.command_line is wrong in that it |
+ // doesn't include any quotes around the parameters. This means the |
+ // string search above is going to fail :( |
+ if (ClientInfo.command_line && |
+ ClientInfo.command_line.indexOf(hostResolverRulesFlag) != -1) { |
+ // Chrome is already using the suggested resolver rules. |
+ return; |
+ } |
+ |
+ $(ProxyView.SOCKS_HINTS_FLAG_DIV_ID).innerText = hostResolverRulesFlag; |
+ setNodeDisplay($(ProxyView.SOCKS_HINTS_DIV_ID), true); |
+ } |
+ }; |
+ |
+ function getSingleSocks5Proxy_(proxyList) { |
+ var proxyString; |
+ if (typeof proxyList == 'string') { |
+ // Older versions of Chrome passed single_proxy as a string. |
+ // TODO(eroman): This behavior changed in M27. Support for older logs can |
+ // safely be removed circa M29. |
+ proxyString = proxyList; |
+ } else if (Array.isArray(proxyList) && proxyList.length == 1) { |
+ proxyString = proxyList[0]; |
+ } else { |
+ return null; |
+ } |
+ |
+ var pattern = /^socks5:\/\/(.*)$/; |
+ var matches = pattern.exec(proxyString); |
+ |
+ if (!matches) |
+ return null; |
+ |
+ var hostPortString = matches[1]; |
+ |
+ matches = /^(.*):(\d+)$/.exec(hostPortString); |
+ if (!matches) |
+ return null; |
+ |
+ var result = {host: matches[1], port: matches[2]}; |
+ |
+ // Strip brackets off of IPv6 literals. |
+ matches = /^\[(.*)\]$/.exec(result.host); |
+ if (matches) |
+ result.host = matches[1]; |
+ |
+ return result; |
+ } |
+ |
+ return ProxyView; |
+})(); |
+ |