| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <memory> |
| #include <utility> |
| |
| #include "components/grpc_support/test/get_stream_engine.h" |
| |
| #include "base/lazy_instance.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/message_loop/message_pump_type.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/task/single_thread_task_runner.h" |
| #include "base/threading/thread.h" |
| #include "base/time/time.h" |
| #include "components/grpc_support/include/bidirectional_stream_c.h" |
| #include "net/base/host_port_pair.h" |
| #include "net/base/network_isolation_key.h" |
| #include "net/cert/mock_cert_verifier.h" |
| #include "net/dns/mapped_host_resolver.h" |
| #include "net/dns/mock_host_resolver.h" |
| #include "net/http/http_network_session.h" |
| #include "net/http/http_server_properties.h" |
| #include "net/test/cert_test_util.h" |
| #include "net/test/quic_simple_test_server.h" |
| #include "net/test/test_data_directory.h" |
| #include "net/url_request/url_request_context.h" |
| #include "net/url_request/url_request_context_builder.h" |
| #include "net/url_request/url_request_test_util.h" |
| |
| namespace grpc_support { |
| namespace { |
| |
| // URLRequestContextGetter for BidirectionalStreamTest. This is used instead of |
| // net::TestURLRequestContextGetter because the URLRequestContext needs to be |
| // created on the test_io_thread_ for the test, and TestURLRequestContextGetter |
| // does not allow for lazy instantiation of the URLRequestContext if additional |
| // setup is required. |
| class BidirectionalStreamTestURLRequestContextGetter |
| : public net::URLRequestContextGetter { |
| public: |
| BidirectionalStreamTestURLRequestContextGetter( |
| const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) |
| : task_runner_(task_runner) {} |
| |
| BidirectionalStreamTestURLRequestContextGetter( |
| const BidirectionalStreamTestURLRequestContextGetter&) = delete; |
| BidirectionalStreamTestURLRequestContextGetter& operator=( |
| const BidirectionalStreamTestURLRequestContextGetter&) = delete; |
| |
| net::URLRequestContext* GetURLRequestContext() override { |
| if (!request_context_) { |
| auto context_builder = net::CreateTestURLRequestContextBuilder(); |
| auto mock_host_resolver = std::make_unique<net::MockHostResolver>(); |
| auto host_resolver = std::make_unique<net::MappedHostResolver>( |
| std::move(mock_host_resolver)); |
| auto test_cert = net::ImportCertFromFile(net::GetTestCertsDirectory(), |
| "quic-chain.pem"); |
| auto mock_cert_verifier = std::make_unique<net::MockCertVerifier>(); |
| net::CertVerifyResult verify_result; |
| verify_result.verified_cert = test_cert; |
| verify_result.is_issued_by_known_root = true; |
| mock_cert_verifier->AddResultForCert(test_cert, verify_result, net::OK); |
| |
| net::HttpNetworkSessionParams params; |
| params.enable_quic = true; |
| params.enable_http2 = true; |
| |
| context_builder->SetCertVerifier(std::move(mock_cert_verifier)); |
| context_builder->set_host_resolver(std::move(host_resolver)); |
| context_builder->set_http_network_session_params(params); |
| request_context_ = context_builder->Build(); |
| UpdateHostResolverRules(); |
| |
| // Need to enable QUIC for the test server. |
| net::AlternativeService alternative_service(net::kProtoQUIC, "", 443); |
| url::SchemeHostPort quic_hint_server( |
| "https", net::QuicSimpleTestServer::GetHost(), 443); |
| request_context_->http_server_properties()->SetQuicAlternativeService( |
| quic_hint_server, net::NetworkIsolationKey(), alternative_service, |
| base::Time::Max(), quic::ParsedQuicVersionVector()); |
| } |
| return request_context_.get(); |
| } |
| |
| net::MappedHostResolver* host_resolver() { |
| if (!request_context_) { |
| return nullptr; |
| } |
| // This is safe because we set a MappedHostResolver in |
| // GetURLRequestContext(). |
| return static_cast<net::MappedHostResolver*>( |
| request_context_->host_resolver()); |
| } |
| |
| scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() |
| const override { |
| return task_runner_; |
| } |
| |
| void SetTestServerPort(int port) { |
| test_server_port_ = port; |
| UpdateHostResolverRules(); |
| } |
| |
| private: |
| void UpdateHostResolverRules() { |
| if (!host_resolver()) |
| return; |
| host_resolver()->SetRulesFromString( |
| base::StringPrintf("MAP notfound.example.com ~NOTFOUND," |
| "MAP test.example.com 127.0.0.1:%d", |
| test_server_port_)); |
| } |
| ~BidirectionalStreamTestURLRequestContextGetter() override {} |
| |
| int test_server_port_; |
| std::unique_ptr<net::URLRequestContext> request_context_; |
| scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
| }; |
| |
| base::LazyInstance< |
| scoped_refptr<BidirectionalStreamTestURLRequestContextGetter>> |
| ::Leaky g_request_context_getter_ = LAZY_INSTANCE_INITIALIZER; |
| bool g_initialized_ = false; |
| |
| } // namespace |
| |
| void CreateRequestContextGetterIfNecessary() { |
| if (!g_initialized_) { |
| g_initialized_ = true; |
| static base::Thread* test_io_thread_ = |
| new base::Thread("grpc_support_test_io_thread"); |
| base::Thread::Options options; |
| options.message_pump_type = base::MessagePumpType::IO; |
| bool started = test_io_thread_->StartWithOptions(std::move(options)); |
| DCHECK(started); |
| |
| g_request_context_getter_.Get() = |
| new BidirectionalStreamTestURLRequestContextGetter( |
| test_io_thread_->task_runner()); |
| } |
| } |
| |
| stream_engine* GetTestStreamEngine(int port) { |
| CreateRequestContextGetterIfNecessary(); |
| g_request_context_getter_.Get()->SetTestServerPort(port); |
| static stream_engine engine; |
| engine.obj = g_request_context_getter_.Get().get(); |
| return &engine; |
| } |
| |
| void StartTestStreamEngine(int port) {} |
| void ShutdownTestStreamEngine() {} |
| |
| } // namespace grpc_support |