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

Side by Side Diff: components/cronet/ios/Cronet.mm

Issue 2146643002: [Cronet] Integrate CrNet functionality into Cronet on iOS. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix gn header dependencies warnings. Created 4 years, 2 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
1 // Copyright 2016 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "components/cronet/ios/Cronet.h" 5 #import "components/cronet/ios/Cronet.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "base/lazy_instance.h" 9 #include "base/lazy_instance.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/mac/bundle_locations.h"
12 #include "base/mac/scoped_block.h"
13 #include "base/memory/ptr_util.h"
11 #include "base/memory/scoped_vector.h" 14 #include "base/memory/scoped_vector.h"
12 #include "base/strings/sys_string_conversions.h" 15 #include "base/strings/sys_string_conversions.h"
16 #include "base/synchronization/lock.h"
13 #include "components/cronet/ios/cronet_environment.h" 17 #include "components/cronet/ios/cronet_environment.h"
14 #include "components/cronet/url_request_context_config.h" 18 #include "components/cronet/url_request_context_config.h"
19 #include "ios/net/crn_http_protocol_handler.h"
20 #include "ios/net/empty_nsurlcache.h"
21 #include "net/cert/cert_verifier.h"
22 #include "net/url_request/url_request_context_getter.h"
15 23
16 namespace { 24 namespace {
17 25
26 class CronetHttpProtocolHandlerDelegate;
27
18 // Currently there is one and only one instance of CronetEnvironment, 28 // Currently there is one and only one instance of CronetEnvironment,
19 // which is leaked at the shutdown. We should consider allowing multiple 29 // which is leaked at the shutdown. We should consider allowing multiple
20 // instances if that makes sense in the future. 30 // instances if that makes sense in the future.
21 base::LazyInstance<std::unique_ptr<cronet::CronetEnvironment>>::Leaky 31 base::LazyInstance<std::unique_ptr<cronet::CronetEnvironment>>::Leaky
22 gChromeNet = LAZY_INSTANCE_INITIALIZER; 32 gChromeNet = LAZY_INSTANCE_INITIALIZER;
23 33
24 BOOL gHttp2Enabled = YES; 34 BOOL gHttp2Enabled = YES;
25 BOOL gQuicEnabled = NO; 35 BOOL gQuicEnabled = NO;
26 ScopedVector<cronet::URLRequestContextConfig::QuicHint> gQuicHints; 36 ScopedVector<cronet::URLRequestContextConfig::QuicHint> gQuicHints;
27 NSString* gUserAgent = nil; 37 NSString* gUserAgent = nil;
38 BOOL gUserAgentPartial = NO;
28 NSString* gSslKeyLogFileName = nil; 39 NSString* gSslKeyLogFileName = nil;
40 RequestFilterBlock gRequestFilterBlock = nil;
41 std::unique_ptr<CronetHttpProtocolHandlerDelegate> gHttpProtocolHandlerDelegate;
42 NSURLCache* gPreservedSharedURLCache = nil;
43 BOOL gEnableTestCertVerifierForTesting = FALSE;
44 NSString* gHostResolverRulesForTesting = @"";
45
46 // CertVerifier, which allows any certificates for testing.
47 class TestCertVerifier : public net::CertVerifier {
48 int Verify(const RequestParams& params,
49 net::CRLSet* crl_set,
50 net::CertVerifyResult* verify_result,
51 const net::CompletionCallback& callback,
52 std::unique_ptr<Request>* out_req,
53 const net::NetLogWithSource& net_log) override {
54 net::Error result = net::OK;
55 verify_result->verified_cert = params.certificate();
56 verify_result->cert_status = net::MapNetErrorToCertStatus(result);
57 return result;
58 }
59 };
60
61 // net::HTTPProtocolHandlerDelegate for Cronet.
62 class CronetHttpProtocolHandlerDelegate
63 : public net::HTTPProtocolHandlerDelegate {
64 public:
65 CronetHttpProtocolHandlerDelegate(net::URLRequestContextGetter* getter,
66 RequestFilterBlock filter)
67 : getter_(getter), filter_(filter, base::scoped_policy::RETAIN) {}
68
69 void SetRequestFilterBlock(RequestFilterBlock filter) {
70 base::AutoLock auto_lock(lock_);
71 filter_.reset(filter);
72 }
73
74 private:
75 // net::HTTPProtocolHandlerDelegate implementation:
76 bool CanHandleRequest(NSURLRequest* request) override {
77 base::AutoLock auto_lock(lock_);
78 if (filter_) {
79 RequestFilterBlock block = filter_.get();
80 return block(request);
81 }
82 return true;
83 }
84
85 bool IsRequestSupported(NSURLRequest* request) override {
86 NSString* scheme = [[request URL] scheme];
87 if (!scheme)
88 return false;
89 return [scheme caseInsensitiveCompare:@"data"] == NSOrderedSame ||
90 [scheme caseInsensitiveCompare:@"http"] == NSOrderedSame ||
91 [scheme caseInsensitiveCompare:@"https"] == NSOrderedSame;
92 }
93
94 net::URLRequestContextGetter* GetDefaultURLRequestContext() override {
95 return getter_.get();
96 }
97
98 scoped_refptr<net::URLRequestContextGetter> getter_;
99 base::mac::ScopedBlock<RequestFilterBlock> filter_;
100 base::Lock lock_;
101 };
29 102
30 } // namespace 103 } // namespace
31 104
32 @implementation Cronet 105 @implementation Cronet
33 106
107 + (void)configureCronetEnvironmentForTesting:
108 (cronet::CronetEnvironment*)cronetEnvironment {
109 cronetEnvironment->set_host_resolver_rules(
110 [gHostResolverRulesForTesting UTF8String]);
111 if (gEnableTestCertVerifierForTesting) {
112 std::unique_ptr<TestCertVerifier> test_cert_verifier =
113 base::MakeUnique<TestCertVerifier>();
114 cronetEnvironment->set_cert_verifier(std::move(test_cert_verifier));
115 }
116 }
117
118 + (NSString*)getAcceptLanguages {
119 // Use the framework bundle to search for resources.
120 NSBundle* frameworkBundle = [NSBundle bundleForClass:self];
121 NSString* bundlePath =
122 [frameworkBundle pathForResource:@"cronet_resources" ofType:@"bundle"];
123 NSBundle* bundle = [NSBundle bundleWithPath:bundlePath];
124 NSString* acceptLanguages = NSLocalizedStringWithDefaultValue(
125 @"IDS_ACCEPT_LANGUAGES", @"Localizable", bundle, @"en-US,en",
126 @"These values are copied from Chrome's .xtb files, so the same "
127 "values are used in the |Accept-Language| header. Key name matches "
128 "Chrome's.");
129 if (acceptLanguages == Nil)
130 acceptLanguages = @"";
131 return acceptLanguages;
132 }
133
34 + (void)checkNotStarted { 134 + (void)checkNotStarted {
35 CHECK(gChromeNet == NULL) << "Cronet is already started."; 135 CHECK(gChromeNet == NULL) << "Cronet is already started.";
36 } 136 }
37 137
38 + (void)setHttp2Enabled:(BOOL)http2Enabled { 138 + (void)setHttp2Enabled:(BOOL)http2Enabled {
39 [self checkNotStarted]; 139 [self checkNotStarted];
40 gHttp2Enabled = http2Enabled; 140 gHttp2Enabled = http2Enabled;
41 } 141 }
42 142
43 + (void)setQuicEnabled:(BOOL)quicEnabled { 143 + (void)setQuicEnabled:(BOOL)quicEnabled {
44 [self checkNotStarted]; 144 [self checkNotStarted];
45 gQuicEnabled = quicEnabled; 145 gQuicEnabled = quicEnabled;
46 } 146 }
47 147
48 + (void)addQuicHint:(NSString*)host port:(int)port altPort:(int)altPort { 148 + (void)addQuicHint:(NSString*)host port:(int)port altPort:(int)altPort {
49 [self checkNotStarted]; 149 [self checkNotStarted];
50 gQuicHints.push_back(new cronet::URLRequestContextConfig::QuicHint( 150 gQuicHints.push_back(new cronet::URLRequestContextConfig::QuicHint(
51 base::SysNSStringToUTF8(host), port, altPort)); 151 base::SysNSStringToUTF8(host), port, altPort));
52 } 152 }
53 153
54 + (void)setPartialUserAgent:(NSString*)userAgent { 154 + (void)setUserAgent:(NSString*)userAgent partial:(BOOL)partial {
55 [self checkNotStarted]; 155 [self checkNotStarted];
56 gUserAgent = userAgent; 156 gUserAgent = userAgent;
157 gUserAgentPartial = partial;
57 } 158 }
58 159
59 + (void)setSslKeyLogFileName:(NSString*)sslKeyLogFileName { 160 + (void)setSslKeyLogFileName:(NSString*)sslKeyLogFileName {
60 [self checkNotStarted]; 161 [self checkNotStarted];
61 gSslKeyLogFileName = sslKeyLogFileName; 162 gSslKeyLogFileName = sslKeyLogFileName;
62 } 163 }
63 164
165 + (void)setRequestFilterBlock:(RequestFilterBlock)block {
166 if (gHttpProtocolHandlerDelegate.get())
167 gHttpProtocolHandlerDelegate.get()->SetRequestFilterBlock(block);
168 else
169 gRequestFilterBlock = block;
170 }
171
64 + (void)startInternal { 172 + (void)startInternal {
65 cronet::CronetEnvironment::Initialize(); 173 cronet::CronetEnvironment::Initialize();
66 std::string partialUserAgent = base::SysNSStringToUTF8(gUserAgent); 174 std::string user_agent = base::SysNSStringToUTF8(gUserAgent);
67 gChromeNet.Get().reset(new cronet::CronetEnvironment(partialUserAgent)); 175 gChromeNet.Get().reset(
176 new cronet::CronetEnvironment(user_agent, gUserAgentPartial));
177 gChromeNet.Get()->set_accept_language(
178 base::SysNSStringToUTF8([self getAcceptLanguages]));
68 179
69 gChromeNet.Get()->set_http2_enabled(gHttp2Enabled); 180 gChromeNet.Get()->set_http2_enabled(gHttp2Enabled);
70 gChromeNet.Get()->set_quic_enabled(gQuicEnabled); 181 gChromeNet.Get()->set_quic_enabled(gQuicEnabled);
71 gChromeNet.Get()->set_ssl_key_log_file_name( 182 gChromeNet.Get()->set_ssl_key_log_file_name(
72 base::SysNSStringToUTF8(gSslKeyLogFileName)); 183 base::SysNSStringToUTF8(gSslKeyLogFileName));
73 for (const auto* quicHint : gQuicHints) { 184 for (const auto* quicHint : gQuicHints) {
74 gChromeNet.Get()->AddQuicHint(quicHint->host, quicHint->port, 185 gChromeNet.Get()->AddQuicHint(quicHint->host, quicHint->port,
75 quicHint->alternate_port); 186 quicHint->alternate_port);
76 } 187 }
188
189 [self configureCronetEnvironmentForTesting:gChromeNet.Get().get()];
77 gChromeNet.Get()->Start(); 190 gChromeNet.Get()->Start();
191 gHttpProtocolHandlerDelegate.reset(new CronetHttpProtocolHandlerDelegate(
192 gChromeNet.Get()->GetURLRequestContextGetter(), gRequestFilterBlock));
193 net::HTTPProtocolHandlerDelegate::SetInstance(
194 gHttpProtocolHandlerDelegate.get());
195 gRequestFilterBlock = nil;
78 } 196 }
79 197
80 + (void)start { 198 + (void)start {
81 static dispatch_once_t onceToken; 199 static dispatch_once_t onceToken;
82 dispatch_once(&onceToken, ^{ 200 dispatch_once(&onceToken, ^{
83 if (![NSThread isMainThread]) { 201 if (![NSThread isMainThread]) {
84 dispatch_sync(dispatch_get_main_queue(), ^(void) { 202 dispatch_sync(dispatch_get_main_queue(), ^(void) {
85 [self startInternal]; 203 [self startInternal];
86 }); 204 });
87 } else { 205 } else {
88 [self startInternal]; 206 [self startInternal];
89 } 207 }
90 }); 208 });
91 } 209 }
92 210
211 + (void)registerHttpProtocolHandler {
212 if (gPreservedSharedURLCache == nil) {
213 gPreservedSharedURLCache = [NSURLCache sharedURLCache];
214 }
215 // Disable the default cache.
216 [NSURLCache setSharedURLCache:[EmptyNSURLCache emptyNSURLCache]];
217 // Register the chrome http protocol handler to replace the default one.
218 BOOL success =
219 [NSURLProtocol registerClass:[CRNPauseableHTTPProtocolHandler class]];
220 DCHECK(success);
221 }
222
223 + (void)unregisterHttpProtocolHandler {
224 // Set up SharedURLCache preserved in registerHttpProtocolHandler.
225 if (gPreservedSharedURLCache != nil) {
226 [NSURLCache setSharedURLCache:gPreservedSharedURLCache];
227 gPreservedSharedURLCache = nil;
228 }
229 [NSURLProtocol unregisterClass:[CRNPauseableHTTPProtocolHandler class]];
230 }
231
232 + (void)installIntoSessionConfiguration:(NSURLSessionConfiguration*)config {
233 config.protocolClasses = @[ [CRNPauseableHTTPProtocolHandler class] ];
234 }
235
93 + (void)startNetLogToFile:(NSString*)fileName logBytes:(BOOL)logBytes { 236 + (void)startNetLogToFile:(NSString*)fileName logBytes:(BOOL)logBytes {
94 if (gChromeNet.Get().get() && [fileName length]) { 237 if (gChromeNet.Get().get() && [fileName length]) {
95 gChromeNet.Get()->StartNetLog([fileName UTF8String], logBytes); 238 gChromeNet.Get()->StartNetLog([fileName UTF8String], logBytes);
96 } 239 }
97 } 240 }
98 241
99 + (void)stopNetLog { 242 + (void)stopNetLog {
100 if (gChromeNet.Get().get()) { 243 if (gChromeNet.Get().get()) {
101 gChromeNet.Get()->StopNetLog(); 244 gChromeNet.Get()->StopNetLog();
102 } 245 }
(...skipping 11 matching lines...) Expand all
114 + (cronet_engine*)getGlobalEngine { 257 + (cronet_engine*)getGlobalEngine {
115 DCHECK(gChromeNet.Get().get()); 258 DCHECK(gChromeNet.Get().get());
116 if (gChromeNet.Get().get()) { 259 if (gChromeNet.Get().get()) {
117 static cronet_engine engine; 260 static cronet_engine engine;
118 engine.obj = gChromeNet.Get().get(); 261 engine.obj = gChromeNet.Get().get();
119 return &engine; 262 return &engine;
120 } 263 }
121 return nil; 264 return nil;
122 } 265 }
123 266
267 + (NSData*)getGlobalMetricsDeltas {
268 if (!gChromeNet.Get().get()) {
269 return nil;
270 }
271 std::vector<uint8_t> deltas(gChromeNet.Get()->GetHistogramDeltas());
272 return [NSData dataWithBytes:deltas.data() length:deltas.size()];
273 }
274
275 + (void)enableTestCertVerifierForTesting {
276 gEnableTestCertVerifierForTesting = YES;
277 }
278
279 + (void)setHostResolverRulesForTesting:(NSString*)hostResolverRulesForTesting {
280 gHostResolverRulesForTesting = hostResolverRulesForTesting;
281 }
282
124 // This is a non-public dummy method that prevents the linker from stripping out 283 // This is a non-public dummy method that prevents the linker from stripping out
125 // the otherwise non-referenced methods from 'cronet_bidirectional_stream.cc'. 284 // the otherwise non-referenced methods from 'cronet_bidirectional_stream.cc'.
126 + (void)preventStrippingCronetBidirectionalStream { 285 + (void)preventStrippingCronetBidirectionalStream {
127 cronet_bidirectional_stream_create(NULL, 0, 0); 286 cronet_bidirectional_stream_create(NULL, 0, 0);
128 } 287 }
129 288
130 @end 289 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698