OLD | NEW |
---|---|
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/scoped_block.h" | |
11 #include "base/memory/scoped_vector.h" | 12 #include "base/memory/scoped_vector.h" |
12 #include "base/strings/sys_string_conversions.h" | 13 #include "base/strings/sys_string_conversions.h" |
13 #include "components/cronet/ios/cronet_environment.h" | 14 #include "components/cronet/ios/cronet_environment.h" |
14 #include "components/cronet/url_request_context_config.h" | 15 #include "components/cronet/url_request_context_config.h" |
16 #include "ios/net/crn_http_protocol_handler.h" | |
17 #include "ios/net/empty_nsurlcache.h" | |
18 #include "net/cert/cert_verifier.h" | |
19 #include "net/url_request/url_request_context_getter.h" | |
15 | 20 |
16 namespace { | 21 namespace { |
17 | 22 |
18 // Currently there is one and only one instance of CronetEnvironment, | 23 // Currently there is one and only one instance of CronetEnvironment, |
19 // which is leaked at the shutdown. We should consider allowing multiple | 24 // which is leaked at the shutdown. We should consider allowing multiple |
20 // instances if that makes sense in the future. | 25 // instances if that makes sense in the future. |
21 base::LazyInstance<std::unique_ptr<cronet::CronetEnvironment>>::Leaky | 26 base::LazyInstance<std::unique_ptr<cronet::CronetEnvironment>>::Leaky |
22 gChromeNet = LAZY_INSTANCE_INITIALIZER; | 27 gChromeNet = LAZY_INSTANCE_INITIALIZER; |
23 | 28 |
24 BOOL gHttp2Enabled = YES; | 29 BOOL gHttp2Enabled = YES; |
25 BOOL gQuicEnabled = NO; | 30 BOOL gQuicEnabled = NO; |
26 ScopedVector<cronet::URLRequestContextConfig::QuicHint> gQuicHints; | 31 ScopedVector<cronet::URLRequestContextConfig::QuicHint> gQuicHints; |
27 NSString* gUserAgent = nil; | 32 NSString* gUserAgent = nil; |
33 std::unique_ptr<net::CertVerifier> gMockCertVerifierForTesting; | |
kapishnikov
2016/08/10 17:47:41
Can we rely on Objective-C++ ARC instead of std::u
mef
2016/08/26 14:58:06
moved into CronetTestSupport.mm, changed to bool.
| |
34 NSString* gHostResolverRulesForTesting = @""; | |
28 NSString* gSslKeyLogFileName = nil; | 35 NSString* gSslKeyLogFileName = nil; |
36 RequestFilterBlock gRequestFilterBlock = nil; | |
37 std::unique_ptr<net::HTTPProtocolHandlerDelegate> gHttpProtocolHandlerDelegate; | |
38 | |
39 // net::HTTPProtocolHandlerDelegate for Cronet. | |
40 class CronetHttpProtocolHandlerDelegate | |
41 : public net::HTTPProtocolHandlerDelegate { | |
42 public: | |
43 CronetHttpProtocolHandlerDelegate(net::URLRequestContextGetter* getter, | |
44 RequestFilterBlock filter) | |
45 : getter_(getter), filter_(filter, base::scoped_policy::RETAIN) {} | |
kapishnikov
2016/08/10 17:47:41
RequestFilterBlock is retained by Cronet and at th
mef
2016/08/26 14:58:07
Now allow to call setFilterBlock multiple times to
| |
46 | |
47 private: | |
48 // net::HTTPProtocolHandlerDelegate implementation: | |
49 bool CanHandleRequest(NSURLRequest* request) override { | |
50 if (filter_) { | |
51 RequestFilterBlock block = filter_.get(); | |
52 return block(request); | |
53 } | |
54 return true; | |
55 } | |
56 | |
57 bool IsRequestSupported(NSURLRequest* request) override { | |
58 NSString* scheme = [[request URL] scheme]; | |
59 if (!scheme) | |
60 return false; | |
61 return [scheme caseInsensitiveCompare:@"data"] == NSOrderedSame || | |
62 [scheme caseInsensitiveCompare:@"http"] == NSOrderedSame || | |
63 [scheme caseInsensitiveCompare:@"https"] == NSOrderedSame; | |
64 } | |
65 | |
66 net::URLRequestContextGetter* GetDefaultURLRequestContext() override { | |
67 return getter_.get(); | |
68 } | |
69 | |
70 scoped_refptr<net::URLRequestContextGetter> getter_; | |
71 base::mac::ScopedBlock<RequestFilterBlock> filter_; | |
72 }; | |
29 | 73 |
30 } // namespace | 74 } // namespace |
31 | 75 |
32 @implementation Cronet | 76 @implementation Cronet |
33 | 77 |
34 + (void)checkNotStarted { | 78 + (void)checkNotStarted { |
35 CHECK(gChromeNet == NULL) << "Cronet is already started."; | 79 CHECK(gChromeNet == NULL) << "Cronet is already started."; |
36 } | 80 } |
37 | 81 |
38 + (void)setHttp2Enabled:(BOOL)http2Enabled { | 82 + (void)setHttp2Enabled:(BOOL)http2Enabled { |
(...skipping 10 matching lines...) Expand all Loading... | |
49 [self checkNotStarted]; | 93 [self checkNotStarted]; |
50 gQuicHints.push_back(new cronet::URLRequestContextConfig::QuicHint( | 94 gQuicHints.push_back(new cronet::URLRequestContextConfig::QuicHint( |
51 base::SysNSStringToUTF8(host), port, altPort)); | 95 base::SysNSStringToUTF8(host), port, altPort)); |
52 } | 96 } |
53 | 97 |
54 + (void)setPartialUserAgent:(NSString*)userAgent { | 98 + (void)setPartialUserAgent:(NSString*)userAgent { |
55 [self checkNotStarted]; | 99 [self checkNotStarted]; |
56 gUserAgent = userAgent; | 100 gUserAgent = userAgent; |
57 } | 101 } |
58 | 102 |
103 + (void)setMockCertVerifierForTesting:(void*)mockCertVerifierForTesting { | |
104 [self checkNotStarted]; | |
105 gMockCertVerifierForTesting.reset( | |
106 reinterpret_cast<net::CertVerifier*>(mockCertVerifierForTesting)); | |
107 } | |
108 | |
109 + (void)setHostResolverRulesForTesting:(NSString*)hostResolverRulesForTesting { | |
110 [self checkNotStarted]; | |
111 gHostResolverRulesForTesting = hostResolverRulesForTesting; | |
112 } | |
113 | |
59 + (void)setSslKeyLogFileName:(NSString*)sslKeyLogFileName { | 114 + (void)setSslKeyLogFileName:(NSString*)sslKeyLogFileName { |
60 [self checkNotStarted]; | 115 [self checkNotStarted]; |
61 gSslKeyLogFileName = sslKeyLogFileName; | 116 gSslKeyLogFileName = sslKeyLogFileName; |
62 } | 117 } |
63 | 118 |
119 + (void)setRequestFilterBlock:(RequestFilterBlock)block { | |
120 [self checkNotStarted]; | |
121 gRequestFilterBlock = block; | |
122 } | |
123 | |
64 + (void)startInternal { | 124 + (void)startInternal { |
65 cronet::CronetEnvironment::Initialize(); | 125 cronet::CronetEnvironment::Initialize(); |
66 std::string partialUserAgent = base::SysNSStringToUTF8(gUserAgent); | 126 std::string partialUserAgent = base::SysNSStringToUTF8(gUserAgent); |
67 gChromeNet.Get().reset(new cronet::CronetEnvironment(partialUserAgent)); | 127 gChromeNet.Get().reset(new cronet::CronetEnvironment(partialUserAgent)); |
68 | 128 |
69 gChromeNet.Get()->set_http2_enabled(gHttp2Enabled); | 129 gChromeNet.Get()->set_http2_enabled(gHttp2Enabled); |
70 gChromeNet.Get()->set_quic_enabled(gQuicEnabled); | 130 gChromeNet.Get()->set_quic_enabled(gQuicEnabled); |
71 gChromeNet.Get()->set_ssl_key_log_file_name( | 131 gChromeNet.Get()->set_ssl_key_log_file_name( |
72 base::SysNSStringToUTF8(gSslKeyLogFileName)); | 132 base::SysNSStringToUTF8(gSslKeyLogFileName)); |
73 for (const auto* quicHint : gQuicHints) { | 133 for (const auto* quicHint : gQuicHints) { |
74 gChromeNet.Get()->AddQuicHint(quicHint->host, quicHint->port, | 134 gChromeNet.Get()->AddQuicHint(quicHint->host, quicHint->port, |
75 quicHint->alternate_port); | 135 quicHint->alternate_port); |
76 } | 136 } |
137 gChromeNet.Get()->set_host_resolver_rules( | |
138 [gHostResolverRulesForTesting UTF8String]); | |
139 gChromeNet.Get()->set_cert_verifier(std::move(gMockCertVerifierForTesting)); | |
140 | |
77 gChromeNet.Get()->Start(); | 141 gChromeNet.Get()->Start(); |
142 gHttpProtocolHandlerDelegate.reset(new CronetHttpProtocolHandlerDelegate( | |
143 gChromeNet.Get()->GetURLRequestContextGetter(), gRequestFilterBlock)); | |
144 net::HTTPProtocolHandlerDelegate::SetInstance( | |
145 gHttpProtocolHandlerDelegate.get()); | |
78 } | 146 } |
79 | 147 |
80 + (void)start { | 148 + (void)start { |
81 static dispatch_once_t onceToken; | 149 static dispatch_once_t onceToken; |
82 dispatch_once(&onceToken, ^{ | 150 dispatch_once(&onceToken, ^{ |
83 if (![NSThread isMainThread]) { | 151 if (![NSThread isMainThread]) { |
84 dispatch_sync(dispatch_get_main_queue(), ^(void) { | 152 dispatch_sync(dispatch_get_main_queue(), ^(void) { |
85 [self startInternal]; | 153 [self startInternal]; |
86 }); | 154 }); |
87 } else { | 155 } else { |
88 [self startInternal]; | 156 [self startInternal]; |
89 } | 157 } |
90 }); | 158 }); |
91 } | 159 } |
92 | 160 |
161 + (void)registerHttpProtocolHandler { | |
162 // Disable the default cache. | |
163 [NSURLCache setSharedURLCache:[EmptyNSURLCache emptyNSURLCache]]; | |
164 // Register the chrome http protocol handler to replace the default one. | |
165 BOOL success = | |
166 [NSURLProtocol registerClass:[CRNPauseableHTTPProtocolHandler class]]; | |
167 DCHECK(success); | |
168 } | |
169 | |
170 + (void)unregisterHttpProtocolHandler { | |
171 // Set up an empty default cache, with default size. | |
172 [NSURLCache setSharedURLCache:[[[NSURLCache alloc] init] autorelease]]; | |
kapishnikov
2016/08/10 17:47:41
Should we remember the old value of NSURLCache in
mef
2016/08/26 14:58:06
Done.
| |
173 [NSURLProtocol unregisterClass:[CRNPauseableHTTPProtocolHandler class]]; | |
174 } | |
175 | |
176 + (void)installIntoSessionConfiguration:(NSURLSessionConfiguration*)config { | |
177 config.protocolClasses = @[ [CRNPauseableHTTPProtocolHandler class] ]; | |
178 } | |
179 | |
93 + (void)startNetLogToFile:(NSString*)fileName logBytes:(BOOL)logBytes { | 180 + (void)startNetLogToFile:(NSString*)fileName logBytes:(BOOL)logBytes { |
94 if (gChromeNet.Get().get() && [fileName length]) { | 181 if (gChromeNet.Get().get() && [fileName length]) { |
95 gChromeNet.Get()->StartNetLog([fileName UTF8String], logBytes); | 182 gChromeNet.Get()->StartNetLog([fileName UTF8String], logBytes); |
96 } | 183 } |
97 } | 184 } |
98 | 185 |
99 + (void)stopNetLog { | 186 + (void)stopNetLog { |
100 if (gChromeNet.Get().get()) { | 187 if (gChromeNet.Get().get()) { |
101 gChromeNet.Get()->StopNetLog(); | 188 gChromeNet.Get()->StopNetLog(); |
102 } | 189 } |
(...skipping 11 matching lines...) Expand all Loading... | |
114 + (cronet_engine*)getGlobalEngine { | 201 + (cronet_engine*)getGlobalEngine { |
115 DCHECK(gChromeNet.Get().get()); | 202 DCHECK(gChromeNet.Get().get()); |
116 if (gChromeNet.Get().get()) { | 203 if (gChromeNet.Get().get()) { |
117 static cronet_engine engine; | 204 static cronet_engine engine; |
118 engine.obj = gChromeNet.Get().get(); | 205 engine.obj = gChromeNet.Get().get(); |
119 return &engine; | 206 return &engine; |
120 } | 207 } |
121 return nil; | 208 return nil; |
122 } | 209 } |
123 | 210 |
211 + (NSData*)getGlobalMetricsDeltas { | |
212 if (!gChromeNet.Get().get()) { | |
213 return nil; | |
214 } | |
215 std::vector<uint8_t> deltas(gChromeNet.Get()->GetHistogramDeltas()); | |
216 return [NSData dataWithBytes:deltas.data() length:deltas.size()]; | |
217 } | |
218 | |
124 // This is a non-public dummy method that prevents the linker from stripping out | 219 // 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'. | 220 // the otherwise non-referenced methods from 'cronet_bidirectional_stream.cc'. |
126 + (void)preventStrippingCronetBidirectionalStream { | 221 + (void)preventStrippingCronetBidirectionalStream { |
127 cronet_bidirectional_stream_create(NULL, 0, 0); | 222 cronet_bidirectional_stream_create(NULL, 0, 0); |
128 } | 223 } |
129 | 224 |
130 @end | 225 @end |
OLD | NEW |