| Index: components/cronet/ios/Cronet.mm
|
| diff --git a/components/cronet/ios/Cronet.mm b/components/cronet/ios/Cronet.mm
|
| index c397eefbdebd9035ae0f0189127e5caa26b961aa..150be2435ff32b9919574f60c8766995eb4f698b 100644
|
| --- a/components/cronet/ios/Cronet.mm
|
| +++ b/components/cronet/ios/Cronet.mm
|
| @@ -8,13 +8,23 @@
|
|
|
| #include "base/lazy_instance.h"
|
| #include "base/logging.h"
|
| +#include "base/mac/bundle_locations.h"
|
| +#include "base/mac/scoped_block.h"
|
| +#include "base/memory/ptr_util.h"
|
| #include "base/memory/scoped_vector.h"
|
| #include "base/strings/sys_string_conversions.h"
|
| +#include "base/synchronization/lock.h"
|
| #include "components/cronet/ios/cronet_environment.h"
|
| #include "components/cronet/url_request_context_config.h"
|
| +#include "ios/net/crn_http_protocol_handler.h"
|
| +#include "ios/net/empty_nsurlcache.h"
|
| +#include "net/cert/cert_verifier.h"
|
| +#include "net/url_request/url_request_context_getter.h"
|
|
|
| namespace {
|
|
|
| +class CronetHttpProtocolHandlerDelegate;
|
| +
|
| // Currently there is one and only one instance of CronetEnvironment,
|
| // which is leaked at the shutdown. We should consider allowing multiple
|
| // instances if that makes sense in the future.
|
| @@ -25,12 +35,102 @@ BOOL gHttp2Enabled = YES;
|
| BOOL gQuicEnabled = NO;
|
| ScopedVector<cronet::URLRequestContextConfig::QuicHint> gQuicHints;
|
| NSString* gUserAgent = nil;
|
| +BOOL gUserAgentPartial = NO;
|
| NSString* gSslKeyLogFileName = nil;
|
| +RequestFilterBlock gRequestFilterBlock = nil;
|
| +std::unique_ptr<CronetHttpProtocolHandlerDelegate> gHttpProtocolHandlerDelegate;
|
| +NSURLCache* gPreservedSharedURLCache = nil;
|
| +BOOL gEnableTestCertVerifierForTesting = FALSE;
|
| +NSString* gHostResolverRulesForTesting = @"";
|
| +
|
| +// CertVerifier, which allows any certificates for testing.
|
| +class TestCertVerifier : public net::CertVerifier {
|
| + int Verify(const RequestParams& params,
|
| + net::CRLSet* crl_set,
|
| + net::CertVerifyResult* verify_result,
|
| + const net::CompletionCallback& callback,
|
| + std::unique_ptr<Request>* out_req,
|
| + const net::NetLogWithSource& net_log) override {
|
| + net::Error result = net::OK;
|
| + verify_result->verified_cert = params.certificate();
|
| + verify_result->cert_status = net::MapNetErrorToCertStatus(result);
|
| + return result;
|
| + }
|
| +};
|
| +
|
| +// net::HTTPProtocolHandlerDelegate for Cronet.
|
| +class CronetHttpProtocolHandlerDelegate
|
| + : public net::HTTPProtocolHandlerDelegate {
|
| + public:
|
| + CronetHttpProtocolHandlerDelegate(net::URLRequestContextGetter* getter,
|
| + RequestFilterBlock filter)
|
| + : getter_(getter), filter_(filter, base::scoped_policy::RETAIN) {}
|
| +
|
| + void SetRequestFilterBlock(RequestFilterBlock filter) {
|
| + base::AutoLock auto_lock(lock_);
|
| + filter_.reset(filter);
|
| + }
|
| +
|
| + private:
|
| + // net::HTTPProtocolHandlerDelegate implementation:
|
| + bool CanHandleRequest(NSURLRequest* request) override {
|
| + base::AutoLock auto_lock(lock_);
|
| + if (filter_) {
|
| + RequestFilterBlock block = filter_.get();
|
| + return block(request);
|
| + }
|
| + return true;
|
| + }
|
| +
|
| + bool IsRequestSupported(NSURLRequest* request) override {
|
| + NSString* scheme = [[request URL] scheme];
|
| + if (!scheme)
|
| + return false;
|
| + return [scheme caseInsensitiveCompare:@"data"] == NSOrderedSame ||
|
| + [scheme caseInsensitiveCompare:@"http"] == NSOrderedSame ||
|
| + [scheme caseInsensitiveCompare:@"https"] == NSOrderedSame;
|
| + }
|
| +
|
| + net::URLRequestContextGetter* GetDefaultURLRequestContext() override {
|
| + return getter_.get();
|
| + }
|
| +
|
| + scoped_refptr<net::URLRequestContextGetter> getter_;
|
| + base::mac::ScopedBlock<RequestFilterBlock> filter_;
|
| + base::Lock lock_;
|
| +};
|
|
|
| } // namespace
|
|
|
| @implementation Cronet
|
|
|
| ++ (void)configureCronetEnvironmentForTesting:
|
| + (cronet::CronetEnvironment*)cronetEnvironment {
|
| + cronetEnvironment->set_host_resolver_rules(
|
| + [gHostResolverRulesForTesting UTF8String]);
|
| + if (gEnableTestCertVerifierForTesting) {
|
| + std::unique_ptr<TestCertVerifier> test_cert_verifier =
|
| + base::MakeUnique<TestCertVerifier>();
|
| + cronetEnvironment->set_cert_verifier(std::move(test_cert_verifier));
|
| + }
|
| +}
|
| +
|
| ++ (NSString*)getAcceptLanguages {
|
| + // Use the framework bundle to search for resources.
|
| + NSBundle* frameworkBundle = [NSBundle bundleForClass:self];
|
| + NSString* bundlePath =
|
| + [frameworkBundle pathForResource:@"cronet_resources" ofType:@"bundle"];
|
| + NSBundle* bundle = [NSBundle bundleWithPath:bundlePath];
|
| + NSString* acceptLanguages = NSLocalizedStringWithDefaultValue(
|
| + @"IDS_ACCEPT_LANGUAGES", @"Localizable", bundle, @"en-US,en",
|
| + @"These values are copied from Chrome's .xtb files, so the same "
|
| + "values are used in the |Accept-Language| header. Key name matches "
|
| + "Chrome's.");
|
| + if (acceptLanguages == Nil)
|
| + acceptLanguages = @"";
|
| + return acceptLanguages;
|
| +}
|
| +
|
| + (void)checkNotStarted {
|
| CHECK(gChromeNet == NULL) << "Cronet is already started.";
|
| }
|
| @@ -51,9 +151,10 @@ NSString* gSslKeyLogFileName = nil;
|
| base::SysNSStringToUTF8(host), port, altPort));
|
| }
|
|
|
| -+ (void)setPartialUserAgent:(NSString*)userAgent {
|
| ++ (void)setUserAgent:(NSString*)userAgent partial:(BOOL)partial {
|
| [self checkNotStarted];
|
| gUserAgent = userAgent;
|
| + gUserAgentPartial = partial;
|
| }
|
|
|
| + (void)setSslKeyLogFileName:(NSString*)sslKeyLogFileName {
|
| @@ -61,10 +162,20 @@ NSString* gSslKeyLogFileName = nil;
|
| gSslKeyLogFileName = sslKeyLogFileName;
|
| }
|
|
|
| ++ (void)setRequestFilterBlock:(RequestFilterBlock)block {
|
| + if (gHttpProtocolHandlerDelegate.get())
|
| + gHttpProtocolHandlerDelegate.get()->SetRequestFilterBlock(block);
|
| + else
|
| + gRequestFilterBlock = block;
|
| +}
|
| +
|
| + (void)startInternal {
|
| cronet::CronetEnvironment::Initialize();
|
| - std::string partialUserAgent = base::SysNSStringToUTF8(gUserAgent);
|
| - gChromeNet.Get().reset(new cronet::CronetEnvironment(partialUserAgent));
|
| + std::string user_agent = base::SysNSStringToUTF8(gUserAgent);
|
| + gChromeNet.Get().reset(
|
| + new cronet::CronetEnvironment(user_agent, gUserAgentPartial));
|
| + gChromeNet.Get()->set_accept_language(
|
| + base::SysNSStringToUTF8([self getAcceptLanguages]));
|
|
|
| gChromeNet.Get()->set_http2_enabled(gHttp2Enabled);
|
| gChromeNet.Get()->set_quic_enabled(gQuicEnabled);
|
| @@ -74,7 +185,14 @@ NSString* gSslKeyLogFileName = nil;
|
| gChromeNet.Get()->AddQuicHint(quicHint->host, quicHint->port,
|
| quicHint->alternate_port);
|
| }
|
| +
|
| + [self configureCronetEnvironmentForTesting:gChromeNet.Get().get()];
|
| gChromeNet.Get()->Start();
|
| + gHttpProtocolHandlerDelegate.reset(new CronetHttpProtocolHandlerDelegate(
|
| + gChromeNet.Get()->GetURLRequestContextGetter(), gRequestFilterBlock));
|
| + net::HTTPProtocolHandlerDelegate::SetInstance(
|
| + gHttpProtocolHandlerDelegate.get());
|
| + gRequestFilterBlock = nil;
|
| }
|
|
|
| + (void)start {
|
| @@ -90,6 +208,31 @@ NSString* gSslKeyLogFileName = nil;
|
| });
|
| }
|
|
|
| ++ (void)registerHttpProtocolHandler {
|
| + if (gPreservedSharedURLCache == nil) {
|
| + gPreservedSharedURLCache = [NSURLCache sharedURLCache];
|
| + }
|
| + // Disable the default cache.
|
| + [NSURLCache setSharedURLCache:[EmptyNSURLCache emptyNSURLCache]];
|
| + // Register the chrome http protocol handler to replace the default one.
|
| + BOOL success =
|
| + [NSURLProtocol registerClass:[CRNPauseableHTTPProtocolHandler class]];
|
| + DCHECK(success);
|
| +}
|
| +
|
| ++ (void)unregisterHttpProtocolHandler {
|
| + // Set up SharedURLCache preserved in registerHttpProtocolHandler.
|
| + if (gPreservedSharedURLCache != nil) {
|
| + [NSURLCache setSharedURLCache:gPreservedSharedURLCache];
|
| + gPreservedSharedURLCache = nil;
|
| + }
|
| + [NSURLProtocol unregisterClass:[CRNPauseableHTTPProtocolHandler class]];
|
| +}
|
| +
|
| ++ (void)installIntoSessionConfiguration:(NSURLSessionConfiguration*)config {
|
| + config.protocolClasses = @[ [CRNPauseableHTTPProtocolHandler class] ];
|
| +}
|
| +
|
| + (void)startNetLogToFile:(NSString*)fileName logBytes:(BOOL)logBytes {
|
| if (gChromeNet.Get().get() && [fileName length]) {
|
| gChromeNet.Get()->StartNetLog([fileName UTF8String], logBytes);
|
| @@ -121,6 +264,22 @@ NSString* gSslKeyLogFileName = nil;
|
| return nil;
|
| }
|
|
|
| ++ (NSData*)getGlobalMetricsDeltas {
|
| + if (!gChromeNet.Get().get()) {
|
| + return nil;
|
| + }
|
| + std::vector<uint8_t> deltas(gChromeNet.Get()->GetHistogramDeltas());
|
| + return [NSData dataWithBytes:deltas.data() length:deltas.size()];
|
| +}
|
| +
|
| ++ (void)enableTestCertVerifierForTesting {
|
| + gEnableTestCertVerifierForTesting = YES;
|
| +}
|
| +
|
| ++ (void)setHostResolverRulesForTesting:(NSString*)hostResolverRulesForTesting {
|
| + gHostResolverRulesForTesting = hostResolverRulesForTesting;
|
| +}
|
| +
|
| // This is a non-public dummy method that prevents the linker from stripping out
|
| // the otherwise non-referenced methods from 'cronet_bidirectional_stream.cc'.
|
| + (void)preventStrippingCronetBidirectionalStream {
|
|
|