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

Unified 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: Simplify TestServer. 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 side-by-side diff with in-line comments
Download patch
Index: components/cronet/ios/Cronet.mm
diff --git a/components/cronet/ios/Cronet.mm b/components/cronet/ios/Cronet.mm
index c397eefbdebd9035ae0f0189127e5caa26b961aa..206ef3a0d7e75f7200d4c7ac6fb871380c5b6d11 100644
--- a/components/cronet/ios/Cronet.mm
+++ b/components/cronet/ios/Cronet.mm
@@ -8,13 +8,22 @@
#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 "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 +34,99 @@ 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) {
+ filter_.reset(filter);
+ }
+
+ private:
+ // net::HTTPProtocolHandlerDelegate implementation:
+ bool CanHandleRequest(NSURLRequest* request) override {
+ 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_;
+};
} // 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 = @"";
kapishnikov 2016/10/19 18:28:53 Why don't we set @"en-US,en" here? Also, should we
mef 2016/10/19 20:12:59 My motivation is that if we run into some unknown
kapishnikov 2016/10/19 21:12:29 I think it is a good idea to give the client an op
+ return acceptLanguages;
+}
+
+ (void)checkNotStarted {
CHECK(gChromeNet == NULL) << "Cronet is already started.";
}
@@ -51,9 +147,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 +158,20 @@ NSString* gSslKeyLogFileName = nil;
gSslKeyLogFileName = sslKeyLogFileName;
}
++ (void)setRequestFilterBlock:(RequestFilterBlock)block {
kapishnikov 2016/10/19 18:28:53 Is this method thread safe? What if there are pend
mef 2016/10/19 20:12:59 Good catch! Done.
+ 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 +181,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 +204,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] ];
kapishnikov 2016/10/19 18:28:53 Should we append to the list of protocols rather t
mef 2016/10/19 20:12:59 But wouldn't this require Cronet to handle that cu
kapishnikov 2016/10/19 21:12:29 Cronet handles "http://", "https://" and "data://"
+}
+
+ (void)startNetLogToFile:(NSString*)fileName logBytes:(BOOL)logBytes {
if (gChromeNet.Get().get() && [fileName length]) {
gChromeNet.Get()->StartNetLog([fileName UTF8String], logBytes);
@@ -121,6 +260,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 = TRUE;
kapishnikov 2016/10/19 18:28:53 TRUE -> YES
mef 2016/10/19 20:12:58 Done.
+}
+
++ (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 {

Powered by Google App Engine
This is Rietveld 408576698