// 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; })();