summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-05 19:28:36 +0000
committereroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-05 19:28:36 +0000
commita0360d8b084eb8908b5bc57e409304aa96947bd4 (patch)
treeddfbcfe03a7d2ed1722e6da00809155dc12a9b96
parent678223eaf6708d2d3839d488c99729c80ddb8f6f (diff)
downloadchromium_src-a0360d8b084eb8908b5bc57e409304aa96947bd4.zip
chromium_src-a0360d8b084eb8908b5bc57e409304aa96947bd4.tar.gz
chromium_src-a0360d8b084eb8908b5bc57e409304aa96947bd4.tar.bz2
Add the proxy information to the new net internals page.
BUG=37421 Review URL: http://codereview.chromium.org/1607004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@43636 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/dom_ui/net_internals_ui.cc159
-rw-r--r--chrome/browser/resources/net_internals/index.html22
-rw-r--r--chrome/browser/resources/net_internals/main.css12
-rw-r--r--chrome/browser/resources/net_internals/main.js190
-rw-r--r--chrome/browser/resources/net_internals/proxyview.js62
-rw-r--r--chrome/browser/resources/net_internals/requestsview.js2
-rwxr-xr-xchrome/chrome_browser.gypi1
7 files changed, 404 insertions, 44 deletions
diff --git a/chrome/browser/dom_ui/net_internals_ui.cc b/chrome/browser/dom_ui/net_internals_ui.cc
index c04b30a..d33b17f 100644
--- a/chrome/browser/dom_ui/net_internals_ui.cc
+++ b/chrome/browser/dom_ui/net_internals_ui.cc
@@ -4,6 +4,8 @@
#include "chrome/browser/dom_ui/net_internals_ui.h"
+#include <sstream>
+
#include "app/resource_bundle.h"
#include "base/file_util.h"
#include "base/path_service.h"
@@ -12,15 +14,25 @@
#include "base/string_util.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
#include "chrome/browser/io_thread.h"
#include "chrome/browser/net/chrome_net_log.h"
+#include "chrome/browser/net/url_request_context_getter.h"
+#include "chrome/browser/profile.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/url_constants.h"
+#include "net/base/escape.h"
+#include "net/proxy/proxy_service.h"
+#include "net/url_request/url_request_context.h"
namespace {
+// Formats |t| as a decimal number, in milliseconds.
+std::string TickCountToString(const base::TimeTicks& t) {
+ return Int64ToString((t - base::TimeTicks()).InMilliseconds());
+}
+
// TODO(eroman): Bootstrap the net-internals page using the passively logged
// data.
@@ -93,7 +105,8 @@ class NetInternalsMessageHandler::IOThreadImpl
// we need to grab it from the UI thread).
IOThreadImpl(
const base::WeakPtr<NetInternalsMessageHandler>& handler,
- IOThread* io_thread);
+ IOThread* io_thread,
+ URLRequestContextGetter* context_getter);
~IOThreadImpl();
@@ -115,6 +128,11 @@ class NetInternalsMessageHandler::IOThreadImpl
// it indicates that the renderer is ready to start receiving captured data.
void OnRendererReady(const Value* value);
+ void OnGetProxySettings(const Value* value);
+ void OnReloadProxySettings(const Value* value);
+ void OnGetBadProxies(const Value* value);
+ void OnClearBadProxies(const Value* value);
+
// ChromeNetLog::Observer implementation:
virtual void OnAddEntry(const net::NetLog::Entry& entry);
@@ -129,7 +147,6 @@ class NetInternalsMessageHandler::IOThreadImpl
void CallJavascriptFunction(const std::wstring& function_name,
Value* arg);
- private:
// Pointer to the UI-thread message handler. Only access this from
// the UI thread.
base::WeakPtr<NetInternalsMessageHandler> handler_;
@@ -137,6 +154,8 @@ class NetInternalsMessageHandler::IOThreadImpl
// The global IOThread, which contains the global NetLog to observer.
IOThread* io_thread_;
+ scoped_refptr<URLRequestContextGetter> context_getter_;
+
// True if we have attached an observer to the NetLog already.
bool is_observing_log_;
friend class base::RefCountedThreadSafe<IOThreadImpl>;
@@ -192,7 +211,15 @@ void NetInternalsHTMLSource::StartDataRequest(const std::string& path,
std::string data_string;
FilePath file_path;
PathService::Get(chrome::DIR_NET_INTERNALS, &file_path);
- std::string filename = path.empty() ? "index.html" : path;
+ std::string filename;
+
+ // The provided "path" may contain a fragment, or query section. We only
+ // care about the path itself, and will disregard anything else.
+ filename = GURL(std::string("chrome://net/") + path).path().substr(1);
+
+ if (filename.empty())
+ filename = "index.html";
+
file_path = file_path.AppendASCII(filename);
if (!file_util::ReadFileToString(file_path, &data_string)) {
@@ -233,7 +260,8 @@ NetInternalsMessageHandler::~NetInternalsMessageHandler() {
DOMMessageHandler* NetInternalsMessageHandler::Attach(DOMUI* dom_ui) {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
- proxy_ = new IOThreadImpl(this->AsWeakPtr(), g_browser_process->io_thread());
+ proxy_ = new IOThreadImpl(this->AsWeakPtr(), g_browser_process->io_thread(),
+ dom_ui->GetProfile()->GetRequestContext());
DOMMessageHandler* result = DOMMessageHandler::Attach(dom_ui);
return result;
}
@@ -243,6 +271,14 @@ void NetInternalsMessageHandler::RegisterMessages() {
dom_ui_->RegisterMessageCallback("notifyReady",
proxy_->CreateCallback(&IOThreadImpl::OnRendererReady));
+ dom_ui_->RegisterMessageCallback("getProxySettings",
+ proxy_->CreateCallback(&IOThreadImpl::OnGetProxySettings));
+ dom_ui_->RegisterMessageCallback("reloadProxySettings",
+ proxy_->CreateCallback(&IOThreadImpl::OnReloadProxySettings));
+ dom_ui_->RegisterMessageCallback("getBadProxies",
+ proxy_->CreateCallback(&IOThreadImpl::OnGetBadProxies));
+ dom_ui_->RegisterMessageCallback("clearBadProxies",
+ proxy_->CreateCallback(&IOThreadImpl::OnClearBadProxies));
}
void NetInternalsMessageHandler::CallJavascriptFunction(
@@ -260,9 +296,11 @@ void NetInternalsMessageHandler::CallJavascriptFunction(
NetInternalsMessageHandler::IOThreadImpl::IOThreadImpl(
const base::WeakPtr<NetInternalsMessageHandler>& handler,
- IOThread* io_thread)
+ IOThread* io_thread,
+ URLRequestContextGetter* context_getter)
: handler_(handler),
io_thread_(io_thread),
+ context_getter_(context_getter),
is_observing_log_(false) {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
}
@@ -308,7 +346,7 @@ void NetInternalsMessageHandler::IOThreadImpl::OnRendererReady(
static_cast<int>(event_types[i]));
}
- CallJavascriptFunction(L"setLogEventTypeConstants", dict);
+ CallJavascriptFunction(L"g_browser.receivedLogEventTypeConstants", dict);
}
// Tell the javascript about the relationship between event phase enums and
@@ -320,7 +358,7 @@ void NetInternalsMessageHandler::IOThreadImpl::OnRendererReady(
dict->SetInteger(L"PHASE_END", net::NetLog::PHASE_END);
dict->SetInteger(L"PHASE_NONE", net::NetLog::PHASE_NONE);
- CallJavascriptFunction(L"setLogEventPhaseConstants", dict);
+ CallJavascriptFunction(L"g_browser.receivedLogEventPhaseConstants", dict);
}
// Tell the javascript about the relationship between source type enums and
@@ -336,7 +374,7 @@ void NetInternalsMessageHandler::IOThreadImpl::OnRendererReady(
net::NetLog::SOURCE_INIT_PROXY_RESOLVER);
dict->SetInteger(L"CONNECT_JOB", net::NetLog::SOURCE_CONNECT_JOB);
- CallJavascriptFunction(L"setLogSourceTypeConstants", dict);
+ CallJavascriptFunction(L"g_browser.receivedLogSourceTypeConstants", dict);
}
// Tell the javascript about the relationship between entry type enums and
@@ -348,8 +386,99 @@ void NetInternalsMessageHandler::IOThreadImpl::OnRendererReady(
dict->SetInteger(L"TYPE_STRING", net::NetLog::Entry::TYPE_STRING);
dict->SetInteger(L"TYPE_ERROR_CODE", net::NetLog::Entry::TYPE_ERROR_CODE);
- CallJavascriptFunction(L"setLogEntryTypeConstants", dict);
+ CallJavascriptFunction(L"g_browser.receivedLogEntryTypeConstants", dict);
+ }
+
+ // Tell the javascript how the "time ticks" values we have given it relate to
+ // actual system times. (We used time ticks throughout since they are stable
+ // across system clock changes).
+ {
+ int64 cur_time_ms = (base::Time::Now() - base::Time()).InMilliseconds();
+
+ int64 cur_time_ticks_ms =
+ (base::TimeTicks::Now() - base::TimeTicks()).InMilliseconds();
+
+ // If we add this number to a time tick value, it gives the timestamp.
+ int64 tick_to_time_ms = cur_time_ms - cur_time_ticks_ms;
+
+ // Chrome on all platforms stores times using the Windows epoch
+ // (Jan 1 1601), but the javascript wants a unix epoch.
+ // TODO(eroman): Getting the timestamp relative the to unix epoch should
+ // be part of the time library.
+ const int64 kUnixEpochMs = 11644473600000LL;
+ int64 tick_to_unix_time_ms = tick_to_time_ms - kUnixEpochMs;
+
+ // Pass it as a string, since it may be too large to fit in an integer.
+ CallJavascriptFunction(L"g_browser.receivedTimeTickOffset",
+ Value::CreateStringValue(
+ Int64ToString(tick_to_unix_time_ms)));
+ }
+
+ // Notify the client of the basic proxy data.
+ OnGetProxySettings(NULL);
+ OnGetBadProxies(NULL);
+}
+
+void NetInternalsMessageHandler::IOThreadImpl::OnGetProxySettings(
+ const Value* value) {
+ URLRequestContext* context = context_getter_->GetURLRequestContext();
+ net::ProxyService* proxy_service = context->proxy_service();
+
+ // TODO(eroman): send a dictionary rather than a flat string, so client can do
+ // its own presentation.
+ std::string settings_string;
+
+ if (proxy_service->config_has_been_initialized()) {
+ // net::ProxyConfig defines an operator<<.
+ std::ostringstream stream;
+ stream << proxy_service->config();
+ settings_string = stream.str();
+ }
+
+ CallJavascriptFunction(L"g_browser.receivedProxySettings",
+ Value::CreateStringValue(settings_string));
+}
+
+void NetInternalsMessageHandler::IOThreadImpl::OnReloadProxySettings(
+ const Value* value) {
+ URLRequestContext* context = context_getter_->GetURLRequestContext();
+ context->proxy_service()->ForceReloadProxyConfig();
+
+ // Cause the renderer to be notified of the new values.
+ OnGetProxySettings(NULL);
+}
+
+void NetInternalsMessageHandler::IOThreadImpl::OnGetBadProxies(
+ const Value* value) {
+ URLRequestContext* context = context_getter_->GetURLRequestContext();
+
+ const net::ProxyRetryInfoMap& bad_proxies_map =
+ context->proxy_service()->proxy_retry_info();
+
+ ListValue* list = new ListValue();
+
+ for (net::ProxyRetryInfoMap::const_iterator it = bad_proxies_map.begin();
+ it != bad_proxies_map.end(); ++it) {
+ const std::string& proxy_uri = it->first;
+ const net::ProxyRetryInfo& retry_info = it->second;
+
+ DictionaryValue* dict = new DictionaryValue();
+ dict->SetString(L"proxy_uri", proxy_uri);
+ dict->SetString(L"bad_until", TickCountToString(retry_info.bad_until));
+
+ list->Append(dict);
}
+
+ CallJavascriptFunction(L"g_browser.receivedBadProxies", list);
+}
+
+void NetInternalsMessageHandler::IOThreadImpl::OnClearBadProxies(
+ const Value* value) {
+ URLRequestContext* context = context_getter_->GetURLRequestContext();
+ context->proxy_service()->ClearBadProxiesCache();
+
+ // Cause the renderer to be notified of the new values.
+ OnGetBadProxies(NULL);
}
void NetInternalsMessageHandler::IOThreadImpl::OnAddEntry(
@@ -368,10 +497,9 @@ void NetInternalsMessageHandler::IOThreadImpl::OnAddEntry(
entry_dict->SetInteger(L"type", static_cast<int>(entry_type));
}
- // Set the entry time.
- entry_dict->SetInteger(
- L"time",
- static_cast<int>((entry.time - base::TimeTicks()).InMilliseconds()));
+ // Set the entry time. (Note that we send it as a string since integers
+ // might overflow).
+ entry_dict->SetString(L"time", TickCountToString(entry.time));
// Set the entry source.
DictionaryValue* source_dict = new DictionaryValue();
@@ -402,7 +530,7 @@ void NetInternalsMessageHandler::IOThreadImpl::OnAddEntry(
entry_dict->SetInteger(L"error_code", entry.error_code);
}
- CallJavascriptFunction(L"onLogEntryAdded", entry_dict);
+ CallJavascriptFunction(L"g_browser.receivedLogEntry", entry_dict);
}
void NetInternalsMessageHandler::IOThreadImpl::DispatchToMessageHandler(
@@ -439,7 +567,6 @@ void NetInternalsMessageHandler::IOThreadImpl::CallJavascriptFunction(
// Failed posting the task, avoid leaking.
delete arg;
}
-
}
} // namespace
diff --git a/chrome/browser/resources/net_internals/index.html b/chrome/browser/resources/net_internals/index.html
index fb7ff9a..f6df28d 100644
--- a/chrome/browser/resources/net_internals/index.html
+++ b/chrome/browser/resources/net_internals/index.html
@@ -18,6 +18,7 @@ found in the LICENSE file.
<script src="timelineviewpainter.js"></script>
<script src="logviewpainter.js"></script>
<script src="loggrouper.js"></script>
+ <script src="proxyview.js"></script>
</head>
<body onload="onLoaded()">
<!-- Tab switcher for main categories. -->
@@ -31,8 +32,27 @@ found in the LICENSE file.
</ul>
<div style="clear: both;"></div>
</div>
+ <!-- Proxy info -->
+ <div id=proxyTabContent>
+ <h4>
+ Current proxy settings
+ <input type=button value="Reload settings" id=proxyReloadSettings />
+ </h4>
+ <pre id=proxyCurrentConfig></pre>
+
+ <h4>
+ Proxies which have failed recently, and are marked as bad
+ <input type=button value="Clear bad proxies" id=clearBadProxies />
+ </h4>
+ <table border=1>
+ <thead>
+ <th>Bad proxy server</th>
+ <th>Time for next retry</th>
+ </thead>
+ <tbody id=badProxiesTableBody></tbody>
+ </table>
+ </div>
<!-- Sections TODO -->
- <div id=proxyTabContent>TODO: display proxy information (PAC error log, initialization log, current settings.)</div>
<div id=dnsTabContent>TODO: display dns information (outstanding jobs, host cache).</div>
<div id=socketsTabContent>TODO: display socket information (outstanding connect jobs)</div>
<div id=httpCacheTabContent>TODO: display http cache information (disk cache navigator)</div>
diff --git a/chrome/browser/resources/net_internals/main.css b/chrome/browser/resources/net_internals/main.css
index cc87520..76c608d 100644
--- a/chrome/browser/resources/net_internals/main.css
+++ b/chrome/browser/resources/net_internals/main.css
@@ -180,6 +180,16 @@ body {
}
#detailsLogBox,
-#detailsTimelineBox {
+#detailsTimelineBox,
+#proxyTabContent {
overflow: auto;
}
+
+#proxyTabContent {
+ padding-left: 20px;
+}
+
+#proxyTabContent td,
+#proxyTabContent th {
+ font-size: 12px;
+}
diff --git a/chrome/browser/resources/net_internals/main.js b/chrome/browser/resources/net_internals/main.js
index 7b9d3c9..c9bf433 100644
--- a/chrome/browser/resources/net_internals/main.js
+++ b/chrome/browser/resources/net_internals/main.js
@@ -11,9 +11,17 @@ var LogEventPhase = null;
var LogSourceType = null;
/**
+ * Object to communicate between the renderer and the browser.
+ * @type {!BrowserBridge}
+ */
+var g_browser = null;
+
+/**
* Main entry point. called once the page has loaded.
*/
function onLoaded() {
+ g_browser = new BrowserBridge();
+
// Create the view which displays requests lists, and lets you select, filter
// and delete them.
var requestsView = new RequestsView('requestsListTableBody',
@@ -35,13 +43,20 @@ function onLoaded() {
"actionBox",
"splitterBox");
+ // Create a view which will display info on the proxy setup.
+ var proxyView = new ProxyView("proxyTabContent",
+ "proxyCurrentConfig",
+ "proxyReloadSettings",
+ "badProxiesTableBody",
+ "clearBadProxies");
+
// Create a view which lets you tab between the different sub-views.
var categoryTabSwitcher =
new TabSwitcherView(new DivView('categoryTabHandles'));
// Populate the main tabs.
categoryTabSwitcher.addTab('requestsTab', requestsView);
- categoryTabSwitcher.addTab('proxyTab', new DivView('proxyTabContent'));
+ categoryTabSwitcher.addTab('proxyTab', proxyView);
categoryTabSwitcher.addTab('dnsTab', new DivView('dnsTabContent'));
categoryTabSwitcher.addTab('socketsTab', new DivView('socketsTabContent'));
categoryTabSwitcher.addTab('httpCacheTab',
@@ -57,55 +72,180 @@ function onLoaded() {
windowView.resetGeometry();
// Tell the browser that we are ready to start receiving log events.
- notifyApplicationReady();
+ g_browser.sendReady();
}
+/**
+ * This class provides a "bridge" for communicating between the javascript and
+ * the browser.
+ *
+ * @constructor
+ */
+function BrowserBridge() {
+ // List of observers for various bits of browser state.
+ this.logObservers_ = [];
+ this.proxySettingsObservers_ = [];
+ this.badProxiesObservers_ = [];
+
+ // Map from observer method name (i.e. 'onProxySettingsChanged', 'onBadProxiesChanged')
+ // to the previously received data for that type. Used to tell if the data has
+ // actually changed since we last polled it.
+ this.prevPollData_ = {};
+}
+
+/**
+ * Delay in milliseconds between polling of certain browser information.
+ */
+BrowserBridge.POLL_INTERVAL_MS = 5000;
+
//------------------------------------------------------------------------------
// Messages sent to the browser
//------------------------------------------------------------------------------
-function notifyApplicationReady() {
+BrowserBridge.prototype.sendReady = function() {
chrome.send('notifyReady');
-}
+
+ // Some of the data we are interested is not currently exposed as a stream,
+ // so we will poll the browser to find out when it changes and then notify
+ // the observers.
+ window.setInterval(
+ this.doPolling_.bind(this), BrowserBridge.POLL_INTERVAL_MS);
+};
+
+BrowserBridge.prototype.sendGetProxySettings = function() {
+ // The browser will call receivedProxySettings on completion.
+ chrome.send('getProxySettings');
+};
+
+BrowserBridge.prototype.sendReloadProxySettings = function() {
+ chrome.send('reloadProxySettings');
+};
+
+BrowserBridge.prototype.sendGetBadProxies = function() {
+ // The browser will call receivedBadProxies on completion.
+ chrome.send('getBadProxies');
+};
+
+BrowserBridge.prototype.sendClearBadProxies = function() {
+ chrome.send('clearBadProxies');
+};
//------------------------------------------------------------------------------
// Messages received from the browser
//------------------------------------------------------------------------------
-function onLogEntryAdded(logEntry) {
- LogDataProvider.broadcast(logEntry);
-}
+BrowserBridge.prototype.receivedLogEntry = function(logEntry) {
+ for (var i = 0; i < this.logObservers_.length; ++i)
+ this.logObservers_[i].onLogEntryAdded(logEntry);
+};
-function setLogEventTypeConstants(constantsMap) {
+BrowserBridge.prototype.receivedLogEventTypeConstants = function(constantsMap) {
LogEventType = constantsMap;
-}
+};
-function setLogEventPhaseConstants(constantsMap) {
+BrowserBridge.prototype.receivedLogEventPhaseConstants = function(constantsMap) {
LogEventPhase = constantsMap;
-}
+};
-function setLogSourceTypeConstants(constantsMap) {
+BrowserBridge.prototype.receivedLogSourceTypeConstants = function(constantsMap) {
LogSourceType = constantsMap;
-}
+};
-function setLogEntryTypeConstants(constantsMap) {
+BrowserBridge.prototype.receivedLogEntryTypeConstants = function(constantsMap) {
LogEntryType = constantsMap;
-}
+};
+
+BrowserBridge.prototype.receivedTimeTickOffset = function(timeTickOffset) {
+ this.timeTickOffset_ = timeTickOffset;
+};
+
+BrowserBridge.prototype.receivedProxySettings = function(proxySettings) {
+ this.dispatchToObserversFromPoll_(
+ this.proxySettingsObservers_, 'onProxySettingsChanged', proxySettings);
+};
+
+BrowserBridge.prototype.receivedBadProxies = function(badProxies) {
+ this.dispatchToObserversFromPoll_(
+ this.badProxiesObservers_, 'onBadProxiesChanged', badProxies);
+};
-//------------------------------------------------------------------------------
-// LogDataProvider
//------------------------------------------------------------------------------
-var LogDataProvider = {}
+/**
+ * Adds a listener of log entries. |observer| will be called back when new log
+ * data arrives, through:
+ *
+ * observer.onLogEntryAdded(logEntry)
+ */
+BrowserBridge.prototype.addLogObserver = function(observer) {
+ this.logObservers_.push(observer);
+};
-LogDataProvider.observers_ = [];
+/**
+ * Adds a listener of the proxy settings. |observer| will be called back when
+ * data is received, through:
+ *
+ * observer.onProxySettingsChanged(proxySettings)
+ *
+ * |proxySettings| is a formatted string describing the settings.
+ * TODO(eroman): send a dictionary instead.
+ */
+BrowserBridge.prototype.addProxySettingsObserver = function(observer) {
+ this.proxySettingsObservers_.push(observer);
+};
+
+/**
+ * Adds a listener of the proxy settings. |observer| will be called back when
+ * data is received, through:
+ *
+ * observer.onBadProxiesChanged(badProxies)
+ *
+ * |badProxies| is an array, where each entry has the property:
+ * badProxies[i].proxy_uri: String identify the proxy.
+ * badProxies[i].bad_until: The time when the proxy stops being considered
+ * bad. Note the time is in time ticks.
+ */
+BrowserBridge.prototype.addBadProxiesObsever = function(observer) {
+ this.badProxiesObservers_.push(observer);
+};
+
+/**
+ * The browser gives us times in terms of "time ticks" in milliseconds.
+ * This function converts the tick count to a Date() object.
+ *
+ * @param {String} timeTicks.
+ * @returns {Date} The time that |timeTicks| represents.
+ */
+BrowserBridge.prototype.convertTimeTicksToDate = function(timeTicks) {
+ // Note that the subtraction by 0 is to cast to a number (probably a float
+ // since the numbers are big).
+ var timeStampMs = (this.timeTickOffset_ - 0) + (timeTicks - 0);
+ var d = new Date();
+ d.setTime(timeStampMs);
+ return d;
+};
-LogDataProvider.broadcast = function(logEntry) {
- for (var i = 0; i < this.observers_.length; ++i) {
- this.observers_[i].onLogEntryAdded(logEntry);
- }
+BrowserBridge.prototype.doPolling_ = function() {
+ this.sendGetProxySettings();
+ this.sendGetBadProxies();
};
-LogDataProvider.addObserver = function(observer) {
- this.observers_.push(observer);
+/**
+ * Helper function to handle calling all the observers, but ONLY if the data has
+ * actually changed since last time. This is used for data we received from
+ * browser on a poll loop.
+ */
+BrowserBridge.prototype.dispatchToObserversFromPoll_ = function(
+ observerList, method, data) {
+ var prevData = this.prevPollData_[method];
+
+ // If the data hasn't changed since last time, no need to notify observers.
+ if (prevData && JSON.stringify(prevData) == JSON.stringify(data))
+ return;
+
+ this.prevPollData_[method] = data;
+
+ // Ok, notify the observers of the change.
+ for (var i = 0; i < observerList.length; ++i)
+ observerList[i][method](data);
};
diff --git a/chrome/browser/resources/net_internals/proxyview.js b/chrome/browser/resources/net_internals/proxyview.js
new file mode 100644
index 0000000..4d7d885
--- /dev/null
+++ b/chrome/browser/resources/net_internals/proxyview.js
@@ -0,0 +1,62 @@
+// Copyright (c) 2010 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.
+ *
+ * @constructor
+ */
+function ProxyView(mainBoxId,
+ currentConfigDivId,
+ reloadSettingsButtonId,
+ badProxiesTbodyId,
+ clearBadProxiesButtonId) {
+ DivView.call(this, mainBoxId);
+
+ // Hook up the UI components.
+ this.currentConfigDiv_ = document.getElementById(currentConfigDivId);
+ this.badProxiesTbody_ = document.getElementById(badProxiesTbodyId);
+
+ var reloadSettingsButton = document.getElementById(reloadSettingsButtonId);
+ var clearBadProxiesButton = document.getElementById(clearBadProxiesButtonId);
+
+ clearBadProxiesButton.onclick = g_browser.sendClearBadProxies.bind(g_browser);
+ reloadSettingsButton.onclick =
+ g_browser.sendReloadProxySettings.bind(g_browser);
+
+ // Register to receive proxy information as it changes.
+ g_browser.addProxySettingsObserver(this);
+ g_browser.addBadProxiesObsever(this);
+}
+
+inherits(ProxyView, DivView);
+
+ProxyView.prototype.onProxySettingsChanged = function(proxySettings) {
+ // |proxySettings| is a formatted string describing the settings.
+ this.currentConfigDiv_.innerHTML = ''
+ addTextNode(this.currentConfigDiv_, proxySettings);
+};
+
+ProxyView.prototype.onBadProxiesChanged = function(badProxies) {
+ this.badProxiesTbody_.innerHTML = '';
+
+ // Add a table row for each bad proxy entry.
+ for (var i = 0; i < badProxies.length; ++i) {
+ var entry = badProxies[i];
+ var badUntilDate = g_browser.convertTimeTicksToDate(entry.bad_until);
+
+ var tr = addNode(this.badProxiesTbody_, 'tr');
+
+ var nameCell = addNode(tr, 'td');
+ var badUntilCell = addNode(tr, 'td');
+
+ addTextNode(nameCell, entry.proxy_uri);
+ addTextNode(badUntilCell, badUntilDate.toLocaleString());
+ }
+};
diff --git a/chrome/browser/resources/net_internals/requestsview.js b/chrome/browser/resources/net_internals/requestsview.js
index 16b39b9..2d16704 100644
--- a/chrome/browser/resources/net_internals/requestsview.js
+++ b/chrome/browser/resources/net_internals/requestsview.js
@@ -49,7 +49,7 @@ function RequestsView(tableBodyId, filterInputId, filterCountId,
this.sourceIdToEntryMap_ = {};
this.currentSelectedSources_ = [];
- LogDataProvider.addObserver(this);
+ g_browser.addLogObserver(this);
this.tableBody_ = document.getElementById(tableBodyId);
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index cedfbbe..d9df1a3 100755
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -3185,6 +3185,7 @@
'browser/resources/net_internals/logviewpainter.js',
'browser/resources/net_internals/main.css',
'browser/resources/net_internals/main.js',
+ 'browser/resources/net_internals/proxyview.js',
'browser/resources/net_internals/requestsview.js',
'browser/resources/net_internals/resizableverticalsplitview.js',
'browser/resources/net_internals/sourceentry.js',