| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "cronet_test_base.h" |
| 6 |
| 7 #include "components/grpc_support/test/quic_test_server.h" |
| 8 #include "crypto/sha2.h" |
| 9 #include "net/base/net_errors.h" |
| 10 #include "net/cert/asn1_util.h" |
| 11 #include "net/cert/mock_cert_verifier.h" |
| 12 #include "net/test/cert_test_util.h" |
| 13 #include "net/test/test_data_directory.h" |
| 14 |
| 15 #pragma mark |
| 16 |
| 17 @implementation TestDelegate { |
| 18 // Completion semaphore for this TestDelegate. When the request this delegate |
| 19 // is attached to finishes (either successfully or with an error), this |
| 20 // delegate signals this semaphore. |
| 21 dispatch_semaphore_t _semaphore; |
| 22 } |
| 23 |
| 24 @synthesize error = _error; |
| 25 @synthesize totalBytesReceived = _totalBytesReceived; |
| 26 |
| 27 NSMutableArray<NSData*>* _responseData; |
| 28 |
| 29 - (id)init { |
| 30 if (self = [super init]) { |
| 31 _semaphore = dispatch_semaphore_create(0); |
| 32 } |
| 33 return self; |
| 34 } |
| 35 |
| 36 - (void)reset { |
| 37 _responseData = nil; |
| 38 _error = nil; |
| 39 _totalBytesReceived = 0; |
| 40 } |
| 41 |
| 42 - (NSString*)responseBody { |
| 43 if (_responseData == nil) { |
| 44 return nil; |
| 45 } |
| 46 NSMutableString* body = [NSMutableString string]; |
| 47 for (NSData* data in _responseData) { |
| 48 [body appendString:[[NSString alloc] initWithData:data |
| 49 encoding:NSUTF8StringEncoding]]; |
| 50 } |
| 51 VLOG(3) << "responseBody size:" << [body length] |
| 52 << " chunks:" << [_responseData count]; |
| 53 return body; |
| 54 } |
| 55 |
| 56 - (BOOL)waitForDone { |
| 57 int64_t deadline_ns = 20 * NSEC_PER_SEC; |
| 58 return dispatch_semaphore_wait( |
| 59 _semaphore, dispatch_time(DISPATCH_TIME_NOW, deadline_ns)) == 0; |
| 60 } |
| 61 |
| 62 - (void)URLSession:(NSURLSession*)session |
| 63 didBecomeInvalidWithError:(NSError*)error { |
| 64 } |
| 65 |
| 66 - (void)URLSession:(NSURLSession*)session |
| 67 task:(NSURLSessionTask*)task |
| 68 didCompleteWithError:(NSError*)error { |
| 69 [self setError:error]; |
| 70 dispatch_semaphore_signal(_semaphore); |
| 71 } |
| 72 |
| 73 - (void)URLSession:(NSURLSession*)session |
| 74 task:(NSURLSessionTask*)task |
| 75 didReceiveChallenge:(NSURLAuthenticationChallenge*)challenge |
| 76 completionHandler: |
| 77 (void (^)(NSURLSessionAuthChallengeDisposition disp, |
| 78 NSURLCredential* credential))completionHandler { |
| 79 completionHandler(NSURLSessionAuthChallengeUseCredential, nil); |
| 80 } |
| 81 |
| 82 - (void)URLSession:(NSURLSession*)session |
| 83 dataTask:(NSURLSessionDataTask*)dataTask |
| 84 didReceiveResponse:(NSURLResponse*)response |
| 85 completionHandler:(void (^)(NSURLSessionResponseDisposition disposition)) |
| 86 completionHandler { |
| 87 completionHandler(NSURLSessionResponseAllow); |
| 88 } |
| 89 |
| 90 - (void)URLSession:(NSURLSession*)session |
| 91 dataTask:(NSURLSessionDataTask*)dataTask |
| 92 didReceiveData:(NSData*)data { |
| 93 _totalBytesReceived += [data length]; |
| 94 if (_responseData == nil) { |
| 95 _responseData = [[NSMutableArray alloc] init]; |
| 96 } |
| 97 [_responseData addObject:data]; |
| 98 } |
| 99 |
| 100 - (void)URLSession:(NSURLSession*)session |
| 101 dataTask:(NSURLSessionDataTask*)dataTask |
| 102 willCacheResponse:(NSCachedURLResponse*)proposedResponse |
| 103 completionHandler: |
| 104 (void (^)(NSCachedURLResponse* cachedResponse))completionHandler { |
| 105 completionHandler(proposedResponse); |
| 106 } |
| 107 |
| 108 @end |
| 109 |
| 110 namespace cronet { |
| 111 |
| 112 void CronetTestBase::SetUp() { |
| 113 ::testing::Test::SetUp(); |
| 114 grpc_support::StartQuicTestServer(); |
| 115 delegate_ = [[TestDelegate alloc] init]; |
| 116 } |
| 117 |
| 118 void CronetTestBase::TearDown() { |
| 119 grpc_support::ShutdownQuicTestServer(); |
| 120 ::testing::Test::TearDown(); |
| 121 } |
| 122 |
| 123 // Launches the supplied |task| and blocks until it completes, with a timeout |
| 124 // of 1 second. |
| 125 void CronetTestBase::StartDataTaskAndWaitForCompletion( |
| 126 NSURLSessionDataTask* task) { |
| 127 [delegate_ reset]; |
| 128 [task resume]; |
| 129 CHECK([delegate_ waitForDone]); |
| 130 } |
| 131 |
| 132 ::testing::AssertionResult CronetTestBase::IsResponseSuccessful() { |
| 133 if ([delegate_ error]) |
| 134 return ::testing::AssertionFailure() << "error in response: " << |
| 135 [[[delegate_ error] description] |
| 136 cStringUsingEncoding:NSUTF8StringEncoding]; |
| 137 else |
| 138 return ::testing::AssertionSuccess() << "no errors in response"; |
| 139 } |
| 140 |
| 141 std::unique_ptr<net::MockCertVerifier> CronetTestBase::CreateMockCertVerifier( |
| 142 const std::vector<std::string>& certs, |
| 143 bool known_root) { |
| 144 std::unique_ptr<net::MockCertVerifier> mock_cert_verifier( |
| 145 new net::MockCertVerifier()); |
| 146 for (const auto& cert : certs) { |
| 147 net::CertVerifyResult verify_result; |
| 148 verify_result.verified_cert = |
| 149 net::ImportCertFromFile(net::GetTestCertsDirectory(), cert); |
| 150 |
| 151 // By default, HPKP verification is enabled for known trust roots only. |
| 152 verify_result.is_issued_by_known_root = known_root; |
| 153 |
| 154 // Calculate the public key hash and add it to the verify_result. |
| 155 net::HashValue hashValue; |
| 156 CHECK(CalculatePublicKeySha256(*verify_result.verified_cert.get(), |
| 157 &hashValue)); |
| 158 verify_result.public_key_hashes.push_back(hashValue); |
| 159 |
| 160 mock_cert_verifier->AddResultForCert(verify_result.verified_cert.get(), |
| 161 verify_result, net::OK); |
| 162 } |
| 163 return mock_cert_verifier; |
| 164 } |
| 165 |
| 166 bool CronetTestBase::CalculatePublicKeySha256(const net::X509Certificate& cert, |
| 167 net::HashValue* out_hash_value) { |
| 168 // Convert the cert to DER encoded bytes. |
| 169 std::string der_cert_bytes; |
| 170 net::X509Certificate::OSCertHandle cert_handle = cert.os_cert_handle(); |
| 171 if (!net::X509Certificate::GetDEREncoded(cert_handle, &der_cert_bytes)) { |
| 172 LOG(INFO) << "Unable to convert the given cert to DER encoding"; |
| 173 return false; |
| 174 } |
| 175 // Extract the public key from the cert. |
| 176 base::StringPiece spki_bytes; |
| 177 if (!net::asn1::ExtractSPKIFromDERCert(der_cert_bytes, &spki_bytes)) { |
| 178 LOG(INFO) << "Unable to retrieve the public key from the DER cert"; |
| 179 return false; |
| 180 } |
| 181 // Calculate SHA256 hash of public key bytes. |
| 182 out_hash_value->tag = net::HASH_VALUE_SHA256; |
| 183 crypto::SHA256HashString(spki_bytes, out_hash_value->data(), |
| 184 crypto::kSHA256Length); |
| 185 return true; |
| 186 } |
| 187 |
| 188 } // namespace cronet |
| OLD | NEW |