Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(42)

Side by Side Diff: components/cronet/ios/cronet_environment.cc

Issue 1858483002: Cronet for iOS with C API for GRPC support. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@small
Patch Set: Use LazyInitializer, wait for stopLogOnNetworkThread. Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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/ios/cronet_environment.h"
6
7 #include <utility>
8
9 #include "base/at_exit.h"
10 #include "base/atomicops.h"
11 #include "base/command_line.h"
12 #include "base/files/file_path.h"
13 #include "base/files/file_util.h"
14 #include "base/files/scoped_file.h"
15 #include "base/json/json_writer.h"
16 #include "base/mac/bind_objc_block.h"
17 #include "base/mac/foundation_util.h"
18 #include "base/mac/scoped_block.h"
xunjieli 2016/04/13 15:28:24 Not used?
mef 2016/04/14 14:07:24 Done.
19 #include "base/macros.h"
20 #include "base/metrics/statistics_recorder.h"
21 #include "base/path_service.h"
22 #include "base/synchronization/waitable_event.h"
23 #include "base/threading/worker_pool.h"
24 #include "components/cronet/version.h"
25 #include "components/prefs/json_pref_store.h"
26 #include "components/prefs/pref_filter.h"
27 #include "net/base/net_errors.h"
28 #include "net/base/network_change_notifier.h"
29 #include "net/base/sdch_manager.h"
xunjieli 2016/04/13 15:28:24 Not used?
mef 2016/04/14 14:07:24 Done.
30 #include "net/cert/cert_verify_result.h"
31 #include "net/dns/host_resolver.h"
32 #include "net/dns/mapped_host_resolver.h"
33 #include "net/http/http_auth_handler_factory.h"
34 #include "net/http/http_cache.h"
35 #include "net/http/http_response_headers.h"
36 #include "net/http/http_server_properties_impl.h"
37 #include "net/http/http_stream_factory.h"
38 #include "net/http/http_util.h"
39 #include "net/log/net_log.h"
40 #include "net/log/write_to_file_net_log_observer.h"
41 #include "net/proxy/proxy_service.h"
42 #include "net/sdch/sdch_owner.h"
xunjieli 2016/04/13 15:28:24 Not used?
mef 2016/04/14 14:07:24 Done.
43 #include "net/socket/ssl_client_socket.h"
44 #include "net/ssl/channel_id_service.h"
45 #include "net/ssl/default_channel_id_store.h"
46 #include "net/ssl/ssl_config_service_defaults.h"
47 #include "net/url_request/static_http_user_agent_settings.h"
48 #include "net/url_request/url_request_context_storage.h"
49 #include "net/url_request/url_request_job_factory_impl.h"
50 #include "url/url_util.h"
51
52 namespace {
53
54 base::AtExitManager* g_at_exit_ = nullptr;
55 net::NetworkChangeNotifier* g_network_change_notifier = nullptr;
56 // MessageLoop on the main thread.
57 base::MessageLoop* g_main_message_loop = nullptr;
58
59 #if USE_FAKE_CERT_VERIFIER
60 // TODO(mef): Remove this after GRPC testing is done.
61 class FakeCertVerifier : public net::CertVerifier {
62 public:
63 FakeCertVerifier() {}
64
65 ~FakeCertVerifier() override {}
66
67 // CertVerifier implementation
68 int Verify(net::X509Certificate* cert,
69 const std::string& hostname,
70 const std::string& ocsp_response,
71 int flags,
72 net::CRLSet* crl_set,
73 net::CertVerifyResult* verify_result,
74 const net::CompletionCallback& callback,
75 scoped_ptr<Request>* out_req,
76 const net::BoundNetLog& net_log) override {
77 // It's all good!
78 verify_result->verified_cert = cert;
79 verify_result->cert_status = MapNetErrorToCertStatus(net::OK);
80 return net::OK;
81 }
82 };
83 #endif // USE_FAKE_CERT_VERIFIER
84
85 } // namespace
86
87 namespace cronet {
88
89 bool CronetEnvironment::IsOnNetworkThread() {
90 return network_io_thread_->task_runner()->BelongsToCurrentThread();
91 }
92
93 void CronetEnvironment::PostToNetworkThread(
94 const tracked_objects::Location& from_here,
95 const base::Closure& task) {
96 network_io_thread_->task_runner()->PostTask(from_here, task);
97 }
98
99 void CronetEnvironment::PostToFileUserBlockingThread(
100 const tracked_objects::Location& from_here,
101 const base::Closure& task) {
102 file_user_blocking_thread_->message_loop()->PostTask(from_here, task);
103 }
104
105 net::URLRequestContext* CronetEnvironment::GetURLRequestContext() const {
106 return main_context_.get();
107 }
108
109 // static
110 void CronetEnvironment::Initialize() {
111 // DCHECK_EQ([NSThread currentThread], [NSThread mainThread]);
112 // This method must be called once from the main thread.
113 if (!g_at_exit_)
114 g_at_exit_ = new base::AtExitManager;
115
116 url::Initialize();
117 base::CommandLine::Init(0, nullptr);
xunjieli 2016/04/13 15:28:24 Why do we call base::CommandLine?
mef 2016/04/14 14:07:24 I don't really know. It was this way in CrNet.
118
119 // Without doing this, StatisticsRecorder::FactoryGet() leaks one histogram
120 // per call after the first for a given name.
121 base::StatisticsRecorder::Initialize();
122
123 // Create a message loop on the UI thread.
124 DCHECK(!base::MessageLoop::current());
125 DCHECK(!g_main_message_loop);
126 g_main_message_loop = new base::MessageLoopForUI();
127 base::MessageLoopForUI::current()->Attach();
128 // The network change notifier must be initialized so that registered
129 // delegates will receive callbacks.
130 DCHECK(!g_network_change_notifier);
131 g_network_change_notifier = net::NetworkChangeNotifier::Create();
132 }
133
134 void CronetEnvironment::StartNetLog(base::FilePath::StringType file_name,
135 bool log_bytes) {
136 DCHECK(file_name.length());
137 PostToNetworkThread(FROM_HERE,
138 base::Bind(&CronetEnvironment::StartNetLogOnNetworkThread,
139 base::Unretained(this), file_name, log_bytes));
140 }
141
142 void CronetEnvironment::StartNetLogOnNetworkThread(
143 const base::FilePath::StringType& file_name,
144 bool log_bytes) {
145 DCHECK(file_name.length());
146 DCHECK(net_log_);
147
148 if (net_log_observer_)
149 return;
150
151 base::FilePath files_root;
152 if (!PathService::Get(base::DIR_HOME, &files_root))
153 return;
154
155 base::FilePath full_path = files_root.Append(file_name);
156 base::ScopedFILE file(base::OpenFile(full_path, "w"));
157 if (!file) {
158 LOG(ERROR) << "Can not start NetLog to " << full_path.value();
159 return;
160 }
161
162 net::NetLogCaptureMode capture_mode =
163 log_bytes ? net::NetLogCaptureMode::IncludeSocketBytes()
164 : net::NetLogCaptureMode::Default();
165
166 net_log_observer_.reset(new net::WriteToFileNetLogObserver());
167 net_log_observer_->set_capture_mode(capture_mode);
168 net_log_observer_->StartObserving(main_context_->net_log(), std::move(file),
169 nullptr, main_context_.get());
170 LOG(WARNING) << "Started NetLog to " << full_path.value();
171 }
172
173 void CronetEnvironment::StopNetLog() {
174 base::WaitableEvent log_stopped_event(true, false);
175 PostToNetworkThread(FROM_HERE,
176 base::Bind(&CronetEnvironment::StopNetLogOnNetworkThread,
177 base::Unretained(this), &log_stopped_event));
178 log_stopped_event.Wait();
179 }
180
181 void CronetEnvironment::StopNetLogOnNetworkThread(
182 base::WaitableEvent* log_stopped_event) {
183 if (net_log_observer_) {
184 DLOG(WARNING) << "Stopped NetLog.";
185 net_log_observer_->StopObserving(main_context_.get());
186 net_log_observer_.reset();
187 }
188 log_stopped_event->Signal();
189 }
190
191 net::HttpNetworkSession* CronetEnvironment::GetHttpNetworkSession(
192 net::URLRequestContext* context) {
193 DCHECK(context);
194 if (!context->http_transaction_factory())
195 return nullptr;
196
197 return context->http_transaction_factory()->GetSession();
198 }
199
200 void CronetEnvironment::AddQuicHint(const std::string& host,
201 int port,
202 int alternate_port) {
203 DCHECK(port == alternate_port);
204 quic_hints_.push_back(net::HostPortPair(host, port));
205 }
206
207 CronetEnvironment::CronetEnvironment(const std::string& user_agent_product_name)
208 : http2_enabled_(false),
209 quic_enabled_(false),
210 user_agent_product_name_(user_agent_product_name),
211 net_log_(new net::NetLog) {}
212
213 void CronetEnvironment::Install() {
214 #if USE_FAKE_CERT_VERIFIER
215 // TODO(mef): Remove this and FakeCertVerifier after GRPC testing.
216 set_cert_verifier(scoped_ptr<net::CertVerifier>(new FakeCertVerifier()));
217 #endif // USE_FAKE_CERT_VERIFIER
218
219 // Threads setup.
220 network_cache_thread_.reset(new base::Thread("Chrome Network Cache Thread"));
221 network_cache_thread_->StartWithOptions(
222 base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
223 network_io_thread_.reset(new base::Thread("Chrome Network IO Thread"));
224 network_io_thread_->StartWithOptions(
225 base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
226 file_thread_.reset(new base::Thread("Chrome File Thread"));
227 file_thread_->StartWithOptions(
228 base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
229 file_user_blocking_thread_.reset(
230 new base::Thread("Chrome File User Blocking Thread"));
231 file_user_blocking_thread_->StartWithOptions(
232 base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
233
234 static bool ssl_key_log_file_set = false;
235 if (!ssl_key_log_file_set && !ssl_key_log_file_name_.empty()) {
236 ssl_key_log_file_set = true;
237 base::FilePath ssl_key_log_file;
238 if (!PathService::Get(base::DIR_HOME, &ssl_key_log_file))
239 return;
240 net::SSLClientSocket::SetSSLKeyLogFile(
241 ssl_key_log_file.Append(ssl_key_log_file_name_),
242 file_thread_->task_runner());
243 }
244
245 proxy_config_service_ = net::ProxyService::CreateSystemProxyConfigService(
246 network_io_thread_->task_runner(), nullptr);
247
248 #if defined(USE_NSS_VERIFIER)
249 net::SetURLRequestContextForNSSHttpIO(main_context_.get());
250 #endif
251 base::subtle::MemoryBarrier();
252 PostToNetworkThread(FROM_HERE,
253 base::Bind(&CronetEnvironment::InitializeOnNetworkThread,
254 base::Unretained(this)));
255 }
256
257 CronetEnvironment::~CronetEnvironment() {
258 // net::HTTPProtocolHandlerDelegate::SetInstance(nullptr);
259 #if defined(USE_NSS_VERIFIER)
260 net::SetURLRequestContextForNSSHttpIO(nullptr);
261 #endif
262 }
263
264 void CronetEnvironment::InitializeOnNetworkThread() {
265 DCHECK(network_io_thread_->task_runner()->BelongsToCurrentThread());
266 main_context_.reset(new net::URLRequestContext);
267 main_context_->set_net_log(net_log_.get());
268 std::string user_agent(user_agent_product_name_ +
269 " (iOS); Cronet/" CRONET_VERSION);
270 main_context_->set_http_user_agent_settings(
271 new net::StaticHttpUserAgentSettings("en", user_agent));
272
273 main_context_->set_ssl_config_service(new net::SSLConfigServiceDefaults);
274 main_context_->set_transport_security_state(
275 new net::TransportSecurityState());
276 http_server_properties_.reset(new net::HttpServerPropertiesImpl());
277 main_context_->set_http_server_properties(
278 http_server_properties_->GetWeakPtr());
279
280 // TODO(rdsmith): Note that the ".release()" calls below are leaking
281 // the objects in question; this should be fixed by having an object
282 // corresponding to URLRequestContextStorage that actually owns those
283 // objects. See http://crbug.com/523858.
284 scoped_ptr<net::MappedHostResolver> mapped_host_resolver(
285 new net::MappedHostResolver(
286 net::HostResolver::CreateDefaultResolver(nullptr)));
287
288 mapped_host_resolver->SetRulesFromString(host_resolver_rules_);
289 main_context_->set_host_resolver(mapped_host_resolver.release());
290
291 if (!cert_verifier_)
292 cert_verifier_ = net::CertVerifier::CreateDefault();
293 main_context_->set_cert_verifier(cert_verifier_.get());
294
295 main_context_->set_http_auth_handler_factory(
296 net::HttpAuthHandlerRegistryFactory::CreateDefault(
297 main_context_->host_resolver())
298 .release());
299 main_context_->set_proxy_service(
300 net::ProxyService::CreateUsingSystemProxyResolver(
301 std::move(proxy_config_service_), 0, nullptr)
302 .release());
303
304 // Cache
305 base::FilePath cache_path;
306 if (!PathService::Get(base::DIR_CACHE, &cache_path))
307 return;
308 cache_path = cache_path.Append(FILE_PATH_LITERAL("cronet"));
309 scoped_ptr<net::HttpCache::DefaultBackend> main_backend(
310 new net::HttpCache::DefaultBackend(net::DISK_CACHE,
311 net::CACHE_BACKEND_SIMPLE, cache_path,
312 0, // Default cache size.
313 network_cache_thread_->task_runner()));
314
315 net::HttpNetworkSession::Params params;
316
317 params.host_resolver = main_context_->host_resolver();
318 params.cert_verifier = main_context_->cert_verifier();
319 params.channel_id_service = main_context_->channel_id_service();
320 params.transport_security_state = main_context_->transport_security_state();
321 params.proxy_service = main_context_->proxy_service();
322 params.ssl_config_service = main_context_->ssl_config_service();
323 params.http_auth_handler_factory = main_context_->http_auth_handler_factory();
324 params.http_server_properties = main_context_->http_server_properties();
325 params.net_log = main_context_->net_log();
326 params.enable_http2 = http2_enabled();
327 params.parse_alternative_services = false;
328 params.enable_quic = quic_enabled();
329
330 for (const auto& quic_hint : quic_hints_) {
331 net::AlternativeService alternative_service(net::AlternateProtocol::QUIC,
332 "", quic_hint.port());
333
334 main_context_->http_server_properties()->SetAlternativeService(
335 quic_hint, alternative_service, base::Time::Max());
336 params.quic_host_whitelist.insert(quic_hint.host());
337 }
338
339 if (!params.channel_id_service) {
340 // The main context may not have a ChannelIDService, since it is lazily
341 // constructed. If not, build an ephemeral ChannelIDService with no backing
342 // disk store.
343 // TODO(ellyjones): support persisting ChannelID.
344 params.channel_id_service =
345 new net::ChannelIDService(new net::DefaultChannelIDStore(NULL),
346 base::WorkerPool::GetTaskRunner(true));
347 }
348
349 // TODO(mmenke): These really shouldn't be leaked.
350 // See https://crbug.com/523858.
351 net::HttpNetworkSession* http_network_session =
352 new net::HttpNetworkSession(params);
353 net::HttpCache* main_cache =
354 new net::HttpCache(http_network_session, std::move(main_backend),
355 true /* set_up_quic_server_info */);
356 main_context_->set_http_transaction_factory(main_cache);
357
358 net::URLRequestJobFactoryImpl* job_factory =
359 new net::URLRequestJobFactoryImpl;
360 main_context_->set_job_factory(job_factory);
361 main_context_->set_net_log(net_log_.get());
362 }
363
364 std::string CronetEnvironment::user_agent() {
365 const net::HttpUserAgentSettings* user_agent_settings =
366 main_context_->http_user_agent_settings();
367 if (!user_agent_settings) {
368 return nullptr;
369 }
370
371 return user_agent_settings->GetUserAgent();
372 }
373
374 } // namespace cronet
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698