OLD | NEW |
| (Empty) |
1 // Copyright 2014 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 "components/cronet/android/url_request_context_adapter.h" | |
6 | |
7 #include <stddef.h> | |
8 #include <stdint.h> | |
9 | |
10 #include <limits> | |
11 #include <utility> | |
12 | |
13 #include "base/bind.h" | |
14 #include "base/files/file_util.h" | |
15 #include "base/files/scoped_file.h" | |
16 #include "base/lazy_instance.h" | |
17 #include "base/macros.h" | |
18 #include "base/memory/ptr_util.h" | |
19 #include "base/message_loop/message_loop.h" | |
20 #include "base/single_thread_task_runner.h" | |
21 #include "base/time/time.h" | |
22 #include "components/cronet/url_request_context_config.h" | |
23 #include "net/android/network_change_notifier_factory_android.h" | |
24 #include "net/base/net_errors.h" | |
25 #include "net/base/network_change_notifier.h" | |
26 #include "net/base/network_delegate_impl.h" | |
27 #include "net/base/url_util.h" | |
28 #include "net/cert/cert_verifier.h" | |
29 #include "net/http/http_auth_handler_factory.h" | |
30 #include "net/http/http_network_layer.h" | |
31 #include "net/http/http_server_properties.h" | |
32 #include "net/log/write_to_file_net_log_observer.h" | |
33 #include "net/proxy/proxy_service.h" | |
34 #include "net/sdch/sdch_owner.h" | |
35 #include "net/ssl/ssl_config_service_defaults.h" | |
36 #include "net/url_request/static_http_user_agent_settings.h" | |
37 #include "net/url_request/url_request_context_builder.h" | |
38 #include "net/url_request/url_request_context_storage.h" | |
39 #include "net/url_request/url_request_job_factory_impl.h" | |
40 #include "url/scheme_host_port.h" | |
41 | |
42 namespace { | |
43 | |
44 // Use a global NetLog instance. See crbug.com/486120. | |
45 static base::LazyInstance<net::NetLog>::Leaky g_net_log = | |
46 LAZY_INSTANCE_INITIALIZER; | |
47 | |
48 class BasicNetworkDelegate : public net::NetworkDelegateImpl { | |
49 public: | |
50 BasicNetworkDelegate() {} | |
51 ~BasicNetworkDelegate() override {} | |
52 | |
53 private: | |
54 // net::NetworkDelegate implementation. | |
55 int OnBeforeURLRequest(net::URLRequest* request, | |
56 const net::CompletionCallback& callback, | |
57 GURL* new_url) override { | |
58 return net::OK; | |
59 } | |
60 | |
61 int OnBeforeStartTransaction(net::URLRequest* request, | |
62 const net::CompletionCallback& callback, | |
63 net::HttpRequestHeaders* headers) override { | |
64 return net::OK; | |
65 } | |
66 | |
67 void OnStartTransaction(net::URLRequest* request, | |
68 const net::HttpRequestHeaders& headers) override {} | |
69 | |
70 int OnHeadersReceived( | |
71 net::URLRequest* request, | |
72 const net::CompletionCallback& callback, | |
73 const net::HttpResponseHeaders* original_response_headers, | |
74 scoped_refptr<net::HttpResponseHeaders>* _response_headers, | |
75 GURL* allowed_unsafe_redirect_url) override { | |
76 return net::OK; | |
77 } | |
78 | |
79 void OnBeforeRedirect(net::URLRequest* request, | |
80 const GURL& new_location) override {} | |
81 | |
82 void OnResponseStarted(net::URLRequest* request, int net_error) override {} | |
83 | |
84 void OnCompleted(net::URLRequest* request, | |
85 bool started, | |
86 int net_error) override {} | |
87 | |
88 void OnURLRequestDestroyed(net::URLRequest* request) override {} | |
89 | |
90 void OnPACScriptError(int line_number, | |
91 const base::string16& error) override {} | |
92 | |
93 NetworkDelegate::AuthRequiredResponse OnAuthRequired( | |
94 net::URLRequest* request, | |
95 const net::AuthChallengeInfo& auth_info, | |
96 const AuthCallback& callback, | |
97 net::AuthCredentials* credentials) override { | |
98 return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION; | |
99 } | |
100 | |
101 bool OnCanGetCookies(const net::URLRequest& request, | |
102 const net::CookieList& cookie_list) override { | |
103 return false; | |
104 } | |
105 | |
106 bool OnCanSetCookie(const net::URLRequest& request, | |
107 const std::string& cookie_line, | |
108 net::CookieOptions* options) override { | |
109 return false; | |
110 } | |
111 | |
112 bool OnCanAccessFile(const net::URLRequest& request, | |
113 const base::FilePath& path) const override { | |
114 return false; | |
115 } | |
116 | |
117 DISALLOW_COPY_AND_ASSIGN(BasicNetworkDelegate); | |
118 }; | |
119 | |
120 } // namespace | |
121 | |
122 namespace cronet { | |
123 | |
124 URLRequestContextAdapter::URLRequestContextAdapter( | |
125 URLRequestContextAdapterDelegate* delegate, | |
126 std::string user_agent) | |
127 : load_disable_cache_(true), | |
128 is_context_initialized_(false) { | |
129 delegate_ = delegate; | |
130 user_agent_ = user_agent; | |
131 } | |
132 | |
133 void URLRequestContextAdapter::Initialize( | |
134 std::unique_ptr<URLRequestContextConfig> config) { | |
135 network_thread_ = new base::Thread("network"); | |
136 base::Thread::Options options; | |
137 options.message_loop_type = base::MessageLoop::TYPE_IO; | |
138 network_thread_->StartWithOptions(options); | |
139 config_ = std::move(config); | |
140 } | |
141 | |
142 void URLRequestContextAdapter::InitRequestContextOnMainThread() { | |
143 proxy_config_service_ = net::ProxyService::CreateSystemProxyConfigService( | |
144 GetNetworkTaskRunner(), NULL); | |
145 GetNetworkTaskRunner()->PostTask( | |
146 FROM_HERE, | |
147 base::Bind(&URLRequestContextAdapter::InitRequestContextOnNetworkThread, | |
148 this)); | |
149 } | |
150 | |
151 void URLRequestContextAdapter::InitRequestContextOnNetworkThread() { | |
152 DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread()); | |
153 DCHECK(config_); | |
154 // TODO(mmenke): Add method to have the builder enable SPDY. | |
155 net::URLRequestContextBuilder context_builder; | |
156 | |
157 context_builder.set_network_delegate( | |
158 base::MakeUnique<BasicNetworkDelegate>()); | |
159 context_builder.set_proxy_config_service(std::move(proxy_config_service_)); | |
160 config_->ConfigureURLRequestContextBuilder(&context_builder, | |
161 g_net_log.Pointer(), nullptr); | |
162 | |
163 context_ = context_builder.Build(); | |
164 | |
165 if (config_->enable_sdch) { | |
166 DCHECK(context_->sdch_manager()); | |
167 sdch_owner_.reset( | |
168 new net::SdchOwner(context_->sdch_manager(), context_.get())); | |
169 } | |
170 | |
171 if (config_->enable_quic) { | |
172 for (size_t hint = 0; hint < config_->quic_hints.size(); ++hint) { | |
173 const URLRequestContextConfig::QuicHint& quic_hint = | |
174 *config_->quic_hints[hint]; | |
175 if (quic_hint.host.empty()) { | |
176 LOG(ERROR) << "Empty QUIC hint host: " << quic_hint.host; | |
177 continue; | |
178 } | |
179 | |
180 url::CanonHostInfo host_info; | |
181 std::string canon_host(net::CanonicalizeHost(quic_hint.host, &host_info)); | |
182 if (!host_info.IsIPAddress() && | |
183 !net::IsCanonicalizedHostCompliant(canon_host)) { | |
184 LOG(ERROR) << "Invalid QUIC hint host: " << quic_hint.host; | |
185 continue; | |
186 } | |
187 | |
188 if (quic_hint.port <= std::numeric_limits<uint16_t>::min() || | |
189 quic_hint.port > std::numeric_limits<uint16_t>::max()) { | |
190 LOG(ERROR) << "Invalid QUIC hint port: " | |
191 << quic_hint.port; | |
192 continue; | |
193 } | |
194 | |
195 if (quic_hint.alternate_port <= std::numeric_limits<uint16_t>::min() || | |
196 quic_hint.alternate_port > std::numeric_limits<uint16_t>::max()) { | |
197 LOG(ERROR) << "Invalid QUIC hint alternate port: " | |
198 << quic_hint.alternate_port; | |
199 continue; | |
200 } | |
201 | |
202 url::SchemeHostPort quic_server("https", canon_host, quic_hint.port); | |
203 net::AlternativeService alternative_service( | |
204 net::AlternateProtocol::QUIC, "", | |
205 static_cast<uint16_t>(quic_hint.alternate_port)); | |
206 context_->http_server_properties()->SetAlternativeService( | |
207 quic_server, alternative_service, base::Time::Max()); | |
208 } | |
209 } | |
210 load_disable_cache_ = config_->load_disable_cache; | |
211 config_.reset(NULL); | |
212 | |
213 if (VLOG_IS_ON(2)) { | |
214 net_log_observer_.reset(new NetLogObserver()); | |
215 context_->net_log()->DeprecatedAddObserver( | |
216 net_log_observer_.get(), | |
217 net::NetLogCaptureMode::IncludeCookiesAndCredentials()); | |
218 } | |
219 | |
220 is_context_initialized_ = true; | |
221 while (!tasks_waiting_for_context_.empty()) { | |
222 tasks_waiting_for_context_.front().Run(); | |
223 tasks_waiting_for_context_.pop(); | |
224 } | |
225 | |
226 delegate_->OnContextInitialized(this); | |
227 } | |
228 | |
229 void URLRequestContextAdapter::PostTaskToNetworkThread( | |
230 const tracked_objects::Location& posted_from, | |
231 const RunAfterContextInitTask& callback) { | |
232 GetNetworkTaskRunner()->PostTask( | |
233 posted_from, | |
234 base::Bind( | |
235 &URLRequestContextAdapter::RunTaskAfterContextInitOnNetworkThread, | |
236 this, | |
237 callback)); | |
238 } | |
239 | |
240 void URLRequestContextAdapter::RunTaskAfterContextInitOnNetworkThread( | |
241 const RunAfterContextInitTask& callback) { | |
242 DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread()); | |
243 if (is_context_initialized_) { | |
244 callback.Run(); | |
245 return; | |
246 } | |
247 tasks_waiting_for_context_.push(callback); | |
248 } | |
249 | |
250 URLRequestContextAdapter::~URLRequestContextAdapter() { | |
251 DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread()); | |
252 if (net_log_observer_) { | |
253 context_->net_log()->DeprecatedRemoveObserver(net_log_observer_.get()); | |
254 net_log_observer_.reset(); | |
255 } | |
256 StopNetLogHelper(); | |
257 // TODO(mef): Ensure that |network_thread_| is destroyed properly. | |
258 } | |
259 | |
260 const std::string& URLRequestContextAdapter::GetUserAgent( | |
261 const GURL& url) const { | |
262 return user_agent_; | |
263 } | |
264 | |
265 net::URLRequestContext* URLRequestContextAdapter::GetURLRequestContext() { | |
266 DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread()); | |
267 if (!context_) { | |
268 LOG(ERROR) << "URLRequestContext is not set up"; | |
269 } | |
270 return context_.get(); | |
271 } | |
272 | |
273 scoped_refptr<base::SingleThreadTaskRunner> | |
274 URLRequestContextAdapter::GetNetworkTaskRunner() const { | |
275 return network_thread_->task_runner(); | |
276 } | |
277 | |
278 void URLRequestContextAdapter::StartNetLogToFile(const std::string& file_name, | |
279 bool log_all) { | |
280 PostTaskToNetworkThread( | |
281 FROM_HERE, | |
282 base::Bind(&URLRequestContextAdapter::StartNetLogToFileHelper, this, | |
283 file_name, log_all)); | |
284 } | |
285 | |
286 void URLRequestContextAdapter::StopNetLog() { | |
287 PostTaskToNetworkThread( | |
288 FROM_HERE, base::Bind(&URLRequestContextAdapter::StopNetLogHelper, this)); | |
289 } | |
290 | |
291 void URLRequestContextAdapter::StartNetLogToFileHelper( | |
292 const std::string& file_name, bool log_all) { | |
293 DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread()); | |
294 // Do nothing if already logging to a file. | |
295 if (write_to_file_observer_) | |
296 return; | |
297 | |
298 base::FilePath file_path(file_name); | |
299 base::ScopedFILE file(base::OpenFile(file_path, "w")); | |
300 if (!file) | |
301 return; | |
302 | |
303 write_to_file_observer_.reset(new net::WriteToFileNetLogObserver()); | |
304 if (log_all) { | |
305 write_to_file_observer_->set_capture_mode( | |
306 net::NetLogCaptureMode::IncludeSocketBytes()); | |
307 } | |
308 write_to_file_observer_->StartObserving(context_->net_log(), std::move(file), | |
309 nullptr, context_.get()); | |
310 } | |
311 | |
312 void URLRequestContextAdapter::StopNetLogHelper() { | |
313 DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread()); | |
314 if (write_to_file_observer_) { | |
315 write_to_file_observer_->StopObserving(context_.get()); | |
316 write_to_file_observer_.reset(); | |
317 } | |
318 } | |
319 | |
320 void NetLogObserver::OnAddEntry(const net::NetLog::Entry& entry) { | |
321 VLOG(2) << "Net log entry: type=" << static_cast<int>(entry.type()) | |
322 << ", source=" << static_cast<int>(entry.source().type) | |
323 << ", phase=" << static_cast<int>(entry.phase()); | |
324 } | |
325 | |
326 } // namespace cronet | |
OLD | NEW |