blob: 2ea8195c784bfc2b571b1f6d560f0f3fe97ecd3e [file] [log] [blame]
[email protected]0ac83682010-01-22 17:46:271// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/io_thread.h"
6#include "base/command_line.h"
7#include "base/leak_tracker.h"
8#include "base/logging.h"
9#include "chrome/browser/browser_process.h"
10#include "chrome/browser/chrome_thread.h"
[email protected]9e743cd2010-03-16 07:03:5311#include "chrome/browser/net/chrome_net_log.h"
[email protected]0ac83682010-01-22 17:46:2712#include "chrome/browser/net/dns_global.h"
[email protected]9e743cd2010-03-16 07:03:5313#include "chrome/browser/net/passive_log_collector.h"
[email protected]0ac83682010-01-22 17:46:2714#include "chrome/browser/net/url_fetcher.h"
15#include "chrome/common/chrome_switches.h"
[email protected]9087aa32010-02-18 08:03:3816#include "net/base/mapped_host_resolver.h"
[email protected]0ac83682010-01-22 17:46:2717#include "net/base/host_cache.h"
18#include "net/base/host_resolver.h"
[email protected]f2d8c4212010-02-02 00:56:3519#include "net/base/host_resolver_impl.h"
[email protected]32eaa332010-02-08 22:15:5420#include "net/base/net_util.h"
[email protected]d13c3272010-02-04 00:24:5121#include "net/base/network_change_notifier.h"
[email protected]eb3cac72010-02-26 21:07:4522#include "net/http/http_auth_filter.h"
[email protected]fa55e192010-02-15 14:25:5023#include "net/http/http_auth_handler_factory.h"
[email protected]0ac83682010-01-22 17:46:2724#include "net/url_request/url_request.h"
25
26namespace {
27
[email protected]d13c3272010-02-04 00:24:5128net::HostResolver* CreateGlobalHostResolver(
29 net::NetworkChangeNotifier* network_change_notifier) {
[email protected]46f6e202010-02-26 06:07:2530 net::HostResolver* global_host_resolver = NULL;
31
[email protected]0ac83682010-01-22 17:46:2732 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
[email protected]46f6e202010-02-26 06:07:2533
34 global_host_resolver =
[email protected]9087aa32010-02-18 08:03:3835 net::CreateSystemHostResolver(network_change_notifier);
36
37 if (!command_line.HasSwitch(switches::kEnableIPv6)) {
[email protected]46f6e202010-02-26 06:07:2538 // Measure impact of allowing IPv6 support without probing.
39 const FieldTrial::Probability kDivisor = 100;
40 const FieldTrial::Probability kProbability = 50; // 50% probability.
41 FieldTrial* trial = new FieldTrial("IPv6_Probe", kDivisor);
42 int skip_group = trial->AppendGroup("_IPv6_probe_skipped", kProbability);
43 trial->AppendGroup("_IPv6_probe_done",
44 FieldTrial::kAllRemainingProbability);
45 bool use_ipv6_probe = (trial->group() != skip_group);
[email protected]7be4c7ee2010-02-26 05:33:4546
[email protected]46f6e202010-02-26 06:07:2547 // Perform probe, and then optionally use result to disable IPv6.
48 // Some users report confused OS handling of IPv6, leading to large
49 // latency. If we can show that IPv6 is not supported, then disabliing it
50 // will work around such problems.
51 if ((!net::IPv6Supported() && use_ipv6_probe) ||
52 command_line.HasSwitch(switches::kDisableIPv6))
53 global_host_resolver->SetDefaultAddressFamily(net::ADDRESS_FAMILY_IPV4);
[email protected]9087aa32010-02-18 08:03:3854 }
55
[email protected]9087aa32010-02-18 08:03:3856 // If hostname remappings were specified on the command-line, layer these
57 // rules on top of the real host resolver. This allows forwarding all requests
58 // through a designated test server.
[email protected]46f6e202010-02-26 06:07:2559 if (command_line.HasSwitch(switches::kHostResolverRules)) {
60 net::MappedHostResolver* remapped_resolver =
61 new net::MappedHostResolver(global_host_resolver);
62 global_host_resolver = remapped_resolver;
63 remapped_resolver->SetRulesFromString(
64 command_line.GetSwitchValueASCII(switches::kHostResolverRules));
65 }
[email protected]0ac83682010-01-22 17:46:2766
[email protected]46f6e202010-02-26 06:07:2567 return global_host_resolver;
[email protected]0ac83682010-01-22 17:46:2768}
69
70} // namespace
71
72// The IOThread object must outlive any tasks posted to the IO thread before the
73// Quit task.
74template <>
75struct RunnableMethodTraits<IOThread> {
76 void RetainCallee(IOThread* /* io_thread */) {}
77 void ReleaseCallee(IOThread* /* io_thread */) {}
78};
79
80IOThread::IOThread()
81 : BrowserProcessSubThread(ChromeThread::IO),
[email protected]d13c3272010-02-04 00:24:5182 globals_(NULL),
[email protected]0ac83682010-01-22 17:46:2783 prefetch_observer_(NULL),
84 dns_master_(NULL) {}
85
86IOThread::~IOThread() {
87 // We cannot rely on our base class to stop the thread since we want our
88 // CleanUp function to run.
89 Stop();
[email protected]d13c3272010-02-04 00:24:5190 DCHECK(!globals_);
[email protected]0ac83682010-01-22 17:46:2791}
92
[email protected]d13c3272010-02-04 00:24:5193IOThread::Globals* IOThread::globals() {
[email protected]0ac83682010-01-22 17:46:2794 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
[email protected]d13c3272010-02-04 00:24:5195 return globals_;
[email protected]0ac83682010-01-22 17:46:2796}
97
98void IOThread::InitDnsMaster(
99 bool prefetching_enabled,
100 base::TimeDelta max_queue_delay,
101 size_t max_concurrent,
102 const chrome_common_net::NameList& hostnames_to_prefetch,
103 ListValue* referral_list) {
104 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
105 message_loop()->PostTask(
106 FROM_HERE,
107 NewRunnableMethod(
108 this,
109 &IOThread::InitDnsMasterOnIOThread,
110 prefetching_enabled, max_queue_delay, max_concurrent,
111 hostnames_to_prefetch, referral_list));
112}
113
114void IOThread::ChangedToOnTheRecord() {
115 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
116 message_loop()->PostTask(
117 FROM_HERE,
118 NewRunnableMethod(
119 this,
120 &IOThread::ChangedToOnTheRecordOnIOThread));
121}
122
123void IOThread::Init() {
124 BrowserProcessSubThread::Init();
125
[email protected]d13c3272010-02-04 00:24:51126 DCHECK(!globals_);
127 globals_ = new Globals;
128
[email protected]9e743cd2010-03-16 07:03:53129 globals_->net_log.reset(new ChromeNetLog());
[email protected]d13c3272010-02-04 00:24:51130 globals_->network_change_notifier.reset(
131 net::NetworkChangeNotifier::CreateDefaultNetworkChangeNotifier());
132 globals_->host_resolver =
133 CreateGlobalHostResolver(globals_->network_change_notifier.get());
[email protected]eb3cac72010-02-26 21:07:45134 globals_->http_auth_handler_factory.reset(CreateDefaultAuthHandlerFactory());
[email protected]0ac83682010-01-22 17:46:27135}
136
137void IOThread::CleanUp() {
138 // Not initialized in Init(). May not be initialized.
139 if (dns_master_) {
140 DCHECK(prefetch_observer_);
141
142 dns_master_->Shutdown();
143
144 // TODO(willchan): Stop reference counting DnsMaster. It's owned by
145 // IOThread now.
146 dns_master_->Release();
147 dns_master_ = NULL;
148 chrome_browser_net::FreeDnsPrefetchResources();
149 }
150
151 // Not initialized in Init(). May not be initialized.
152 if (prefetch_observer_) {
[email protected]d13c3272010-02-04 00:24:51153 globals_->host_resolver->RemoveObserver(prefetch_observer_);
[email protected]0ac83682010-01-22 17:46:27154 delete prefetch_observer_;
155 prefetch_observer_ = NULL;
156 }
157
[email protected]e4d2dd822010-02-05 20:57:33158 // TODO(eroman): hack for http://crbug.com/15513
[email protected]970210c2010-02-19 20:27:02159 if (globals_->host_resolver->GetAsHostResolverImpl()) {
160 globals_->host_resolver.get()->GetAsHostResolverImpl()->Shutdown();
[email protected]e4d2dd822010-02-05 20:57:33161 }
[email protected]0ac83682010-01-22 17:46:27162
[email protected]d13c3272010-02-04 00:24:51163 delete globals_;
164 globals_ = NULL;
[email protected]0ac83682010-01-22 17:46:27165
166 // URLFetcher and URLRequest instances must NOT outlive the IO thread.
167 //
168 // Strictly speaking, URLFetcher's CheckForLeaks() should be done on the
169 // UI thread. However, since there _shouldn't_ be any instances left
170 // at this point, it shouldn't be a race.
171 //
172 // We check URLFetcher first, since if it has leaked then an associated
173 // URLRequest will also have leaked. However it is more useful to
174 // crash showing the callstack of URLFetcher's allocation than its
175 // URLRequest member.
176 base::LeakTracker<URLFetcher>::CheckForLeaks();
177 base::LeakTracker<URLRequest>::CheckForLeaks();
178
179 BrowserProcessSubThread::CleanUp();
180}
181
[email protected]eb3cac72010-02-26 21:07:45182net::HttpAuthHandlerFactory* IOThread::CreateDefaultAuthHandlerFactory() {
183 net::HttpAuthHandlerRegistryFactory* registry_factory =
184 net::HttpAuthHandlerFactory::CreateDefault();
185
186 // Get the whitelist information from the command line, create an
187 // HttpAuthFilterWhitelist, and attach it to the HttpAuthHandlerFactory.
188 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
189
190 // Set the NTLM and Negotiate filters (from the same whitelist)
191 if (command_line.HasSwitch(switches::kAuthServerWhitelist)) {
192 std::string ntlm_server_whitelist =
193 command_line.GetSwitchValueASCII(switches::kAuthServerWhitelist);
194 net::HttpAuthFilterWhitelist* ntlm_whitelist =
195 new net::HttpAuthFilterWhitelist();
196 net::HttpAuthFilterWhitelist* negotiate_whitelist =
197 new net::HttpAuthFilterWhitelist();
198
199 ntlm_whitelist->SetFilters(ntlm_server_whitelist);
200 negotiate_whitelist->SetFilters(ntlm_server_whitelist);
201 registry_factory->SetFilter("ntlm", ntlm_whitelist);
202 registry_factory->SetFilter("negotiate", negotiate_whitelist);
203 }
204
205 return registry_factory;
206}
207
[email protected]0ac83682010-01-22 17:46:27208void IOThread::InitDnsMasterOnIOThread(
209 bool prefetching_enabled,
210 base::TimeDelta max_queue_delay,
211 size_t max_concurrent,
212 chrome_common_net::NameList hostnames_to_prefetch,
213 ListValue* referral_list) {
214 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
215 CHECK(!dns_master_);
216
217 chrome_browser_net::EnableDnsPrefetch(prefetching_enabled);
218
219 dns_master_ = new chrome_browser_net::DnsMaster(
[email protected]d13c3272010-02-04 00:24:51220 globals_->host_resolver, max_queue_delay, max_concurrent);
[email protected]0ac83682010-01-22 17:46:27221 dns_master_->AddRef();
222
223 DCHECK(!prefetch_observer_);
224 prefetch_observer_ = chrome_browser_net::CreatePrefetchObserver();
[email protected]d13c3272010-02-04 00:24:51225 globals_->host_resolver->AddObserver(prefetch_observer_);
[email protected]0ac83682010-01-22 17:46:27226
227 FinalizeDnsPrefetchInitialization(
228 dns_master_, prefetch_observer_, hostnames_to_prefetch, referral_list);
229}
230
231void IOThread::ChangedToOnTheRecordOnIOThread() {
232 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
233
234 if (dns_master_) {
235 // Destroy all evidence of our OTR session.
236 dns_master_->DnsMaster::DiscardAllResults();
237 }
238
239 // Clear the host cache to avoid showing entries from the OTR session
240 // in about:net-internals.
[email protected]970210c2010-02-19 20:27:02241 if (globals_->host_resolver->GetAsHostResolverImpl()) {
242 net::HostCache* host_cache =
243 globals_->host_resolver.get()->GetAsHostResolverImpl()->cache();
[email protected]f2d8c4212010-02-02 00:56:35244 if (host_cache)
245 host_cache->clear();
246 }
[email protected]9e743cd2010-03-16 07:03:53247 // Clear all of the passively logged data.
248 // TODO(eroman): this is a bit heavy handed, really all we need to do is
249 // clear the data pertaining to off the record context.
250 globals_->net_log->passive_collector()->Clear();
[email protected]0ac83682010-01-22 17:46:27251}