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 "mojo/services/network/network_context.h" | |
6 | |
7 #include <stddef.h> | |
8 #include <stdint.h> | |
9 | |
10 #include <algorithm> | |
11 #include <utility> | |
12 #include <vector> | |
13 | |
14 #include "base/base_paths.h" | |
15 #include "base/bind.h" | |
16 #include "base/command_line.h" | |
17 #include "base/logging.h" | |
18 #include "base/macros.h" | |
19 #include "base/path_service.h" | |
20 #include "base/strings/string_number_conversions.h" | |
21 #include "mojo/common/user_agent.h" | |
22 #include "mojo/services/network/url_loader_impl.h" | |
23 #include "net/cookies/cookie_monster.h" | |
24 #include "net/dns/host_resolver.h" | |
25 #include "net/dns/mapped_host_resolver.h" | |
26 #include "net/log/net_log_util.h" | |
27 #include "net/log/write_to_file_net_log_observer.h" | |
28 #include "net/proxy/proxy_service.h" | |
29 #include "net/ssl/channel_id_service.h" | |
30 #include "net/url_request/url_request_context.h" | |
31 #include "net/url_request/url_request_context_builder.h" | |
32 | |
33 namespace mojo { | |
34 | |
35 namespace { | |
36 // Applies the specified mapping rules when resolving hosts. Please see the | |
37 // comment of net::MappedHostResolver::AddRulesFromString() for rule format. | |
38 const char kHostResolverRules[] = "host-resolver-rules"; | |
39 | |
40 // Ignores certificate-related errors. | |
41 const char kIgnoreCertificateErrors[] = "ignore-certificate-errors"; | |
42 | |
43 // Logs network information to the specified file. | |
44 const char kLogNetLog[] = "log-net-log"; | |
45 | |
46 // Allows for forcing socket connections to HTTP/HTTPS to use fixed ports. | |
47 const char kTestingFixedHttpPort[] = "testing-fixed-http-port"; | |
48 const char kTestingFixedHttpsPort[] = "testing-fixed-https-port"; | |
49 | |
50 uint16_t GetPortNumber(const base::CommandLine& command_line, | |
51 const base::StringPiece& switch_name) { | |
52 std::string port_str = command_line.GetSwitchValueASCII(switch_name); | |
53 unsigned port; | |
54 if (!base::StringToUint(port_str, &port) || port > 65535) { | |
55 LOG(ERROR) << "Invalid value for switch " << switch_name << ": '" | |
56 << port_str << "' is not a valid port number."; | |
57 return 0; | |
58 } | |
59 return static_cast<uint16_t>(port); | |
60 } | |
61 | |
62 } // namespace | |
63 | |
64 class NetworkContext::MojoNetLog : public net::NetLog { | |
65 public: | |
66 MojoNetLog() { | |
67 const base::CommandLine* command_line = | |
68 base::CommandLine::ForCurrentProcess(); | |
69 if (!command_line->HasSwitch(kLogNetLog)) | |
70 return; | |
71 | |
72 base::FilePath log_path = command_line->GetSwitchValuePath(kLogNetLog); | |
73 base::ScopedFILE file; | |
74 #if defined(OS_WIN) | |
75 file.reset(_wfopen(log_path.value().c_str(), L"w")); | |
76 #elif defined(OS_POSIX) | |
77 file.reset(fopen(log_path.value().c_str(), "w")); | |
78 #endif | |
79 if (!file) { | |
80 LOG(ERROR) << "Could not open file " << log_path.value() | |
81 << " for net logging"; | |
82 } else { | |
83 write_to_file_observer_.reset(new net::WriteToFileNetLogObserver()); | |
84 write_to_file_observer_->set_capture_mode( | |
85 net::NetLogCaptureMode::IncludeCookiesAndCredentials()); | |
86 write_to_file_observer_->StartObserving(this, std::move(file), nullptr, | |
87 nullptr); | |
88 } | |
89 } | |
90 | |
91 ~MojoNetLog() override { | |
92 if (write_to_file_observer_) | |
93 write_to_file_observer_->StopObserving(nullptr); | |
94 } | |
95 | |
96 private: | |
97 scoped_ptr<net::WriteToFileNetLogObserver> write_to_file_observer_; | |
98 | |
99 DISALLOW_COPY_AND_ASSIGN(MojoNetLog); | |
100 }; | |
101 | |
102 NetworkContext::NetworkContext( | |
103 scoped_ptr<net::URLRequestContext> url_request_context) | |
104 : net_log_(new MojoNetLog), | |
105 url_request_context_(std::move(url_request_context)), | |
106 in_shutdown_(false) { | |
107 url_request_context_->set_net_log(net_log_.get()); | |
108 } | |
109 | |
110 NetworkContext::NetworkContext( | |
111 const base::FilePath& base_path, | |
112 NetworkServiceDelegate* delegate) | |
113 : NetworkContext(MakeURLRequestContext(base_path, delegate)) { | |
114 } | |
115 | |
116 NetworkContext::~NetworkContext() { | |
117 in_shutdown_ = true; | |
118 // TODO(darin): Be careful about destruction order of member variables? | |
119 | |
120 // Call each URLLoaderImpl and ask it to release its net::URLRequest, as the | |
121 // corresponding net::URLRequestContext is going away with this | |
122 // NetworkContext. The loaders can be deregistering themselves in Cleanup(), | |
123 // so iterate over a copy. | |
124 for (auto& url_loader : url_loaders_) { | |
125 url_loader->Cleanup(); | |
126 } | |
127 } | |
128 | |
129 void NetworkContext::RegisterURLLoader(URLLoaderImpl* url_loader) { | |
130 DCHECK(url_loaders_.count(url_loader) == 0); | |
131 url_loaders_.insert(url_loader); | |
132 } | |
133 | |
134 void NetworkContext::DeregisterURLLoader(URLLoaderImpl* url_loader) { | |
135 if (!in_shutdown_) { | |
136 size_t removed_count = url_loaders_.erase(url_loader); | |
137 DCHECK(removed_count); | |
138 } | |
139 } | |
140 | |
141 size_t NetworkContext::GetURLLoaderCountForTesting() { | |
142 return url_loaders_.size(); | |
143 } | |
144 | |
145 // static | |
146 scoped_ptr<net::URLRequestContext> NetworkContext::MakeURLRequestContext( | |
147 const base::FilePath& base_path, | |
148 NetworkServiceDelegate* delegate) { | |
149 net::URLRequestContextBuilder builder; | |
150 net::URLRequestContextBuilder::HttpNetworkSessionParams params; | |
151 const base::CommandLine* command_line = | |
152 base::CommandLine::ForCurrentProcess(); | |
153 if (command_line->HasSwitch(kIgnoreCertificateErrors)) | |
154 params.ignore_certificate_errors = true; | |
155 if (command_line->HasSwitch(kTestingFixedHttpPort)) { | |
156 params.testing_fixed_http_port = | |
157 GetPortNumber(*command_line, kTestingFixedHttpPort); | |
158 } | |
159 if (command_line->HasSwitch(kTestingFixedHttpsPort)) { | |
160 params.testing_fixed_https_port = | |
161 GetPortNumber(*command_line, kTestingFixedHttpsPort); | |
162 } | |
163 builder.set_http_network_session_params(params); | |
164 | |
165 if (command_line->HasSwitch(kHostResolverRules)) { | |
166 scoped_ptr<net::HostResolver> host_resolver( | |
167 net::HostResolver::CreateDefaultResolver(nullptr)); | |
168 scoped_ptr<net::MappedHostResolver> remapped_host_resolver( | |
169 new net::MappedHostResolver(std::move(host_resolver))); | |
170 remapped_host_resolver->SetRulesFromString( | |
171 command_line->GetSwitchValueASCII(kHostResolverRules)); | |
172 builder.set_host_resolver(std::move(remapped_host_resolver)); | |
173 } | |
174 | |
175 builder.set_accept_language("en-us,en"); | |
176 builder.set_user_agent(mojo::common::GetUserAgent()); | |
177 builder.set_proxy_service(net::ProxyService::CreateDirect()); | |
178 builder.set_transport_security_persister_path(base_path); | |
179 | |
180 net::URLRequestContextBuilder::HttpCacheParams cache_params; | |
181 #if defined(OS_ANDROID) | |
182 // On Android, we store the cache on disk becase we can run only a single | |
183 // instance of the shell at a time. | |
184 cache_params.type = net::URLRequestContextBuilder::HttpCacheParams::DISK; | |
185 cache_params.path = base_path.Append(FILE_PATH_LITERAL("Cache")); | |
186 #else | |
187 // On desktop, we store the cache in memory so we can run many shells | |
188 // in parallel when running tests, otherwise the network services in each | |
189 // shell will corrupt the disk cache. | |
190 cache_params.type = net::URLRequestContextBuilder::HttpCacheParams::IN_MEMORY; | |
191 #endif | |
192 | |
193 builder.EnableHttpCache(cache_params); | |
194 builder.set_file_enabled(true); | |
195 | |
196 return builder.Build(); | |
197 } | |
198 | |
199 } // namespace mojo | |
OLD | NEW |