Commit 250b6247 authored by Brad Lassey's avatar Brad Lassey Committed by Commit Bot

Add Brotli support to iOS Cronet

This adds a getter and setter to enable and disable brotli. The test
tests that brotli is advertised (or not) and that encoded data can be
decoded correctly.

Bug = 737231

Bug: 737231
Change-Id: I63e58f97725764b74f51a86edc2ed0eefafe7476
Reviewed-on: https://chromium-review.googlesource.com/563857
Commit-Queue: Brad Lassey <lassey@chromium.org>
Reviewed-by: default avatarsmut <smut@google.com>
Reviewed-by: default avatarSylvain Defresne <sdefresne@chromium.org>
Reviewed-by: default avatarMisha Efimov <mef@chromium.org>
Cr-Commit-Position: refs/heads/master@{#485262}
parent b0a0d75d
...@@ -51,6 +51,10 @@ GRPC_SUPPORT_EXPORT ...@@ -51,6 +51,10 @@ GRPC_SUPPORT_EXPORT
// any effect before |start| is called. // any effect before |start| is called.
+ (void)setQuicEnabled:(BOOL)quicEnabled; + (void)setQuicEnabled:(BOOL)quicEnabled;
// Sets whether Brotli should be supported by CronetEngine. This method only has
// any effect before |start| is called.
+ (void)setBrotliEnabled:(BOOL)brotliEnabled;
// Set HTTP Cache type to be used by CronetEngine. This method only has any // Set HTTP Cache type to be used by CronetEngine. This method only has any
// effect before |start| is called. See HttpCacheType enum for available // effect before |start| is called. See HttpCacheType enum for available
// options. // options.
......
...@@ -43,6 +43,7 @@ base::LazyInstance<std::unique_ptr<cronet::CronetEnvironment>>::Leaky ...@@ -43,6 +43,7 @@ base::LazyInstance<std::unique_ptr<cronet::CronetEnvironment>>::Leaky
// sane. // sane.
BOOL gHttp2Enabled = YES; BOOL gHttp2Enabled = YES;
BOOL gQuicEnabled = NO; BOOL gQuicEnabled = NO;
BOOL gBrotliEnabled = NO;
cronet::URLRequestContextConfig::HttpCacheType gHttpCache = cronet::URLRequestContextConfig::HttpCacheType gHttpCache =
cronet::URLRequestContextConfig::HttpCacheType::DISK; cronet::URLRequestContextConfig::HttpCacheType::DISK;
QuicHintVector gQuicHints; QuicHintVector gQuicHints;
...@@ -179,6 +180,11 @@ class CronetHttpProtocolHandlerDelegate ...@@ -179,6 +180,11 @@ class CronetHttpProtocolHandlerDelegate
gQuicEnabled = quicEnabled; gQuicEnabled = quicEnabled;
} }
+ (void)setBrotliEnabled:(BOOL)brotliEnabled {
[self checkNotStarted];
gBrotliEnabled = brotliEnabled;
}
+ (void)addQuicHint:(NSString*)host port:(int)port altPort:(int)altPort { + (void)addQuicHint:(NSString*)host port:(int)port altPort:(int)altPort {
[self checkNotStarted]; [self checkNotStarted];
gQuicHints.push_back( gQuicHints.push_back(
...@@ -281,6 +287,7 @@ class CronetHttpProtocolHandlerDelegate ...@@ -281,6 +287,7 @@ class CronetHttpProtocolHandlerDelegate
gChromeNet.Get()->set_http2_enabled(gHttp2Enabled); gChromeNet.Get()->set_http2_enabled(gHttp2Enabled);
gChromeNet.Get()->set_quic_enabled(gQuicEnabled); gChromeNet.Get()->set_quic_enabled(gQuicEnabled);
gChromeNet.Get()->set_brotli_enabled(gBrotliEnabled);
gChromeNet.Get()->set_experimental_options( gChromeNet.Get()->set_experimental_options(
base::SysNSStringToUTF8(gExperimentalOptions)); base::SysNSStringToUTF8(gExperimentalOptions));
gChromeNet.Get()->set_http_cache(gHttpCache); gChromeNet.Get()->set_http_cache(gHttpCache);
......
...@@ -68,13 +68,15 @@ class CronetEnvironment { ...@@ -68,13 +68,15 @@ class CronetEnvironment {
void AddQuicHint(const std::string& host, int port, int alternate_port); void AddQuicHint(const std::string& host, int port, int alternate_port);
// Setters and getters for |http2_enabled_|, |quic_enabled_|, and // Setters and getters for |http2_enabled_|, |quic_enabled_|, and
// |forced_quic_origin_|. These only have any effect before Start() is // |brotli_enabled| These only have any effect
// called. // before Start() is called.
void set_http2_enabled(bool enabled) { http2_enabled_ = enabled; } void set_http2_enabled(bool enabled) { http2_enabled_ = enabled; }
void set_quic_enabled(bool enabled) { quic_enabled_ = enabled; } void set_quic_enabled(bool enabled) { quic_enabled_ = enabled; }
void set_brotli_enabled(bool enabled) { brotli_enabled_ = enabled; }
bool http2_enabled() const { return http2_enabled_; } bool http2_enabled() const { return http2_enabled_; }
bool quic_enabled() const { return quic_enabled_; } bool quic_enabled() const { return quic_enabled_; }
bool brotli_enabled() const { return brotli_enabled_; }
void set_quic_user_agent_id(const std::string& quic_user_agent_id) { void set_quic_user_agent_id(const std::string& quic_user_agent_id) {
quic_user_agent_id_ = quic_user_agent_id; quic_user_agent_id_ = quic_user_agent_id;
...@@ -145,6 +147,7 @@ class CronetEnvironment { ...@@ -145,6 +147,7 @@ class CronetEnvironment {
bool http2_enabled_; bool http2_enabled_;
bool quic_enabled_; bool quic_enabled_;
bool brotli_enabled_;
std::string quic_user_agent_id_; std::string quic_user_agent_id_;
std::string accept_language_; std::string accept_language_;
std::string experimental_options_; std::string experimental_options_;
......
...@@ -219,6 +219,7 @@ CronetEnvironment::CronetEnvironment(const std::string& user_agent, ...@@ -219,6 +219,7 @@ CronetEnvironment::CronetEnvironment(const std::string& user_agent,
bool user_agent_partial) bool user_agent_partial)
: http2_enabled_(false), : http2_enabled_(false),
quic_enabled_(false), quic_enabled_(false),
brotli_enabled_(false),
http_cache_(URLRequestContextConfig::HttpCacheType::DISK), http_cache_(URLRequestContextConfig::HttpCacheType::DISK),
user_agent_(user_agent), user_agent_(user_agent),
user_agent_partial_(user_agent_partial), user_agent_partial_(user_agent_partial),
...@@ -348,6 +349,7 @@ void CronetEnvironment::InitializeOnNetworkThread() { ...@@ -348,6 +349,7 @@ void CronetEnvironment::InitializeOnNetworkThread() {
context_builder.SetHttpServerProperties(std::move(http_server_properties)); context_builder.SetHttpServerProperties(std::move(http_server_properties));
context_builder.set_enable_brotli(brotli_enabled_);
main_context_ = context_builder.Build(); main_context_ = context_builder.Build();
main_context_->transport_security_state() main_context_->transport_security_state()
......
...@@ -372,4 +372,50 @@ TEST_F(HttpTest, DataSchemeNotSupported) { ...@@ -372,4 +372,50 @@ TEST_F(HttpTest, DataSchemeNotSupported) {
EXPECT_TRUE([[delegate_ responseBody] containsString:testString]); EXPECT_TRUE([[delegate_ responseBody] containsString:testString]);
} }
TEST_F(HttpTest, BrotliAdvertisedTest) {
[Cronet shutdownForTesting];
[Cronet setBrotliEnabled:YES];
StartCronet(grpc_support::GetQuicTestServerPort());
NSURL* url =
net::NSURLWithGURL(GURL(TestServer::GetEchoHeaderURL("Accept-Encoding")));
NSURLSessionDataTask* task = [session_ dataTaskWithURL:url];
StartDataTaskAndWaitForCompletion(task);
EXPECT_EQ(nil, [delegate_ error]);
EXPECT_TRUE([[delegate_ responseBody] containsString:@"br"]);
}
TEST_F(HttpTest, BrotliNotAdvertisedTest) {
[Cronet shutdownForTesting];
[Cronet setBrotliEnabled:NO];
StartCronet(grpc_support::GetQuicTestServerPort());
NSURL* url =
net::NSURLWithGURL(GURL(TestServer::GetEchoHeaderURL("Accept-Encoding")));
NSURLSessionDataTask* task = [session_ dataTaskWithURL:url];
StartDataTaskAndWaitForCompletion(task);
EXPECT_EQ(nil, [delegate_ error]);
EXPECT_FALSE([[delegate_ responseBody] containsString:@"br"]);
}
TEST_F(HttpTest, BrotliHandleDecoding) {
[Cronet shutdownForTesting];
[Cronet setBrotliEnabled:YES];
StartCronet(grpc_support::GetQuicTestServerPort());
NSURL* url =
net::NSURLWithGURL(GURL(TestServer::GetUseEncodingURL("brotli")));
NSURLSessionDataTask* task = [session_ dataTaskWithURL:url];
StartDataTaskAndWaitForCompletion(task);
EXPECT_EQ(nil, [delegate_ error]);
EXPECT_STREQ(base::SysNSStringToUTF8([delegate_ responseBody]).c_str(),
"The quick brown fox jumps over the lazy dog");
}
} // namespace cronet } // namespace cronet
...@@ -22,6 +22,7 @@ namespace { ...@@ -22,6 +22,7 @@ namespace {
const char kEchoHeaderPath[] = "/EchoHeader?"; const char kEchoHeaderPath[] = "/EchoHeader?";
const char kSetCookiePath[] = "/SetCookie?"; const char kSetCookiePath[] = "/SetCookie?";
const char kBigDataPath[] = "/BigData?"; const char kBigDataPath[] = "/BigData?";
const char kUseEncodingPath[] = "/UseEncoding?";
std::unique_ptr<net::EmbeddedTestServer> g_test_server; std::unique_ptr<net::EmbeddedTestServer> g_test_server;
base::LazyInstance<std::string>::Leaky g_big_data_body = base::LazyInstance<std::string>::Leaky g_big_data_body =
...@@ -43,6 +44,29 @@ std::unique_ptr<net::test_server::HttpResponse> EchoHeaderInRequest( ...@@ -43,6 +44,29 @@ std::unique_ptr<net::test_server::HttpResponse> EchoHeaderInRequest(
return std::move(http_response); return std::move(http_response);
} }
std::unique_ptr<net::test_server::HttpResponse> UseEncodingInResponse(
const net::test_server::HttpRequest& request) {
std::string encoding;
DCHECK(base::StartsWith(request.relative_url, kUseEncodingPath,
base::CompareCase::INSENSITIVE_ASCII));
encoding = request.relative_url.substr(strlen(kUseEncodingPath));
auto http_response = base::MakeUnique<net::test_server::BasicHttpResponse>();
if (!encoding.compare("brotli")) {
const char quickfoxCompressed[] = {
0x0b, 0x15, -0x80, 0x54, 0x68, 0x65, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b,
0x20, 0x62, 0x72, 0x6f, 0x77, 0x6e, 0x20, 0x66, 0x6f, 0x78, 0x20, 0x6a,
0x75, 0x6d, 0x70, 0x73, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68,
0x65, 0x20, 0x6c, 0x61, 0x7a, 0x79, 0x20, 0x64, 0x6f, 0x67, 0x03};
std::string quickfoxCompressedStr(quickfoxCompressed,
sizeof(quickfoxCompressed));
http_response->set_content(quickfoxCompressedStr);
http_response->AddCustomHeader(std::string("content-encoding"),
std::string("br"));
}
return std::move(http_response);
}
std::unique_ptr<net::test_server::HttpResponse> ReturnBigDataInResponse( std::unique_ptr<net::test_server::HttpResponse> ReturnBigDataInResponse(
const net::test_server::HttpRequest& request) { const net::test_server::HttpRequest& request) {
DCHECK(base::StartsWith(request.relative_url, kBigDataPath, DCHECK(base::StartsWith(request.relative_url, kBigDataPath,
...@@ -81,6 +105,10 @@ std::unique_ptr<net::test_server::HttpResponse> CronetTestRequestHandler( ...@@ -81,6 +105,10 @@ std::unique_ptr<net::test_server::HttpResponse> CronetTestRequestHandler(
base::CompareCase::INSENSITIVE_ASCII)) { base::CompareCase::INSENSITIVE_ASCII)) {
return ReturnBigDataInResponse(request); return ReturnBigDataInResponse(request);
} }
if (base::StartsWith(request.relative_url, kUseEncodingPath,
base::CompareCase::INSENSITIVE_ASCII)) {
return UseEncodingInResponse(request);
}
return base::MakeUnique<net::test_server::BasicHttpResponse>(); return base::MakeUnique<net::test_server::BasicHttpResponse>();
} }
...@@ -108,6 +136,11 @@ std::string TestServer::GetEchoHeaderURL(const std::string& header_name) { ...@@ -108,6 +136,11 @@ std::string TestServer::GetEchoHeaderURL(const std::string& header_name) {
return g_test_server->GetURL(kEchoHeaderPath + header_name).spec(); return g_test_server->GetURL(kEchoHeaderPath + header_name).spec();
} }
std::string TestServer::GetUseEncodingURL(const std::string& header_name) {
DCHECK(g_test_server);
return g_test_server->GetURL(kUseEncodingPath + header_name).spec();
}
std::string TestServer::GetSetCookieURL(const std::string& cookie_line) { std::string TestServer::GetSetCookieURL(const std::string& cookie_line) {
DCHECK(g_test_server); DCHECK(g_test_server);
return g_test_server->GetURL(kSetCookiePath + cookie_line).spec(); return g_test_server->GetURL(kSetCookiePath + cookie_line).spec();
......
...@@ -17,6 +17,9 @@ class TestServer { ...@@ -17,6 +17,9 @@ class TestServer {
// Returns URL which respond with echo of header with |header_name| in // Returns URL which respond with echo of header with |header_name| in
// response body. // response body.
static std::string GetEchoHeaderURL(const std::string& header_name); static std::string GetEchoHeaderURL(const std::string& header_name);
// Returns URL which responds with "The quick brown fox jumps over the lazy
// dog" in specified encoding.
static std::string GetUseEncodingURL(const std::string& header_name);
// Returns URL which respond with setting cookie to |cookie_line| and echo it // Returns URL which respond with setting cookie to |cookie_line| and echo it
// in response body. // in response body.
static std::string GetSetCookieURL(const std::string& cookie_line); static std::string GetSetCookieURL(const std::string& cookie_line);
......
...@@ -101,6 +101,7 @@ def main(): ...@@ -101,6 +101,7 @@ def main():
gn_args += 'target_os="' + target_os + '" enable_websockets=false '+ \ gn_args += 'target_os="' + target_os + '" enable_websockets=false '+ \
'disable_file_support=true disable_ftp_support=true '+ \ 'disable_file_support=true disable_ftp_support=true '+ \
'disable_brotli_filter=false ' + \
'use_platform_icu_alternatives=true '+ \ 'use_platform_icu_alternatives=true '+ \
'enable_reporting=false '+ \ 'enable_reporting=false '+ \
'is_component_build=false ' + \ 'is_component_build=false ' + \
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
"xcode version": "8.0", "xcode version": "8.0",
"gn_args": [ "gn_args": [
"additional_target_cpus=[\"x86\"]", "additional_target_cpus=[\"x86\"]",
"disable_brotli_filter=true", "disable_brotli_filter=false",
"disable_file_support=true", "disable_file_support=true",
"disable_ftp_support=true", "disable_ftp_support=true",
"enable_websockets=false", "enable_websockets=false",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment