summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjoi@chromium.org <joi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-25 21:11:53 +0000
committerjoi@chromium.org <joi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-25 21:11:53 +0000
commit227b0e8d0e0f62dc2ee2a50aca77de83ff394278 (patch)
treee185402e8a1da224dc3ac55ebd0fa295ce07a5ad
parent76c551c6fe7dcfc664b9261eaec812a1966d1984 (diff)
downloadchromium_src-227b0e8d0e0f62dc2ee2a50aca77de83ff394278.zip
chromium_src-227b0e8d0e0f62dc2ee2a50aca77de83ff394278.tar.gz
chromium_src-227b0e8d0e0f62dc2ee2a50aca77de83ff394278.tar.bz2
Support enabling/disabling the URL request throttler via the about:net-internals page:
- Add a new tab to the about:net-internals page. - Add a preference item to persist user's choice. - Remove the command line switch --disable-enforced-throttling. - Make throttling feature off by default for now. This is 95% based on yzshen@chromium.org's patch http://codereview.chromium.org/6286001/ which was never landed. The changes that have been made from that patch are mostly cosmetic, apart from updating it to match the codebase (the patch was prepared ~2 months ago) and responding to eroman@'s initial round of code review comments. BUG=66062 TEST=Make sure the checkbox on about:net-internals > HTTP Throttling is checked. (1) Type in the addresss bar a URL which is expected to return 5XX. (2) Keep clicking the "reload" button. (3) After a few clicks, Chrome displays an error page explaining why a net::ERR_TEMPORARILY_THROTTLED error occurs. Make sure the checkbox on about:net-internals > HTTP Throttling is unchecked. Following step (1) and (2) described above won't result in a net::ERR_TEMPORARILY_THROTTLED error page. Review URL: http://codereview.chromium.org/6677085 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@79455 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/app/generated_resources.grd9
-rw-r--r--chrome/browser/browser_main.cc4
-rw-r--r--chrome/browser/net/net_pref_observer.cc33
-rw-r--r--chrome/browser/net/net_pref_observer.h6
-rw-r--r--chrome/browser/resources/net_internals/httpthrottlingview.js34
-rw-r--r--chrome/browser/resources/net_internals/index.html22
-rw-r--r--chrome/browser/resources/net_internals/main.css11
-rw-r--r--chrome/browser/resources/net_internals/main.js31
-rw-r--r--chrome/browser/ui/webui/net_internals_ui.cc81
-rw-r--r--chrome/common/chrome_switches.cc6
-rw-r--r--chrome/common/chrome_switches.h1
-rw-r--r--chrome/common/pref_names.cc3
-rw-r--r--chrome/common/pref_names.h1
-rw-r--r--net/url_request/url_request_http_job.cc10
-rw-r--r--net/url_request/url_request_throttler_entry.cc14
-rw-r--r--net/url_request/url_request_throttler_manager.cc26
-rw-r--r--net/url_request/url_request_throttler_manager.h14
-rw-r--r--net/url_request/url_request_throttler_unittest.cc2
18 files changed, 266 insertions, 42 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 2717ec4..2eb87d1 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -6276,9 +6276,14 @@ Keep your key file in a safe place. You will need it to create new versions of y
</message>
<message name="IDS_ERRORPAGES_SUMMARY_TEMPORARILY_THROTTLED" desc="Summary in the error page when we temporarily stop sending requests to a server in order to avoid DDoS.">
- It is likely that the server hosting the webpage has been overloaded or encountered an error. In order to avoid causing too much traffic and making the situation worse, <ph name="PRODUCT_NAME">&lt;span jscontent="productName"&gt;&lt;/span&gt;<ex>Google Chrome</ex></ph> has temporarily stopped allowing requests to the server.
+ It is likely that the server hosting the webpage has been overloaded or encountered an error. In order to avoid causing
+ too much traffic and making the situation worse,
+ <ph name="PRODUCT_NAME">&lt;span jscontent="productName"&gt;&lt;/span&gt;<ex>Google Chrome</ex></ph> has temporarily
+ stopped allowing requests to the server.
<ph name="LINE_BREAK">&lt;br /&gt;&lt;br /&gt;</ph>
- If you think this behavior is undesirable, for example, you are debugging your own website, you could disable it by relaunching <ph name="PRODUCT_NAME">&lt;span jscontent="productName"&gt;&lt;/span&gt;<ex>Google Chrome</ex></ph> with the command line flag <ph name="COMMAND_LINE_FLAG">&lt;strong&gt;--disable-enforced-throttling&lt;/strong&gt;</ph>.
+ If you think this behavior is undesirable, for example, you are debugging your own website, please
+ visit the <ph name="NET_INTERNALS_PAGE">&lt;strong&gt;chrome://net-internals/#httpThrottling&lt;/strong&gt;</ph> page,
+ where you can find more information or disable the feature.
</message>
<message name="IDS_ERRORPAGES_DETAILS_TEMPORARILY_THROTTLED" desc="The error message displayed when we temporarily stop sending requests to a server in order to avoid DDoS.">
Requests to the server have been temporarily throttled.
diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc
index 66b13d7..b4db556 100644
--- a/chrome/browser/browser_main.cc
+++ b/chrome/browser/browser_main.cc
@@ -626,8 +626,8 @@ void InitializeNetworkOptions(const CommandLine& parsed_command_line) {
net::SpdySessionPool::set_max_sessions_per_domain(value);
}
- net::URLRequestThrottlerManager::GetInstance()->InitializeOptions(
- parsed_command_line.HasSwitch(switches::kDisableEnforcedThrottling));
+ net::URLRequestThrottlerManager::GetInstance()->set_enable_thread_checks(
+ true);
SetDnsCertProvenanceCheckerFactory(CreateChromeDnsCertProvenanceChecker);
}
diff --git a/chrome/browser/net/net_pref_observer.cc b/chrome/browser/net/net_pref_observer.cc
index 48a051c..75dd11a 100644
--- a/chrome/browser/net/net_pref_observer.cc
+++ b/chrome/browser/net/net_pref_observer.cc
@@ -4,20 +4,35 @@
#include "chrome/browser/net/net_pref_observer.h"
+#include "base/task.h"
#include "chrome/browser/net/predictor_api.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/common/pref_names.h"
#include "content/browser/browser_thread.h"
#include "content/common/notification_type.h"
+#include "content/common/notification_details.h"
#include "net/http/http_stream_factory.h"
+#include "net/url_request/url_request_throttler_manager.h"
+
+namespace {
+
+// Function (for NewRunnableFunction) to call the set_enforce_throttling
+// member on the URLRequestThrottlerManager singleton.
+void SetEnforceThrottlingOnThrottlerManager(bool enforce) {
+ net::URLRequestThrottlerManager::GetInstance()->set_enforce_throttling(
+ enforce);
+}
+
+}
NetPrefObserver::NetPrefObserver(PrefService* prefs) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
dns_prefetching_enabled_.Init(prefs::kDnsPrefetchingEnabled, prefs, this);
spdy_disabled_.Init(prefs::kDisableSpdy, prefs, this);
+ http_throttling_enabled_.Init(prefs::kHttpThrottlingEnabled, prefs, this);
- ApplySettings();
+ ApplySettings(NULL);
}
NetPrefObserver::~NetPrefObserver() {
@@ -27,16 +42,28 @@ NetPrefObserver::~NetPrefObserver() {
void NetPrefObserver::Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
- ApplySettings();
+ DCHECK_EQ(type.value, NotificationType::PREF_CHANGED);
+
+ std::string* pref_name = Details<std::string>(details).ptr();
+ ApplySettings(pref_name);
}
-void NetPrefObserver::ApplySettings() {
+void NetPrefObserver::ApplySettings(const std::string* pref_name) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
chrome_browser_net::EnablePredictor(*dns_prefetching_enabled_);
net::HttpStreamFactory::set_spdy_enabled(!*spdy_disabled_);
+
+ if (!pref_name || *pref_name == prefs::kHttpThrottlingEnabled) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ NewRunnableFunction(SetEnforceThrottlingOnThrottlerManager,
+ *http_throttling_enabled_));
+ }
}
// static
void NetPrefObserver::RegisterPrefs(PrefService* prefs) {
prefs->RegisterBooleanPref(prefs::kDisableSpdy, false);
+ prefs->RegisterBooleanPref(prefs::kHttpThrottlingEnabled, false);
}
diff --git a/chrome/browser/net/net_pref_observer.h b/chrome/browser/net/net_pref_observer.h
index b5954231..a1fd2bd 100644
--- a/chrome/browser/net/net_pref_observer.h
+++ b/chrome/browser/net/net_pref_observer.h
@@ -6,6 +6,8 @@
#define CHROME_BROWSER_NET_NET_PREF_OBSERVER_H_
#pragma once
+#include <string>
+
#include "base/basictypes.h"
#include "chrome/browser/prefs/pref_member.h"
#include "content/common/notification_observer.h"
@@ -26,10 +28,12 @@ class NetPrefObserver : public NotificationObserver {
static void RegisterPrefs(PrefService* prefs);
private:
- void ApplySettings();
+ // If |pref_name| is NULL, all monitored preferences will be applied.
+ void ApplySettings(const std::string* pref_name);
BooleanPrefMember dns_prefetching_enabled_;
BooleanPrefMember spdy_disabled_;
+ BooleanPrefMember http_throttling_enabled_;
DISALLOW_COPY_AND_ASSIGN(NetPrefObserver);
};
diff --git a/chrome/browser/resources/net_internals/httpthrottlingview.js b/chrome/browser/resources/net_internals/httpthrottlingview.js
new file mode 100644
index 0000000..4cc8305
--- /dev/null
+++ b/chrome/browser/resources/net_internals/httpthrottlingview.js
@@ -0,0 +1,34 @@
+// Copyright (c) 2011 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 related to HTTP throttling.
+ * @constructor
+ */
+function HttpThrottlingView(mainBoxId, enableCheckboxId) {
+ DivView.call(this, mainBoxId);
+
+ this.enableCheckbox_ = document.getElementById(enableCheckboxId);
+ this.enableCheckbox_.onclick = this.onEnableCheckboxClicked_.bind(this);
+
+ g_browser.addHttpThrottlingObserver(this);
+}
+
+inherits(HttpThrottlingView, DivView);
+
+/**
+ * Gets informed that HTTP throttling has been enabled/disabled.
+ * @param {boolean} enabled HTTP throttling has been enabled.
+ */
+HttpThrottlingView.prototype.onHttpThrottlingEnabledPrefChanged = function(
+ enabled) {
+ this.enableCheckbox_.checked = enabled;
+};
+
+/**
+ * Handler for the onclick event of the checkbox.
+ */
+HttpThrottlingView.prototype.onEnableCheckboxClicked_ = function() {
+ g_browser.enableHttpThrottling(this.enableCheckbox_.checked);
+}; \ No newline at end of file
diff --git a/chrome/browser/resources/net_internals/index.html b/chrome/browser/resources/net_internals/index.html
index c18da47..32b0518 100644
--- a/chrome/browser/resources/net_internals/index.html
+++ b/chrome/browser/resources/net_internals/index.html
@@ -1,7 +1,7 @@
<!DOCTYPE HTML>
<head i18n-values="dir:textdirection;">
<!--
-Copyright (c) 2010 The Chromium Authors. All rights reserved.
+Copyright (c) 2011 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.
-->
@@ -30,6 +30,7 @@ found in the LICENSE file.
<script src="socketsview.js"></script>
<script src="spdyview.js"></script>
<script src="serviceprovidersview.js"></script>
+ <script src="httpthrottlingview.js"></script>
</head>
<body onload="onLoaded()">
<!-- Tab switcher for main categories. -->
@@ -42,6 +43,7 @@ found in the LICENSE file.
<li><a href="#sockets" id=socketsTab>Sockets</a></li>
<li><a href="#spdy" id=spdyTab>SPDY</a></li>
<li><a href="#httpCache" id=httpCacheTab>HTTP Cache</a></li>
+ <li><a href="#httpThrottling" id=httpThrottlingTab>HTTP Throttling</a></li>
<!-- Tab is only shown on Windows -->
<li><a href="#serviceProviders" id=serviceProvidersTab style="display: none;">SPIs</a></li>
<li><a href="#tests" id=testTab>Tests</a></li>
@@ -181,6 +183,24 @@ found in the LICENSE file.
<h4>Statistics</h4>
<div id=httpCacheStats>Nothing loaded yet.</div>
</div>
+ <div id=httpThrottlingTabContent>
+ <p>
+ In order to prevent Distributed Denial of Service (DDoS) attacks from
+ being perpetrated by web pages and extensions that run within Chrome, the
+ HTTP throttling mechanism keeps track of errors requesting a given URL
+ (minus the query parameters), and after a few 5xx errors in a row, starts
+ exponentially increasing an interval during which requests to the
+ given URL are disallowed.
+ </p><p>
+ You may enable or disable the feature below. Please let us know if the
+ feature is causing problems for your web site. More details and contact
+ information at
+ <a href="http://dev.chromium.org/throttling">http://dev.chromium.org/throttling</a>.
+ </p>
+ <p><input id=enableHttpThrottlingCheckbox type=checkbox />
+ Throttle HTTP requests if the server has been overloaded or encountered an error.
+ </p>
+ </div>
<!-- Only shown on Windows -->
<div id=serviceProvidersTabContent style="display: none;">
<h4>Layered Service Providers</h4>
diff --git a/chrome/browser/resources/net_internals/main.css b/chrome/browser/resources/net_internals/main.css
index 46a10c5..f7c575c 100644
--- a/chrome/browser/resources/net_internals/main.css
+++ b/chrome/browser/resources/net_internals/main.css
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2010 The Chromium Authors. All rights reserved.
+Copyright (c) 2011 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.
*/
@@ -162,7 +162,8 @@ body {
#spdyTabContent,
#serviceProvidersTabContent,
#testTabContent,
-#hstsTabContent {
+#hstsTabContent,
+#httpThrottlingTabContent {
overflow: auto;
padding: 10px;
}
@@ -183,8 +184,8 @@ table.styledTable,
.styledTable th,
.styledTable td {
border: 1px solid #777;
- padding-right: 4px;
- padding-left: 4px;
+ padding-right: 4px;
+ padding-left: 4px;
}
.styledTable th {
@@ -195,7 +196,7 @@ table.styledTable,
background: rgb(255,217,217);
}
-/*
+/*
* This is the box in the top right of the Data tab which shows how many
* events have been captured so far.
*/
diff --git a/chrome/browser/resources/net_internals/main.js b/chrome/browser/resources/net_internals/main.js
index 561770b..979ac96 100644
--- a/chrome/browser/resources/net_internals/main.js
+++ b/chrome/browser/resources/net_internals/main.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -120,6 +120,9 @@ function onLoaded() {
'namespaceProvidersTbody');
}
+ var httpThrottlingView = new HttpThrottlingView(
+ 'httpThrottlingTabContent', 'enableHttpThrottlingCheckbox');
+
// Create a view which lets you tab between the different sub-views.
var categoryTabSwitcher = new TabSwitcherView('categoryTabHandles');
g_browser.setTabSwitcher(categoryTabSwitcher);
@@ -136,6 +139,7 @@ function onLoaded() {
categoryTabSwitcher.addTab('serviceProvidersTab', serviceView, false);
categoryTabSwitcher.addTab('testTab', testView, false);
categoryTabSwitcher.addTab('hstsTab', hstsView, false);
+ categoryTabSwitcher.addTab('httpThrottlingTab', httpThrottlingView, false);
// Build a map from the anchor name of each tab handle to its "tab ID".
// We will consider navigations to the #hash as a switch tab request.
@@ -178,6 +182,7 @@ function BrowserBridge() {
this.logObservers_ = [];
this.connectionTestsObservers_ = [];
this.hstsObservers_ = [];
+ this.httpThrottlingObservers_ = [];
this.pollableDataHelpers_ = {};
this.pollableDataHelpers_.proxySettings =
@@ -352,7 +357,11 @@ BrowserBridge.prototype.enableIPv6 = function() {
BrowserBridge.prototype.setLogLevel = function(logLevel) {
chrome.send('setLogLevel', ['' + logLevel]);
-}
+};
+
+BrowserBridge.prototype.enableHttpThrottling = function(enable) {
+ chrome.send('enableHttpThrottling', [enable]);
+};
BrowserBridge.prototype.loadLogFile = function() {
chrome.send('loadLogFile');
@@ -502,6 +511,14 @@ BrowserBridge.prototype.receivedHttpCacheInfo = function(info) {
this.pollableDataHelpers_.httpCacheInfo.update(info);
};
+BrowserBridge.prototype.receivedHttpThrottlingEnabledPrefChanged = function(
+ enabled) {
+ for (var i = 0; i < this.httpThrottlingObservers_.length; ++i) {
+ this.httpThrottlingObservers_[i].onHttpThrottlingEnabledPrefChanged(
+ enabled);
+ }
+};
+
BrowserBridge.prototype.loadedLogFile = function(logFileContents) {
var match;
// Replace carriage returns with linebreaks and then split around linebreaks.
@@ -730,6 +747,16 @@ BrowserBridge.prototype.addHSTSObserver = function(observer) {
};
/**
+ * Adds a listener for HTTP throttling-related events. |observer| will be called
+ * back when HTTP throttling is enabled/disabled, through:
+ *
+ * observer.onHttpThrottlingEnabledPrefChanged(enabled);
+ */
+BrowserBridge.prototype.addHttpThrottlingObserver = function(observer) {
+ this.httpThrottlingObservers_.push(observer);
+};
+
+/**
* The browser gives us times in terms of "time ticks" in milliseconds.
* This function converts the tick count to a Date() object.
*
diff --git a/chrome/browser/ui/webui/net_internals_ui.cc b/chrome/browser/ui/webui/net_internals_ui.cc
index a440a39..641012c 100644
--- a/chrome/browser/ui/webui/net_internals_ui.cc
+++ b/chrome/browser/ui/webui/net_internals_ui.cc
@@ -26,6 +26,7 @@
#include "chrome/browser/net/passive_log_collector.h"
#include "chrome/browser/net/url_fixer_upper.h"
#include "chrome/browser/platform_util.h"
+#include "chrome/browser/prefs/pref_member.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/shell_dialogs.h"
#include "chrome/browser/ui/webui/chrome_url_data_manager.h"
@@ -33,10 +34,12 @@
#include "chrome/common/chrome_version_info.h"
#include "chrome/common/jstemplate_builder.h"
#include "chrome/common/net/url_request_context_getter.h"
+#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "content/browser/browser_thread.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "content/browser/tab_contents/tab_contents_view.h"
+#include "content/common/notification_details.h"
#include "grit/generated_resources.h"
#include "grit/net_internals_resources.h"
#include "net/base/escape.h"
@@ -136,14 +139,15 @@ class NetInternalsHTMLSource : public ChromeURLDataManager::DataSource {
// this class's methods are expected to run on the UI thread.
//
// Since the network code we want to run lives on the IO thread, we proxy
-// everything over to NetInternalsMessageHandler::IOThreadImpl, which runs
-// on the IO thread.
+// almost everything over to NetInternalsMessageHandler::IOThreadImpl, which
+// runs on the IO thread.
//
// TODO(eroman): Can we start on the IO thread to begin with?
class NetInternalsMessageHandler
: public WebUIMessageHandler,
public SelectFileDialog::Listener,
- public base::SupportsWeakPtr<NetInternalsMessageHandler> {
+ public base::SupportsWeakPtr<NetInternalsMessageHandler>,
+ public NotificationObserver {
public:
NetInternalsMessageHandler();
virtual ~NetInternalsMessageHandler();
@@ -157,6 +161,15 @@ class NetInternalsMessageHandler
void CallJavascriptFunction(const std::wstring& function_name,
const Value* value);
+ // NotificationObserver implementation.
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ // Javascript message handlers.
+ void OnRendererReady(const ListValue* list);
+ void OnEnableHttpThrottling(const ListValue* list);
+
// SelectFileDialog::Listener implementation
virtual void FileSelected(const FilePath& path, int index, void* params);
virtual void FileSelectionCanceled(void* params);
@@ -188,6 +201,14 @@ class NetInternalsMessageHandler
const FilePath path_;
};
+ // The pref member about whether HTTP throttling is enabled, which needs to
+ // be accessed on the UI thread.
+ BooleanPrefMember http_throttling_enabled_;
+
+ // OnRendererReady invokes this callback to do the part of message handling
+ // that needs to happen on the IO thread.
+ scoped_ptr<WebUI::MessageCallback> renderer_ready_io_callback_;
+
// This is the "real" message handler, which lives on the IO thread.
scoped_refptr<IOThreadImpl> proxy_;
@@ -340,7 +361,7 @@ class NetInternalsMessageHandler::IOThreadImpl
scoped_ptr<ListValue> pending_entries_;
};
-// Helper class for a WebUI::MessageCallback which when excuted calls
+// Helper class for a WebUI::MessageCallback which when executed calls
// instance->*method(value) on the IO thread.
class NetInternalsMessageHandler::IOThreadImpl::CallbackHelper
: public WebUI::MessageCallback {
@@ -449,8 +470,16 @@ NetInternalsMessageHandler::~NetInternalsMessageHandler() {
WebUIMessageHandler* NetInternalsMessageHandler::Attach(WebUI* web_ui) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ PrefService* pref_service = web_ui->GetProfile()->GetPrefs();
+ http_throttling_enabled_.Init(prefs::kHttpThrottlingEnabled, pref_service,
+ this);
+
proxy_ = new IOThreadImpl(this->AsWeakPtr(), g_browser_process->io_thread(),
web_ui->GetProfile()->GetRequestContext());
+ renderer_ready_io_callback_.reset(
+ proxy_->CreateCallback(&IOThreadImpl::OnRendererReady));
+
WebUIMessageHandler* result = WebUIMessageHandler::Attach(web_ui);
return result;
}
@@ -487,7 +516,7 @@ void NetInternalsMessageHandler::RegisterMessages() {
web_ui_->RegisterMessageCallback(
"notifyReady",
- proxy_->CreateCallback(&IOThreadImpl::OnRendererReady));
+ NewCallback(this, &NetInternalsMessageHandler::OnRendererReady));
web_ui_->RegisterMessageCallback(
"getProxySettings",
proxy_->CreateCallback(&IOThreadImpl::OnGetProxySettings));
@@ -546,6 +575,10 @@ void NetInternalsMessageHandler::RegisterMessages() {
web_ui_->RegisterMessageCallback(
"setLogLevel",
proxy_->CreateCallback(&IOThreadImpl::OnSetLogLevel));
+
+ web_ui_->RegisterMessageCallback(
+ "enableHttpThrottling",
+ NewCallback(this, &NetInternalsMessageHandler::OnEnableHttpThrottling));
}
void NetInternalsMessageHandler::CallJavascriptFunction(
@@ -559,6 +592,44 @@ void NetInternalsMessageHandler::CallJavascriptFunction(
}
}
+void NetInternalsMessageHandler::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK_EQ(type.value, NotificationType::PREF_CHANGED);
+
+ std::string* pref_name = Details<std::string>(details).ptr();
+ if (*pref_name == prefs::kHttpThrottlingEnabled) {
+ scoped_ptr<Value> enabled(
+ Value::CreateBooleanValue(*http_throttling_enabled_));
+
+ CallJavascriptFunction(
+ L"g_browser.receivedHttpThrottlingEnabledPrefChanged", enabled.get());
+ }
+}
+
+void NetInternalsMessageHandler::OnRendererReady(const ListValue* list) {
+ CHECK(renderer_ready_io_callback_.get());
+ renderer_ready_io_callback_->Run(list);
+
+ scoped_ptr<Value> enabled(
+ Value::CreateBooleanValue(*http_throttling_enabled_));
+ CallJavascriptFunction(
+ L"g_browser.receivedHttpThrottlingEnabledPrefChanged", enabled.get());
+}
+
+void NetInternalsMessageHandler::OnEnableHttpThrottling(const ListValue* list) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ bool enable = false;
+ if (!list->GetBoolean(0, &enable)) {
+ NOTREACHED();
+ return;
+ }
+
+ http_throttling_enabled_.SetValue(enable);
+}
+
////////////////////////////////////////////////////////////////////////////////
//
// NetInternalsMessageHandler::ReadLogFileTask
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index b7c237e..7fcece0 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -209,12 +209,6 @@ const char kDisableDevTools[] = "disable-dev-tools";
// Disables device orientation events.
const char kDisableDeviceOrientation[] = "disable-device-orientation";
-// By default, if the URL request throttler finds that a server is overloaded or
-// encounters an error, it rejects requests to the server for a period of time,
-// which is determined by an exponential back-off algorithm. This switch
-// disables such behavior.
-const char kDisableEnforcedThrottling[] = "disable-enforced-throttling";
-
// Disable extensions.
const char kDisableExtensions[] = "disable-extensions";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 4604e0e..d667e19 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -71,7 +71,6 @@ extern const char kDisableConnectBackupJobs[];
extern const char kDisableCustomJumpList[];
extern const char kDisableDevTools[];
extern const char kDisableDeviceOrientation[];
-extern const char kDisableEnforcedThrottling[];
extern const char kDisableExtensionsFileAccessCheck[];
extern const char kDisableExtensions[];
extern const char kDisableFlashSandbox[];
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 04d2e0a..9b4c1f7 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -674,6 +674,9 @@ const char kEnableTranslate[] = "translate.enabled";
const char kPinnedTabs[] = "pinned_tabs";
+// Boolean that is true when HTTP throttling is enabled.
+const char kHttpThrottlingEnabled[] = "http_throttling.enabled";
+
// Integer that specifies the policy refresh rate for user policy in
// milliseconds. Not all values are meaningful, so it is clamped to a sane
// range by the cloud policy subsystem.
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 1550df6..1ae19e6 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -240,6 +240,7 @@ extern const char kAutofillPersonalDataManagerFirstRun[];
extern const char kUseVerticalTabs[];
extern const char kEnableTranslate[];
extern const char kPinnedTabs[];
+extern const char kHttpThrottlingEnabled[];
extern const char kPolicyUserPolicyRefreshRate[];
extern const char kPolicyDevicePolicyRefreshRate[];
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc
index 111146c..a51e239 100644
--- a/net/url_request/url_request_http_job.cc
+++ b/net/url_request/url_request_http_job.cc
@@ -317,8 +317,14 @@ void URLRequestHttpJob::StartTransaction() {
rv = request_->context()->http_transaction_factory()->CreateTransaction(
&transaction_);
if (rv == OK) {
- rv = transaction_->Start(
- &request_info_, &start_callback_, request_->net_log());
+ if (!URLRequestThrottlerManager::GetInstance()->enforce_throttling() ||
+ !throttling_entry_->IsDuringExponentialBackoff()) {
+ rv = transaction_->Start(
+ &request_info_, &start_callback_, request_->net_log());
+ } else {
+ // Special error code for the exponential back-off module.
+ rv = ERR_TEMPORARILY_THROTTLED;
+ }
// Make sure the context is alive for the duration of the
// transaction.
context_ = request_->context();
diff --git a/net/url_request/url_request_throttler_entry.cc b/net/url_request/url_request_throttler_entry.cc
index 05b2af2..0fdef2b 100644
--- a/net/url_request/url_request_throttler_entry.cc
+++ b/net/url_request/url_request_throttler_entry.cc
@@ -58,6 +58,20 @@ URLRequestThrottlerEntry::URLRequestThrottlerEntry(
}
bool URLRequestThrottlerEntry::IsEntryOutdated() const {
+ // This function is called by the URLRequestThrottlerManager to determine
+ // whether entries should be discarded from its url_entries_ map. We
+ // want to ensure that it does not remove entries from the map while there
+ // are clients (objects other than the manager) holding references to
+ // the entry, otherwise separate clients could end up holding separate
+ // entries for a request to the same URL, which is undesirable. Therefore,
+ // if an entry has more than one reference (the map will always hold one),
+ // it should not be considered outdated.
+ //
+ // TODO(joi): Once the manager is not a Singleton, revisit whether
+ // refcounting is needed at all.
+ if (!HasOneRef())
+ return false;
+
// If there are send events in the sliding window period, we still need this
// entry.
if (!send_log_.empty() &&
diff --git a/net/url_request/url_request_throttler_manager.cc b/net/url_request/url_request_throttler_manager.cc
index 635c716..de8b817 100644
--- a/net/url_request/url_request_throttler_manager.cc
+++ b/net/url_request/url_request_throttler_manager.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -18,7 +18,7 @@ URLRequestThrottlerManager* URLRequestThrottlerManager::GetInstance() {
scoped_refptr<URLRequestThrottlerEntryInterface>
URLRequestThrottlerManager::RegisterRequestUrl(const GURL &url) {
- DCHECK(being_tested_ || CalledOnValidThread());
+ DCHECK(!enable_thread_checks_ || CalledOnValidThread());
// Normalize the url.
std::string url_id = GetIdFromUrl(url);
@@ -52,15 +52,27 @@ void URLRequestThrottlerManager::EraseEntryForTests(const GURL& url) {
url_entries_.erase(url_id);
}
-void URLRequestThrottlerManager::InitializeOptions(bool enforce_throttling) {
- enforce_throttling_ = enforce_throttling;
- being_tested_ = false;
+void URLRequestThrottlerManager::set_enable_thread_checks(bool enable) {
+ enable_thread_checks_ = enable;
}
+bool URLRequestThrottlerManager::enable_thread_checks() const {
+ return enable_thread_checks_;
+}
+
+void URLRequestThrottlerManager::set_enforce_throttling(bool enforce) {
+ enforce_throttling_ = enforce;
+}
+
+bool URLRequestThrottlerManager::enforce_throttling() {
+ return enforce_throttling_;
+}
+
+// TODO(joi): Turn throttling on by default when appropriate.
URLRequestThrottlerManager::URLRequestThrottlerManager()
: requests_since_last_gc_(0),
- enforce_throttling_(true),
- being_tested_(true) {
+ enforce_throttling_(false),
+ enable_thread_checks_(false) {
// Construction/destruction is on main thread (because BrowserMain
// retrieves an instance to call InitializeOptions), but is from then on
// used on I/O thread.
diff --git a/net/url_request/url_request_throttler_manager.h b/net/url_request/url_request_throttler_manager.h
index c48e917..d65b20f 100644
--- a/net/url_request/url_request_throttler_manager.h
+++ b/net/url_request/url_request_throttler_manager.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -53,9 +53,15 @@ class URLRequestThrottlerManager : public base::NonThreadSafe {
// It is only used by unit tests.
void EraseEntryForTests(const GURL& url);
- void InitializeOptions(bool enforce_throttling);
+ // Turns threading model verification on or off. Any code that correctly
+ // uses the network stack should preferably call this function to enable
+ // verification of correct adherence to the network stack threading model.
+ void set_enable_thread_checks(bool enable);
+ bool enable_thread_checks() const;
- bool enforce_throttling() const { return enforce_throttling_; }
+ // Whether throttling is enabled or not.
+ void set_enforce_throttling(bool enforce);
+ bool enforce_throttling();
protected:
URLRequestThrottlerManager();
@@ -113,7 +119,7 @@ class URLRequestThrottlerManager : public base::NonThreadSafe {
//
// TODO(joi): See if we can fix the offending unit tests and remove this
// workaround.
- bool being_tested_;
+ bool enable_thread_checks_;
DISALLOW_COPY_AND_ASSIGN(URLRequestThrottlerManager);
};
diff --git a/net/url_request/url_request_throttler_unittest.cc b/net/url_request/url_request_throttler_unittest.cc
index 5ca56b9..9e33587 100644
--- a/net/url_request/url_request_throttler_unittest.cc
+++ b/net/url_request/url_request_throttler_unittest.cc
@@ -33,7 +33,7 @@ class MockBackoffEntry : public BackoffEntry {
return fake_now_;
}
- void SetFakeNow(TimeTicks now) {
+ void SetFakeNow(const TimeTicks& now) {
fake_now_ = now;
}