12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671 |
- // Copyright (c) 2012 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 "net/http/http_stream_factory.h"
- #include <stdint.h>
- #include <memory>
- #include <set>
- #include <string>
- #include <tuple>
- #include <utility>
- #include <vector>
- #include "base/compiler_specific.h"
- #include "base/containers/contains.h"
- #include "base/memory/ptr_util.h"
- #include "base/no_destructor.h"
- #include "base/run_loop.h"
- #include "base/strings/strcat.h"
- #include "base/strings/string_piece.h"
- #include "base/test/metrics/histogram_tester.h"
- #include "base/test/scoped_feature_list.h"
- #include "build/build_config.h"
- #include "net/base/completion_once_callback.h"
- #include "net/base/features.h"
- #include "net/base/net_errors.h"
- #include "net/base/network_isolation_key.h"
- #include "net/base/port_util.h"
- #include "net/base/privacy_mode.h"
- #include "net/base/proxy_server.h"
- #include "net/base/schemeful_site.h"
- #include "net/base/test_completion_callback.h"
- #include "net/base/test_proxy_delegate.h"
- #include "net/cert/ct_policy_enforcer.h"
- #include "net/cert/mock_cert_verifier.h"
- #include "net/cert/multi_log_ct_verifier.h"
- #include "net/dns/mock_host_resolver.h"
- #include "net/dns/public/secure_dns_policy.h"
- #include "net/http/bidirectional_stream_impl.h"
- #include "net/http/bidirectional_stream_request_info.h"
- #include "net/http/http_auth_handler_factory.h"
- #include "net/http/http_network_session.h"
- #include "net/http/http_network_session_peer.h"
- #include "net/http/http_network_transaction.h"
- #include "net/http/http_proxy_connect_job.h"
- #include "net/http/http_request_info.h"
- #include "net/http/http_server_properties.h"
- #include "net/http/http_stream.h"
- #include "net/http/transport_security_state.h"
- #include "net/log/net_log_with_source.h"
- #include "net/proxy_resolution/configured_proxy_resolution_service.h"
- #include "net/proxy_resolution/proxy_info.h"
- #include "net/quic/mock_crypto_client_stream_factory.h"
- #include "net/quic/mock_quic_context.h"
- #include "net/quic/quic_http_utils.h"
- #include "net/quic/quic_stream_factory_peer.h"
- #include "net/quic/quic_test_packet_maker.h"
- #include "net/quic/quic_test_packet_printer.h"
- #include "net/socket/client_socket_handle.h"
- #include "net/socket/client_socket_pool.h"
- #include "net/socket/connect_job.h"
- #include "net/socket/mock_client_socket_pool_manager.h"
- #include "net/socket/next_proto.h"
- #include "net/socket/socket_tag.h"
- #include "net/socket/socket_test_util.h"
- #include "net/socket/socks_connect_job.h"
- #include "net/socket/ssl_connect_job.h"
- #include "net/socket/transport_connect_job.h"
- #include "net/spdy/spdy_session.h"
- #include "net/spdy/spdy_session_pool.h"
- #include "net/spdy/spdy_test_util_common.h"
- #include "net/ssl/ssl_config_service.h"
- #include "net/ssl/ssl_config_service_defaults.h"
- #include "net/test/cert_test_util.h"
- #include "net/test/gtest_util.h"
- #include "net/test/test_data_directory.h"
- #include "net/test/test_with_task_environment.h"
- #include "net/third_party/quiche/src/quiche/quic/core/quic_server_id.h"
- #include "net/third_party/quiche/src/quiche/quic/core/quic_utils.h"
- #include "net/third_party/quiche/src/quiche/quic/test_tools/crypto_test_utils.h"
- #include "net/third_party/quiche/src/quiche/quic/test_tools/mock_random.h"
- #include "net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.h"
- #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
- // This file can be included from net/http even though
- // it is in net/websockets because it doesn't
- // introduce any link dependency to net/websockets.
- #include "net/websockets/websocket_handshake_stream_base.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- #include "url/gurl.h"
- #include "url/scheme_host_port.h"
- #include "url/url_constants.h"
- using ::testing::Contains;
- using ::testing::ElementsAre;
- using ::testing::IsEmpty;
- using ::testing::Key;
- using ::testing::SizeIs;
- using net::test::IsError;
- using net::test::IsOk;
- namespace base {
- class Value;
- } // namespace base
- namespace net {
- class BidirectionalStreamImpl;
- class WebSocketEndpointLockManager;
- namespace {
- class MockWebSocketHandshakeStream : public WebSocketHandshakeStreamBase {
- public:
- enum StreamType {
- kStreamTypeBasic,
- kStreamTypeSpdy,
- };
- explicit MockWebSocketHandshakeStream(StreamType type) : type_(type) {}
- ~MockWebSocketHandshakeStream() override = default;
- StreamType type() const { return type_; }
- // HttpStream methods
- void RegisterRequest(const HttpRequestInfo* request_info) override {}
- int InitializeStream(bool can_send_early,
- RequestPriority priority,
- const NetLogWithSource& net_log,
- CompletionOnceCallback callback) override {
- return ERR_IO_PENDING;
- }
- int SendRequest(const HttpRequestHeaders& request_headers,
- HttpResponseInfo* response,
- CompletionOnceCallback callback) override {
- return ERR_IO_PENDING;
- }
- int ReadResponseHeaders(CompletionOnceCallback callback) override {
- return ERR_IO_PENDING;
- }
- int ReadResponseBody(IOBuffer* buf,
- int buf_len,
- CompletionOnceCallback callback) override {
- return ERR_IO_PENDING;
- }
- void Close(bool not_reusable) override {}
- bool IsResponseBodyComplete() const override { return false; }
- bool IsConnectionReused() const override { return false; }
- void SetConnectionReused() override {}
- bool CanReuseConnection() const override { return false; }
- int64_t GetTotalReceivedBytes() const override { return 0; }
- int64_t GetTotalSentBytes() const override { return 0; }
- bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
- return false;
- }
- bool GetAlternativeService(
- AlternativeService* alternative_service) const override {
- return false;
- }
- void GetSSLInfo(SSLInfo* ssl_info) override {}
- void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {}
- int GetRemoteEndpoint(IPEndPoint* endpoint) override {
- return ERR_UNEXPECTED;
- }
- void Drain(HttpNetworkSession* session) override {}
- void PopulateNetErrorDetails(NetErrorDetails* details) override { return; }
- void SetPriority(RequestPriority priority) override {}
- std::unique_ptr<HttpStream> RenewStreamForAuth() override { return nullptr; }
- const std::set<std::string>& GetDnsAliases() const override {
- static const base::NoDestructor<std::set<std::string>> nullset_result;
- return *nullset_result;
- }
- base::StringPiece GetAcceptChViaAlps() const override { return {}; }
- std::unique_ptr<WebSocketStream> Upgrade() override { return nullptr; }
- base::WeakPtr<WebSocketHandshakeStreamBase> GetWeakPtr() override {
- return weak_ptr_factory_.GetWeakPtr();
- }
- private:
- const StreamType type_;
- base::WeakPtrFactory<MockWebSocketHandshakeStream> weak_ptr_factory_{this};
- };
- // HttpStreamFactory subclass that can wait until a preconnect is complete.
- class MockHttpStreamFactoryForPreconnect : public HttpStreamFactory {
- public:
- explicit MockHttpStreamFactoryForPreconnect(HttpNetworkSession* session)
- : HttpStreamFactory(session) {}
- ~MockHttpStreamFactoryForPreconnect() override = default;
- void WaitForPreconnects() {
- while (!preconnect_done_) {
- waiting_for_preconnect_ = true;
- loop_.Run();
- waiting_for_preconnect_ = false;
- }
- }
- private:
- // HttpStreamFactory methods.
- void OnPreconnectsCompleteInternal() override {
- preconnect_done_ = true;
- if (waiting_for_preconnect_)
- loop_.QuitWhenIdle();
- }
- bool preconnect_done_ = false;
- bool waiting_for_preconnect_ = false;
- base::RunLoop loop_;
- };
- class StreamRequestWaiter : public HttpStreamRequest::Delegate {
- public:
- StreamRequestWaiter() = default;
- StreamRequestWaiter(const StreamRequestWaiter&) = delete;
- StreamRequestWaiter& operator=(const StreamRequestWaiter&) = delete;
- // HttpStreamRequest::Delegate
- void OnStreamReady(const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- std::unique_ptr<HttpStream> stream) override {
- stream_done_ = true;
- if (loop_)
- loop_->Quit();
- stream_ = std::move(stream);
- used_ssl_config_ = used_ssl_config;
- used_proxy_info_ = used_proxy_info;
- }
- void OnWebSocketHandshakeStreamReady(
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- std::unique_ptr<WebSocketHandshakeStreamBase> stream) override {
- stream_done_ = true;
- if (loop_)
- loop_->Quit();
- websocket_stream_ = std::move(stream);
- used_ssl_config_ = used_ssl_config;
- used_proxy_info_ = used_proxy_info;
- }
- void OnBidirectionalStreamImplReady(
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- std::unique_ptr<BidirectionalStreamImpl> stream) override {
- stream_done_ = true;
- if (loop_)
- loop_->Quit();
- bidirectional_stream_impl_ = std::move(stream);
- used_ssl_config_ = used_ssl_config;
- used_proxy_info_ = used_proxy_info;
- }
- void OnStreamFailed(int status,
- const NetErrorDetails& net_error_details,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- ResolveErrorInfo resolve_error_info) override {
- stream_done_ = true;
- if (loop_)
- loop_->Quit();
- used_ssl_config_ = used_ssl_config;
- error_status_ = status;
- }
- void OnCertificateError(int status,
- const SSLConfig& used_ssl_config,
- const SSLInfo& ssl_info) override {}
- void OnNeedsProxyAuth(const HttpResponseInfo& proxy_response,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- HttpAuthController* auth_controller) override {}
- void OnNeedsClientAuth(const SSLConfig& used_ssl_config,
- SSLCertRequestInfo* cert_info) override {}
- void OnQuicBroken() override {}
- void WaitForStream() {
- stream_done_ = false;
- loop_ = std::make_unique<base::RunLoop>();
- while (!stream_done_)
- loop_->Run();
- loop_.reset();
- }
- const SSLConfig& used_ssl_config() const { return used_ssl_config_; }
- const ProxyInfo& used_proxy_info() const { return used_proxy_info_; }
- HttpStream* stream() { return stream_.get(); }
- MockWebSocketHandshakeStream* websocket_stream() {
- return static_cast<MockWebSocketHandshakeStream*>(websocket_stream_.get());
- }
- BidirectionalStreamImpl* bidirectional_stream_impl() {
- return bidirectional_stream_impl_.get();
- }
- bool stream_done() const { return stream_done_; }
- int error_status() const { return error_status_; }
- protected:
- bool stream_done_ = false;
- std::unique_ptr<base::RunLoop> loop_;
- std::unique_ptr<HttpStream> stream_;
- std::unique_ptr<WebSocketHandshakeStreamBase> websocket_stream_;
- std::unique_ptr<BidirectionalStreamImpl> bidirectional_stream_impl_;
- SSLConfig used_ssl_config_;
- ProxyInfo used_proxy_info_;
- int error_status_ = OK;
- };
- class WebSocketBasicHandshakeStream : public MockWebSocketHandshakeStream {
- public:
- explicit WebSocketBasicHandshakeStream(
- std::unique_ptr<ClientSocketHandle> connection)
- : MockWebSocketHandshakeStream(kStreamTypeBasic),
- connection_(std::move(connection)) {}
- ~WebSocketBasicHandshakeStream() override {
- connection_->socket()->Disconnect();
- }
- ClientSocketHandle* connection() { return connection_.get(); }
- private:
- std::unique_ptr<ClientSocketHandle> connection_;
- };
- class WebSocketStreamCreateHelper
- : public WebSocketHandshakeStreamBase::CreateHelper {
- public:
- ~WebSocketStreamCreateHelper() override = default;
- std::unique_ptr<WebSocketHandshakeStreamBase> CreateBasicStream(
- std::unique_ptr<ClientSocketHandle> connection,
- bool using_proxy,
- WebSocketEndpointLockManager* websocket_endpoint_lock_manager) override {
- return std::make_unique<WebSocketBasicHandshakeStream>(
- std::move(connection));
- }
- std::unique_ptr<WebSocketHandshakeStreamBase> CreateHttp2Stream(
- base::WeakPtr<SpdySession> session,
- std::set<std::string> dns_aliases) override {
- NOTREACHED();
- return nullptr;
- }
- };
- struct TestCase {
- int num_streams;
- bool ssl;
- };
- TestCase kTests[] = {
- {1, false},
- {2, false},
- {1, true},
- {2, true},
- };
- void PreconnectHelperForURL(int num_streams,
- const GURL& url,
- NetworkIsolationKey network_isolation_key,
- SecureDnsPolicy secure_dns_policy,
- HttpNetworkSession* session) {
- HttpNetworkSessionPeer peer(session);
- auto mock_factory =
- std::make_unique<MockHttpStreamFactoryForPreconnect>(session);
- auto* mock_factory_ptr = mock_factory.get();
- peer.SetHttpStreamFactory(std::move(mock_factory));
- HttpRequestInfo request;
- request.method = "GET";
- request.url = url;
- request.load_flags = 0;
- request.network_isolation_key = network_isolation_key;
- request.secure_dns_policy = secure_dns_policy;
- request.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- session->http_stream_factory()->PreconnectStreams(num_streams, request);
- mock_factory_ptr->WaitForPreconnects();
- }
- void PreconnectHelper(const TestCase& test, HttpNetworkSession* session) {
- GURL url =
- test.ssl ? GURL("https://www.google.com") : GURL("http://www.google.com");
- PreconnectHelperForURL(test.num_streams, url, NetworkIsolationKey(),
- SecureDnsPolicy::kAllow, session);
- }
- ClientSocketPool::GroupId GetGroupId(const TestCase& test) {
- if (test.ssl) {
- return ClientSocketPool::GroupId(
- url::SchemeHostPort(url::kHttpsScheme, "www.google.com", 443),
- PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
- SecureDnsPolicy::kAllow);
- }
- return ClientSocketPool::GroupId(
- url::SchemeHostPort(url::kHttpScheme, "www.google.com", 80),
- PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
- SecureDnsPolicy::kAllow);
- }
- class CapturePreconnectsTransportSocketPool : public TransportClientSocketPool {
- public:
- explicit CapturePreconnectsTransportSocketPool(
- const CommonConnectJobParams* common_connect_job_params)
- : TransportClientSocketPool(0,
- 0,
- base::TimeDelta(),
- ProxyServer::Direct(),
- false /* is_for_websockets */,
- common_connect_job_params) {}
- int last_num_streams() const { return last_num_streams_; }
- const ClientSocketPool::GroupId& last_group_id() const {
- return last_group_id_;
- }
- // Resets |last_num_streams_| and |last_group_id_| default values.
- void reset() {
- last_num_streams_ = -1;
- // Group ID that shouldn't match much.
- last_group_id_ = ClientSocketPool::GroupId(
- url::SchemeHostPort(url::kHttpsScheme,
- "unexpected.to.conflict.with.anything.test", 9999),
- PrivacyMode::PRIVACY_MODE_ENABLED, NetworkIsolationKey(),
- SecureDnsPolicy::kAllow);
- }
- int RequestSocket(
- const ClientSocketPool::GroupId& group_id,
- scoped_refptr<ClientSocketPool::SocketParams> socket_params,
- const absl::optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
- RequestPriority priority,
- const SocketTag& socket_tag,
- ClientSocketPool::RespectLimits respect_limits,
- ClientSocketHandle* handle,
- CompletionOnceCallback callback,
- const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback,
- const NetLogWithSource& net_log) override {
- ADD_FAILURE();
- return ERR_UNEXPECTED;
- }
- int RequestSockets(
- const ClientSocketPool::GroupId& group_id,
- scoped_refptr<ClientSocketPool::SocketParams> socket_params,
- const absl::optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
- int num_sockets,
- CompletionOnceCallback callback,
- const NetLogWithSource& net_log) override {
- last_num_streams_ = num_sockets;
- last_group_id_ = group_id;
- return OK;
- }
- void CancelRequest(const ClientSocketPool::GroupId& group_id,
- ClientSocketHandle* handle,
- bool cancel_connect_job) override {
- ADD_FAILURE();
- }
- void ReleaseSocket(const ClientSocketPool::GroupId& group_id,
- std::unique_ptr<StreamSocket> socket,
- int64_t generation) override {
- ADD_FAILURE();
- }
- void CloseIdleSockets(const char* net_log_reason_utf8) override {
- ADD_FAILURE();
- }
- int IdleSocketCount() const override {
- ADD_FAILURE();
- return 0;
- }
- size_t IdleSocketCountInGroup(
- const ClientSocketPool::GroupId& group_id) const override {
- ADD_FAILURE();
- return 0;
- }
- LoadState GetLoadState(const ClientSocketPool::GroupId& group_id,
- const ClientSocketHandle* handle) const override {
- ADD_FAILURE();
- return LOAD_STATE_IDLE;
- }
- private:
- int last_num_streams_ = -1;
- ClientSocketPool::GroupId last_group_id_;
- };
- using HttpStreamFactoryTest = TestWithTaskEnvironment;
- TEST_F(HttpStreamFactoryTest, PreconnectDirect) {
- for (const auto& test : kTests) {
- SpdySessionDependencies session_deps(
- ConfiguredProxyResolutionService::CreateDirect());
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- HttpNetworkSessionPeer peer(session.get());
- CommonConnectJobParams common_connect_job_params =
- session->CreateCommonConnectJobParams();
- std::unique_ptr<CapturePreconnectsTransportSocketPool>
- owned_transport_conn_pool =
- std::make_unique<CapturePreconnectsTransportSocketPool>(
- &common_connect_job_params);
- CapturePreconnectsTransportSocketPool* transport_conn_pool =
- owned_transport_conn_pool.get();
- auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
- mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
- std::move(owned_transport_conn_pool));
- peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
- PreconnectHelper(test, session.get());
- EXPECT_EQ(test.num_streams, transport_conn_pool->last_num_streams());
- EXPECT_EQ(GetGroupId(test), transport_conn_pool->last_group_id());
- }
- }
- TEST_F(HttpStreamFactoryTest, PreconnectHttpProxy) {
- for (const auto& test : kTests) {
- SpdySessionDependencies session_deps(
- ConfiguredProxyResolutionService::CreateFixedForTest(
- "http_proxy", TRAFFIC_ANNOTATION_FOR_TESTS));
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- HttpNetworkSessionPeer peer(session.get());
- ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
- HostPortPair("http_proxy", 80));
- CommonConnectJobParams common_connect_job_params =
- session->CreateCommonConnectJobParams();
- auto http_proxy_pool =
- std::make_unique<CapturePreconnectsTransportSocketPool>(
- &common_connect_job_params);
- auto* http_proxy_pool_ptr = http_proxy_pool.get();
- auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
- mock_pool_manager->SetSocketPool(proxy_server, std::move(http_proxy_pool));
- peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
- PreconnectHelper(test, session.get());
- EXPECT_EQ(test.num_streams, http_proxy_pool_ptr->last_num_streams());
- EXPECT_EQ(GetGroupId(test), http_proxy_pool_ptr->last_group_id());
- }
- }
- TEST_F(HttpStreamFactoryTest, PreconnectSocksProxy) {
- for (const auto& test : kTests) {
- SpdySessionDependencies session_deps(
- ConfiguredProxyResolutionService::CreateFixedForTest(
- "socks4://socks_proxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS));
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- HttpNetworkSessionPeer peer(session.get());
- ProxyServer proxy_server(ProxyServer::SCHEME_SOCKS4,
- HostPortPair("socks_proxy", 1080));
- CommonConnectJobParams common_connect_job_params =
- session->CreateCommonConnectJobParams();
- auto socks_proxy_pool =
- std::make_unique<CapturePreconnectsTransportSocketPool>(
- &common_connect_job_params);
- auto* socks_proxy_pool_ptr = socks_proxy_pool.get();
- auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
- mock_pool_manager->SetSocketPool(proxy_server, std::move(socks_proxy_pool));
- peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
- PreconnectHelper(test, session.get());
- EXPECT_EQ(test.num_streams, socks_proxy_pool_ptr->last_num_streams());
- EXPECT_EQ(GetGroupId(test), socks_proxy_pool_ptr->last_group_id());
- }
- }
- TEST_F(HttpStreamFactoryTest, PreconnectDirectWithExistingSpdySession) {
- for (const auto& test : kTests) {
- SpdySessionDependencies session_deps(
- ConfiguredProxyResolutionService::CreateDirect());
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- HttpNetworkSessionPeer peer(session.get());
- // Put a SpdySession in the pool.
- HostPortPair host_port_pair("www.google.com", 443);
- SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
- PRIVACY_MODE_DISABLED,
- SpdySessionKey::IsProxySession::kFalse, SocketTag(),
- NetworkIsolationKey(), SecureDnsPolicy::kAllow);
- std::ignore = CreateFakeSpdySession(session->spdy_session_pool(), key);
- CommonConnectJobParams common_connect_job_params =
- session->CreateCommonConnectJobParams();
- std::unique_ptr<CapturePreconnectsTransportSocketPool>
- owned_transport_conn_pool =
- std::make_unique<CapturePreconnectsTransportSocketPool>(
- &common_connect_job_params);
- CapturePreconnectsTransportSocketPool* transport_conn_pool =
- owned_transport_conn_pool.get();
- auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
- mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
- std::move(owned_transport_conn_pool));
- peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
- PreconnectHelper(test, session.get());
- // We shouldn't be preconnecting if we have an existing session, which is
- // the case for https://www.google.com.
- if (test.ssl)
- EXPECT_EQ(-1, transport_conn_pool->last_num_streams());
- else
- EXPECT_EQ(test.num_streams, transport_conn_pool->last_num_streams());
- }
- }
- // Verify that preconnects to unsafe ports are cancelled before they reach
- // the SocketPool.
- TEST_F(HttpStreamFactoryTest, PreconnectUnsafePort) {
- ASSERT_FALSE(IsPortAllowedForScheme(7, "http"));
- SpdySessionDependencies session_deps(
- ConfiguredProxyResolutionService::CreateDirect());
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- HttpNetworkSessionPeer peer(session.get());
- CommonConnectJobParams common_connect_job_params =
- session->CreateCommonConnectJobParams();
- std::unique_ptr<CapturePreconnectsTransportSocketPool>
- owned_transport_conn_pool =
- std::make_unique<CapturePreconnectsTransportSocketPool>(
- &common_connect_job_params);
- CapturePreconnectsTransportSocketPool* transport_conn_pool =
- owned_transport_conn_pool.get();
- auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
- mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
- std::move(owned_transport_conn_pool));
- peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
- PreconnectHelperForURL(1, GURL("http://www.google.com:7"),
- NetworkIsolationKey(), SecureDnsPolicy::kAllow,
- session.get());
- EXPECT_EQ(-1, transport_conn_pool->last_num_streams());
- }
- // Verify that preconnects use the specified NetworkIsolationKey.
- TEST_F(HttpStreamFactoryTest, PreconnectNetworkIsolationKey) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(
- features::kPartitionConnectionsByNetworkIsolationKey);
- SpdySessionDependencies session_deps(
- ConfiguredProxyResolutionService::CreateDirect());
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- HttpNetworkSessionPeer peer(session.get());
- CommonConnectJobParams common_connect_job_params =
- session->CreateCommonConnectJobParams();
- std::unique_ptr<CapturePreconnectsTransportSocketPool>
- owned_transport_conn_pool =
- std::make_unique<CapturePreconnectsTransportSocketPool>(
- &common_connect_job_params);
- CapturePreconnectsTransportSocketPool* transport_conn_pool =
- owned_transport_conn_pool.get();
- auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
- mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
- std::move(owned_transport_conn_pool));
- peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
- const GURL kURL("http://foo.test/");
- SchemefulSite kSiteFoo(GURL("http://foo.test"));
- SchemefulSite kSiteBar(GURL("http://bar.test"));
- const NetworkIsolationKey kKey1(kSiteFoo, kSiteFoo);
- const NetworkIsolationKey kKey2(kSiteBar, kSiteBar);
- PreconnectHelperForURL(1, kURL, kKey1, SecureDnsPolicy::kAllow,
- session.get());
- EXPECT_EQ(1, transport_conn_pool->last_num_streams());
- EXPECT_EQ(kKey1,
- transport_conn_pool->last_group_id().network_isolation_key());
- PreconnectHelperForURL(2, kURL, kKey2, SecureDnsPolicy::kAllow,
- session.get());
- EXPECT_EQ(2, transport_conn_pool->last_num_streams());
- EXPECT_EQ(kKey2,
- transport_conn_pool->last_group_id().network_isolation_key());
- }
- // Verify that preconnects use the specified Secure DNS Tag.
- TEST_F(HttpStreamFactoryTest, PreconnectDisableSecureDns) {
- SpdySessionDependencies session_deps(
- ConfiguredProxyResolutionService::CreateDirect());
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- HttpNetworkSessionPeer peer(session.get());
- CommonConnectJobParams common_connect_job_params =
- session->CreateCommonConnectJobParams();
- std::unique_ptr<CapturePreconnectsTransportSocketPool>
- owned_transport_conn_pool =
- std::make_unique<CapturePreconnectsTransportSocketPool>(
- &common_connect_job_params);
- CapturePreconnectsTransportSocketPool* transport_conn_pool =
- owned_transport_conn_pool.get();
- auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
- mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
- std::move(owned_transport_conn_pool));
- peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
- const GURL kURL("http://foo.test/");
- SchemefulSite kSiteFoo(GURL("http://foo.test"));
- SchemefulSite kSiteBar(GURL("http://bar.test"));
- PreconnectHelperForURL(1, kURL, NetworkIsolationKey(),
- SecureDnsPolicy::kAllow, session.get());
- EXPECT_EQ(1, transport_conn_pool->last_num_streams());
- EXPECT_EQ(SecureDnsPolicy::kAllow,
- transport_conn_pool->last_group_id().secure_dns_policy());
- PreconnectHelperForURL(2, kURL, NetworkIsolationKey(),
- SecureDnsPolicy::kDisable, session.get());
- EXPECT_EQ(2, transport_conn_pool->last_num_streams());
- EXPECT_EQ(SecureDnsPolicy::kDisable,
- transport_conn_pool->last_group_id().secure_dns_policy());
- }
- TEST_F(HttpStreamFactoryTest, JobNotifiesProxy) {
- const char* kProxyString = "PROXY bad:99; PROXY maybe:80; DIRECT";
- SpdySessionDependencies session_deps(
- ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
- kProxyString, TRAFFIC_ANNOTATION_FOR_TESTS));
- // First connection attempt fails
- StaticSocketDataProvider socket_data1;
- socket_data1.set_connect_data(MockConnect(ASYNC, ERR_ADDRESS_UNREACHABLE));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data1);
- // Second connection attempt succeeds
- StaticSocketDataProvider socket_data2;
- socket_data2.set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data2);
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- // Now request a stream. It should succeed using the second proxy in the
- // list.
- HttpRequestInfo request_info;
- request_info.method = "GET";
- request_info.url = GURL("http://www.google.com");
- request_info.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- SSLConfig ssl_config;
- StreamRequestWaiter waiter;
- std::unique_ptr<HttpStreamRequest> request(
- session->http_stream_factory()->RequestStream(
- request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter.WaitForStream();
- // The proxy that failed should now be known to the proxy_resolution_service
- // as bad.
- const ProxyRetryInfoMap& retry_info =
- session->proxy_resolution_service()->proxy_retry_info();
- EXPECT_EQ(1u, retry_info.size());
- auto iter = retry_info.find("bad:99");
- EXPECT_TRUE(iter != retry_info.end());
- }
- // This test requests a stream for an https:// URL using an HTTP proxy.
- // The proxy will fail to establish a tunnel via connect, and the resolved
- // proxy list includes a fallback to DIRECT.
- //
- // The expected behavior is that proxy fallback does NOT occur, even though the
- // request might work using the fallback. This is a regression test for
- // https://crbug.com/680837.
- TEST_F(HttpStreamFactoryTest, NoProxyFallbackOnTunnelFail) {
- const char* kProxyString = "PROXY bad:99; DIRECT";
- SpdySessionDependencies session_deps(
- ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
- kProxyString, TRAFFIC_ANNOTATION_FOR_TESTS));
- // A 404 in response to a CONNECT will trigger
- // ERR_TUNNEL_CONNECTION_FAILED.
- MockRead data_reads[] = {
- MockRead("HTTP/1.1 404 Not Found\r\n\r\n"), MockRead(SYNCHRONOUS, OK),
- };
- // Simulate a failure during CONNECT to bad:99.
- StaticSocketDataProvider socket_data1(data_reads, base::span<MockWrite>());
- socket_data1.set_connect_data(MockConnect(SYNCHRONOUS, OK));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data1);
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- // Request a stream for an https:// URL. The exact URL doesn't matter for
- // this test, since it mocks a failure immediately when establishing a
- // tunnel through the proxy.
- HttpRequestInfo request_info;
- request_info.method = "GET";
- request_info.url = GURL("https://www.google.com");
- request_info.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- SSLConfig ssl_config;
- StreamRequestWaiter waiter;
- std::unique_ptr<HttpStreamRequest> request(
- session->http_stream_factory()->RequestStream(
- request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter.WaitForStream();
- // The stream should have failed, since the proxy server failed to
- // establish a tunnel.
- ASSERT_THAT(waiter.error_status(), IsError(ERR_TUNNEL_CONNECTION_FAILED));
- // The proxy should NOT have been marked as bad.
- const ProxyRetryInfoMap& retry_info =
- session->proxy_resolution_service()->proxy_retry_info();
- EXPECT_EQ(0u, retry_info.size());
- }
- // List of errors that are used in the tests related to QUIC proxy.
- const int quic_proxy_test_mock_errors[] = {
- ERR_PROXY_CONNECTION_FAILED,
- ERR_NAME_NOT_RESOLVED,
- ERR_ADDRESS_UNREACHABLE,
- ERR_CONNECTION_CLOSED,
- ERR_CONNECTION_TIMED_OUT,
- ERR_CONNECTION_RESET,
- ERR_CONNECTION_REFUSED,
- ERR_CONNECTION_ABORTED,
- ERR_TIMED_OUT,
- ERR_SOCKS_CONNECTION_FAILED,
- ERR_PROXY_CERTIFICATE_INVALID,
- ERR_QUIC_PROTOCOL_ERROR,
- ERR_QUIC_HANDSHAKE_FAILED,
- ERR_SSL_PROTOCOL_ERROR,
- ERR_MSG_TOO_BIG,
- };
- // Tests that a bad QUIC proxy is added to the list of bad proxies.
- TEST_F(HttpStreamFactoryTest, QuicProxyMarkedAsBad) {
- for (int quic_proxy_test_mock_error : quic_proxy_test_mock_errors) {
- std::unique_ptr<ProxyResolutionService> proxy_resolution_service =
- ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
- "QUIC bad:99; DIRECT", TRAFFIC_ANNOTATION_FOR_TESTS);
- HttpNetworkSessionParams session_params;
- session_params.enable_quic = true;
- HttpNetworkSessionContext session_context;
- SSLConfigServiceDefaults ssl_config_service;
- HttpServerProperties http_server_properties;
- MockClientSocketFactory socket_factory;
- session_context.client_socket_factory = &socket_factory;
- MockHostResolver host_resolver;
- session_context.host_resolver = &host_resolver;
- MockCertVerifier cert_verifier;
- session_context.cert_verifier = &cert_verifier;
- TransportSecurityState transport_security_state;
- session_context.transport_security_state = &transport_security_state;
- DefaultCTPolicyEnforcer ct_policy_enforcer;
- QuicContext quic_context;
- session_context.ct_policy_enforcer = &ct_policy_enforcer;
- session_context.proxy_resolution_service = proxy_resolution_service.get();
- session_context.ssl_config_service = &ssl_config_service;
- session_context.http_server_properties = &http_server_properties;
- session_context.quic_context = &quic_context;
- host_resolver.rules()->AddRule("www.google.com", "2.3.4.5");
- host_resolver.rules()->AddRule("bad", "1.2.3.4");
- auto session =
- std::make_unique<HttpNetworkSession>(session_params, session_context);
- session->quic_stream_factory()
- ->set_is_quic_known_to_work_on_current_network(true);
- StaticSocketDataProvider socket_data1;
- socket_data1.set_connect_data(
- MockConnect(ASYNC, quic_proxy_test_mock_error));
- socket_factory.AddSocketDataProvider(&socket_data1);
- // Second connection attempt succeeds.
- StaticSocketDataProvider socket_data2;
- socket_data2.set_connect_data(MockConnect(ASYNC, OK));
- socket_factory.AddSocketDataProvider(&socket_data2);
- // Now request a stream. It should succeed using the second proxy in the
- // list.
- HttpRequestInfo request_info;
- request_info.method = "GET";
- request_info.url = GURL("http://www.google.com");
- request_info.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- SSLConfig ssl_config;
- StreamRequestWaiter waiter;
- std::unique_ptr<HttpStreamRequest> request(
- session->http_stream_factory()->RequestStream(
- request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter.WaitForStream();
- // The proxy that failed should now be known to the
- // proxy_resolution_service as bad.
- const ProxyRetryInfoMap& retry_info =
- session->proxy_resolution_service()->proxy_retry_info();
- EXPECT_EQ(1u, retry_info.size()) << quic_proxy_test_mock_error;
- EXPECT_TRUE(waiter.used_proxy_info().is_direct());
- auto iter = retry_info.find("quic://bad:99");
- EXPECT_TRUE(iter != retry_info.end()) << quic_proxy_test_mock_error;
- }
- }
- // BidirectionalStreamImpl::Delegate to wait until response headers are
- // received.
- class TestBidirectionalDelegate : public BidirectionalStreamImpl::Delegate {
- public:
- void WaitUntilDone() { loop_.Run(); }
- const spdy::Http2HeaderBlock& response_headers() const {
- return response_headers_;
- }
- private:
- void OnStreamReady(bool request_headers_sent) override {}
- void OnHeadersReceived(
- const spdy::Http2HeaderBlock& response_headers) override {
- response_headers_ = response_headers.Clone();
- loop_.Quit();
- }
- void OnDataRead(int bytes_read) override { NOTREACHED(); }
- void OnDataSent() override { NOTREACHED(); }
- void OnTrailersReceived(const spdy::Http2HeaderBlock& trailers) override {
- NOTREACHED();
- }
- void OnFailed(int error) override { NOTREACHED(); }
- base::RunLoop loop_;
- spdy::Http2HeaderBlock response_headers_;
- };
- // Helper class to encapsulate MockReads and MockWrites for QUIC.
- // Simplify ownership issues and the interaction with the MockSocketFactory.
- class MockQuicData {
- public:
- explicit MockQuicData(quic::ParsedQuicVersion version) : printer_(version) {}
- ~MockQuicData() = default;
- void AddRead(std::unique_ptr<quic::QuicEncryptedPacket> packet) {
- reads_.emplace_back(ASYNC, packet->data(), packet->length(),
- packet_number_++);
- packets_.push_back(std::move(packet));
- }
- void AddRead(IoMode mode, int rv) {
- reads_.emplace_back(mode, rv, packet_number_++);
- }
- void AddWrite(std::unique_ptr<quic::QuicEncryptedPacket> packet) {
- writes_.emplace_back(SYNCHRONOUS, packet->data(), packet->length(),
- packet_number_++);
- packets_.push_back(std::move(packet));
- }
- void AddSocketDataToFactory(MockClientSocketFactory* factory) {
- socket_data_ = std::make_unique<SequencedSocketData>(reads_, writes_);
- socket_data_->set_printer(&printer_);
- factory->AddSocketDataProvider(socket_data_.get());
- }
- private:
- std::vector<std::unique_ptr<quic::QuicEncryptedPacket>> packets_;
- std::vector<MockWrite> writes_;
- std::vector<MockRead> reads_;
- size_t packet_number_ = 0;
- QuicPacketPrinter printer_;
- std::unique_ptr<SequencedSocketData> socket_data_;
- };
- } // namespace
- TEST_F(HttpStreamFactoryTest, UsePreConnectIfNoZeroRTT) {
- for (int num_streams = 1; num_streams < 3; ++num_streams) {
- GURL url = GURL("https://www.google.com");
- SpdySessionDependencies session_deps(
- ConfiguredProxyResolutionService::CreateFixedForTest(
- "http_proxy", TRAFFIC_ANNOTATION_FOR_TESTS));
- // Setup params to disable preconnect, but QUIC doesn't 0RTT.
- HttpNetworkSessionParams session_params =
- SpdySessionDependencies::CreateSessionParams(&session_deps);
- session_params.enable_quic = true;
- // Set up QUIC as alternative_service.
- HttpServerProperties http_server_properties;
- const AlternativeService alternative_service(kProtoQUIC, url.host().c_str(),
- url.IntPort());
- base::Time expiration = base::Time::Now() + base::Days(1);
- HostPortPair host_port_pair(alternative_service.host_port_pair());
- url::SchemeHostPort server("https", host_port_pair.host(),
- host_port_pair.port());
- http_server_properties.SetQuicAlternativeService(
- server, NetworkIsolationKey(), alternative_service, expiration,
- DefaultSupportedQuicVersions());
- HttpNetworkSessionContext session_context =
- SpdySessionDependencies::CreateSessionContext(&session_deps);
- session_context.http_server_properties = &http_server_properties;
- auto session =
- std::make_unique<HttpNetworkSession>(session_params, session_context);
- HttpNetworkSessionPeer peer(session.get());
- ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
- HostPortPair("http_proxy", 80));
- CommonConnectJobParams common_connect_job_params =
- session->CreateCommonConnectJobParams();
- auto http_proxy_pool =
- std::make_unique<CapturePreconnectsTransportSocketPool>(
- &common_connect_job_params);
- auto* http_proxy_pool_ptr = http_proxy_pool.get();
- auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
- mock_pool_manager->SetSocketPool(proxy_server, std::move(http_proxy_pool));
- peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
- PreconnectHelperForURL(num_streams, url, NetworkIsolationKey(),
- SecureDnsPolicy::kAllow, session.get());
- EXPECT_EQ(num_streams, http_proxy_pool_ptr->last_num_streams());
- }
- }
- namespace {
- // Return count of distinct groups in given socket pool.
- int GetSocketPoolGroupCount(ClientSocketPool* pool) {
- int count = 0;
- base::Value dict = pool->GetInfoAsValue("", "");
- EXPECT_TRUE(dict.is_dict());
- const base::Value::Dict* groups = dict.GetDict().FindDict("groups");
- if (groups) {
- count = groups->size();
- }
- return count;
- }
- // Return count of distinct spdy sessions.
- int GetSpdySessionCount(HttpNetworkSession* session) {
- std::unique_ptr<base::Value> value(
- session->spdy_session_pool()->SpdySessionPoolInfoToValue());
- if (!value || !value->is_list())
- return -1;
- return value->GetList().size();
- }
- // Return count of sockets handed out by a given socket pool.
- int GetHandedOutSocketCount(ClientSocketPool* pool) {
- base::Value dict = pool->GetInfoAsValue("", "");
- EXPECT_TRUE(dict.is_dict());
- return dict.GetDict().FindInt("handed_out_socket_count").value_or(-1);
- }
- // Return count of distinct QUIC sessions.
- int GetQuicSessionCount(HttpNetworkSession* session) {
- base::Value dict(session->QuicInfoToValue());
- base::Value::List* session_list = dict.GetDict().FindList("sessions");
- if (!session_list)
- return -1;
- return session_list->size();
- }
- TEST_F(HttpStreamFactoryTest, PrivacyModeUsesDifferentSocketPoolGroup) {
- SpdySessionDependencies session_deps(
- ConfiguredProxyResolutionService::CreateDirect());
- StaticSocketDataProvider socket_data_1;
- socket_data_1.set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data_1);
- StaticSocketDataProvider socket_data_2;
- socket_data_2.set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data_2);
- StaticSocketDataProvider socket_data_3;
- socket_data_3.set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data_3);
- SSLSocketDataProvider ssl_1(ASYNC, OK);
- session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_1);
- SSLSocketDataProvider ssl_2(ASYNC, OK);
- session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_2);
- SSLSocketDataProvider ssl_3(ASYNC, OK);
- session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_3);
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- ClientSocketPool* ssl_pool = session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct());
- EXPECT_EQ(GetSocketPoolGroupCount(ssl_pool), 0);
- HttpRequestInfo request_info;
- request_info.method = "GET";
- request_info.url = GURL("https://www.google.com");
- request_info.load_flags = 0;
- request_info.privacy_mode = PRIVACY_MODE_DISABLED;
- request_info.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- SSLConfig ssl_config;
- StreamRequestWaiter waiter;
- std::unique_ptr<HttpStreamRequest> request1(
- session->http_stream_factory()->RequestStream(
- request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter.WaitForStream();
- EXPECT_EQ(GetSocketPoolGroupCount(ssl_pool), 1);
- std::unique_ptr<HttpStreamRequest> request2(
- session->http_stream_factory()->RequestStream(
- request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter.WaitForStream();
- EXPECT_EQ(GetSocketPoolGroupCount(ssl_pool), 1);
- request_info.privacy_mode = PRIVACY_MODE_ENABLED;
- std::unique_ptr<HttpStreamRequest> request3(
- session->http_stream_factory()->RequestStream(
- request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter.WaitForStream();
- EXPECT_EQ(GetSocketPoolGroupCount(ssl_pool), 2);
- }
- TEST_F(HttpStreamFactoryTest, DisableSecureDnsUsesDifferentSocketPoolGroup) {
- SpdySessionDependencies session_deps(
- ConfiguredProxyResolutionService::CreateDirect());
- StaticSocketDataProvider socket_data_1;
- socket_data_1.set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data_1);
- StaticSocketDataProvider socket_data_2;
- socket_data_2.set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data_2);
- StaticSocketDataProvider socket_data_3;
- socket_data_3.set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data_3);
- SSLSocketDataProvider ssl_1(ASYNC, OK);
- session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_1);
- SSLSocketDataProvider ssl_2(ASYNC, OK);
- session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_2);
- SSLSocketDataProvider ssl_3(ASYNC, OK);
- session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_3);
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- ClientSocketPool* ssl_pool = session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct());
- EXPECT_EQ(GetSocketPoolGroupCount(ssl_pool), 0);
- HttpRequestInfo request_info;
- request_info.method = "GET";
- request_info.url = GURL("https://www.google.com");
- request_info.load_flags = 0;
- request_info.privacy_mode = PRIVACY_MODE_DISABLED;
- request_info.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- request_info.secure_dns_policy = SecureDnsPolicy::kAllow;
- SSLConfig ssl_config;
- StreamRequestWaiter waiter;
- std::unique_ptr<HttpStreamRequest> request1(
- session->http_stream_factory()->RequestStream(
- request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter.WaitForStream();
- EXPECT_EQ(SecureDnsPolicy::kAllow,
- session_deps.host_resolver->last_secure_dns_policy());
- EXPECT_EQ(GetSocketPoolGroupCount(ssl_pool), 1);
- std::unique_ptr<HttpStreamRequest> request2(
- session->http_stream_factory()->RequestStream(
- request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter.WaitForStream();
- EXPECT_EQ(SecureDnsPolicy::kAllow,
- session_deps.host_resolver->last_secure_dns_policy());
- EXPECT_EQ(GetSocketPoolGroupCount(ssl_pool), 1);
- request_info.secure_dns_policy = SecureDnsPolicy::kDisable;
- std::unique_ptr<HttpStreamRequest> request3(
- session->http_stream_factory()->RequestStream(
- request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter.WaitForStream();
- EXPECT_EQ(SecureDnsPolicy::kDisable,
- session_deps.host_resolver->last_secure_dns_policy());
- EXPECT_EQ(GetSocketPoolGroupCount(ssl_pool), 2);
- }
- TEST_F(HttpStreamFactoryTest, GetLoadState) {
- SpdySessionDependencies session_deps(
- ConfiguredProxyResolutionService::CreateDirect());
- StaticSocketDataProvider socket_data;
- socket_data.set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data);
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- HttpRequestInfo request_info;
- request_info.method = "GET";
- request_info.url = GURL("http://www.google.com");
- request_info.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- SSLConfig ssl_config;
- StreamRequestWaiter waiter;
- std::unique_ptr<HttpStreamRequest> request(
- session->http_stream_factory()->RequestStream(
- request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- EXPECT_EQ(LOAD_STATE_RESOLVING_HOST, request->GetLoadState());
- waiter.WaitForStream();
- }
- TEST_F(HttpStreamFactoryTest, RequestHttpStream) {
- SpdySessionDependencies session_deps(
- ConfiguredProxyResolutionService::CreateDirect());
- StaticSocketDataProvider socket_data;
- socket_data.set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data);
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- // Now request a stream. It should succeed using the second proxy in the
- // list.
- HttpRequestInfo request_info;
- request_info.method = "GET";
- request_info.url = GURL("http://www.google.com");
- request_info.load_flags = 0;
- request_info.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- SSLConfig ssl_config;
- StreamRequestWaiter waiter;
- std::unique_ptr<HttpStreamRequest> request(
- session->http_stream_factory()->RequestStream(
- request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter.WaitForStream();
- EXPECT_TRUE(waiter.stream_done());
- ASSERT_TRUE(nullptr != waiter.stream());
- EXPECT_TRUE(nullptr == waiter.websocket_stream());
- EXPECT_EQ(0, GetSpdySessionCount(session.get()));
- EXPECT_EQ(
- 1, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_TRUE(waiter.used_proxy_info().is_direct());
- }
- // Test the race of SetPriority versus stream completion where SetPriority may
- // be called on an HttpStreamFactory::Job after the stream has been created by
- // the job.
- TEST_F(HttpStreamFactoryTest, ReprioritizeAfterStreamReceived) {
- SpdySessionDependencies session_deps(
- ConfiguredProxyResolutionService::CreateDirect());
- session_deps.host_resolver->set_synchronous_mode(true);
- MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING);
- StaticSocketDataProvider socket_data(base::make_span(&mock_read, 1),
- base::span<MockWrite>());
- socket_data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data);
- SSLSocketDataProvider ssl_socket_data(SYNCHRONOUS, OK);
- ssl_socket_data.next_proto = kProtoHTTP2;
- session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- // Now request a stream.
- HttpRequestInfo request_info;
- request_info.method = "GET";
- request_info.url = GURL("https://www.google.com");
- request_info.load_flags = 0;
- request_info.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- SSLConfig ssl_config;
- StreamRequestWaiter waiter;
- EXPECT_EQ(0, GetSpdySessionCount(session.get()));
- std::unique_ptr<HttpStreamRequest> request(
- session->http_stream_factory()->RequestStream(
- request_info, LOWEST, ssl_config, ssl_config, &waiter,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- EXPECT_FALSE(waiter.stream_done());
- // Confirm a stream has been created by asserting that a new session
- // has been created. (The stream is only created at the SPDY level on
- // first write, which happens after the request has returned a stream).
- ASSERT_EQ(1, GetSpdySessionCount(session.get()));
- // Test to confirm that a SetPriority received after the stream is created
- // but before the request returns it does not crash.
- request->SetPriority(HIGHEST);
- waiter.WaitForStream();
- EXPECT_TRUE(waiter.stream_done());
- ASSERT_TRUE(waiter.stream());
- EXPECT_FALSE(waiter.websocket_stream());
- }
- TEST_F(HttpStreamFactoryTest, RequestHttpStreamOverSSL) {
- SpdySessionDependencies session_deps(
- ConfiguredProxyResolutionService::CreateDirect());
- MockRead mock_read(ASYNC, OK);
- StaticSocketDataProvider socket_data(base::make_span(&mock_read, 1),
- base::span<MockWrite>());
- socket_data.set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data);
- SSLSocketDataProvider ssl_socket_data(ASYNC, OK);
- session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- // Now request a stream.
- HttpRequestInfo request_info;
- request_info.method = "GET";
- request_info.url = GURL("https://www.google.com");
- request_info.load_flags = 0;
- request_info.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- SSLConfig ssl_config;
- StreamRequestWaiter waiter;
- std::unique_ptr<HttpStreamRequest> request(
- session->http_stream_factory()->RequestStream(
- request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter.WaitForStream();
- EXPECT_TRUE(waiter.stream_done());
- ASSERT_TRUE(nullptr != waiter.stream());
- EXPECT_TRUE(nullptr == waiter.websocket_stream());
- EXPECT_EQ(0, GetSpdySessionCount(session.get()));
- EXPECT_EQ(
- 1, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_TRUE(waiter.used_proxy_info().is_direct());
- }
- TEST_F(HttpStreamFactoryTest, RequestHttpStreamOverProxy) {
- SpdySessionDependencies session_deps(
- ConfiguredProxyResolutionService::CreateFixedForTest(
- "myproxy:8888", TRAFFIC_ANNOTATION_FOR_TESTS));
- StaticSocketDataProvider socket_data;
- socket_data.set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data);
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- // Now request a stream. It should succeed using the second proxy in the
- // list.
- HttpRequestInfo request_info;
- request_info.method = "GET";
- request_info.url = GURL("http://www.google.com");
- request_info.load_flags = 0;
- request_info.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- SSLConfig ssl_config;
- StreamRequestWaiter waiter;
- std::unique_ptr<HttpStreamRequest> request(
- session->http_stream_factory()->RequestStream(
- request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter.WaitForStream();
- EXPECT_TRUE(waiter.stream_done());
- ASSERT_TRUE(nullptr != waiter.stream());
- EXPECT_TRUE(nullptr == waiter.websocket_stream());
- EXPECT_EQ(0, GetSpdySessionCount(session.get()));
- EXPECT_EQ(
- 0, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_EQ(1, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL,
- ProxyServer(ProxyServer::SCHEME_HTTP,
- HostPortPair("myproxy", 8888)))));
- EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL,
- ProxyServer(ProxyServer::SCHEME_HTTPS,
- HostPortPair("myproxy", 8888)))));
- EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::WEBSOCKET_SOCKET_POOL,
- ProxyServer(ProxyServer::SCHEME_HTTP,
- HostPortPair("myproxy", 8888)))));
- EXPECT_FALSE(waiter.used_proxy_info().is_direct());
- }
- TEST_F(HttpStreamFactoryTest, RequestWebSocketBasicHandshakeStream) {
- SpdySessionDependencies session_deps(
- ConfiguredProxyResolutionService::CreateDirect());
- StaticSocketDataProvider socket_data;
- socket_data.set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data);
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- // Now request a stream.
- HttpRequestInfo request_info;
- request_info.method = "GET";
- request_info.url = GURL("ws://www.google.com");
- request_info.load_flags = 0;
- request_info.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- SSLConfig ssl_config;
- StreamRequestWaiter waiter;
- WebSocketStreamCreateHelper create_helper;
- std::unique_ptr<HttpStreamRequest> request(
- session->http_stream_factory()->RequestWebSocketHandshakeStream(
- request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
- &create_helper,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter.WaitForStream();
- EXPECT_TRUE(waiter.stream_done());
- EXPECT_TRUE(nullptr == waiter.stream());
- ASSERT_TRUE(nullptr != waiter.websocket_stream());
- EXPECT_EQ(MockWebSocketHandshakeStream::kStreamTypeBasic,
- waiter.websocket_stream()->type());
- EXPECT_EQ(
- 0, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_TRUE(waiter.used_proxy_info().is_direct());
- }
- TEST_F(HttpStreamFactoryTest, RequestWebSocketBasicHandshakeStreamOverSSL) {
- SpdySessionDependencies session_deps(
- ConfiguredProxyResolutionService::CreateDirect());
- MockRead mock_read(ASYNC, OK);
- StaticSocketDataProvider socket_data(base::make_span(&mock_read, 1),
- base::span<MockWrite>());
- socket_data.set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data);
- SSLSocketDataProvider ssl_socket_data(ASYNC, OK);
- session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- // Now request a stream.
- HttpRequestInfo request_info;
- request_info.method = "GET";
- request_info.url = GURL("wss://www.google.com");
- request_info.load_flags = 0;
- request_info.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- SSLConfig ssl_config;
- StreamRequestWaiter waiter;
- WebSocketStreamCreateHelper create_helper;
- std::unique_ptr<HttpStreamRequest> request(
- session->http_stream_factory()->RequestWebSocketHandshakeStream(
- request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
- &create_helper,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter.WaitForStream();
- EXPECT_TRUE(waiter.stream_done());
- EXPECT_TRUE(nullptr == waiter.stream());
- ASSERT_TRUE(nullptr != waiter.websocket_stream());
- EXPECT_EQ(MockWebSocketHandshakeStream::kStreamTypeBasic,
- waiter.websocket_stream()->type());
- EXPECT_EQ(
- 0, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_TRUE(waiter.used_proxy_info().is_direct());
- }
- TEST_F(HttpStreamFactoryTest, RequestWebSocketBasicHandshakeStreamOverProxy) {
- SpdySessionDependencies session_deps(
- ConfiguredProxyResolutionService::CreateFixedForTest(
- "myproxy:8888", TRAFFIC_ANNOTATION_FOR_TESTS));
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, "HTTP/1.0 200 Connection established\r\n\r\n")};
- StaticSocketDataProvider socket_data(reads, base::span<MockWrite>());
- socket_data.set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data);
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- // Now request a stream.
- HttpRequestInfo request_info;
- request_info.method = "GET";
- request_info.url = GURL("ws://www.google.com");
- request_info.load_flags = 0;
- request_info.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- SSLConfig ssl_config;
- StreamRequestWaiter waiter;
- WebSocketStreamCreateHelper create_helper;
- std::unique_ptr<HttpStreamRequest> request(
- session->http_stream_factory()->RequestWebSocketHandshakeStream(
- request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
- &create_helper,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter.WaitForStream();
- EXPECT_TRUE(waiter.stream_done());
- EXPECT_TRUE(nullptr == waiter.stream());
- ASSERT_TRUE(nullptr != waiter.websocket_stream());
- EXPECT_EQ(MockWebSocketHandshakeStream::kStreamTypeBasic,
- waiter.websocket_stream()->type());
- EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::WEBSOCKET_SOCKET_POOL,
- ProxyServer::Direct())));
- EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL,
- ProxyServer(ProxyServer::SCHEME_HTTP,
- HostPortPair("myproxy", 8888)))));
- EXPECT_EQ(1, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::WEBSOCKET_SOCKET_POOL,
- ProxyServer(ProxyServer::SCHEME_HTTP,
- HostPortPair("myproxy", 8888)))));
- EXPECT_FALSE(waiter.used_proxy_info().is_direct());
- }
- TEST_F(HttpStreamFactoryTest, RequestSpdyHttpStreamHttpsURL) {
- SpdySessionDependencies session_deps(
- ConfiguredProxyResolutionService::CreateDirect());
- MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING);
- SequencedSocketData socket_data(base::make_span(&mock_read, 1),
- base::span<MockWrite>());
- socket_data.set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data);
- SSLSocketDataProvider ssl_socket_data(ASYNC, OK);
- ssl_socket_data.next_proto = kProtoHTTP2;
- session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
- HostPortPair host_port_pair("www.google.com", 443);
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- // Now request a stream.
- HttpRequestInfo request_info;
- request_info.method = "GET";
- request_info.url = GURL("https://www.google.com");
- request_info.load_flags = 0;
- request_info.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- SSLConfig ssl_config;
- StreamRequestWaiter waiter;
- std::unique_ptr<HttpStreamRequest> request(
- session->http_stream_factory()->RequestStream(
- request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter.WaitForStream();
- EXPECT_TRUE(waiter.stream_done());
- EXPECT_TRUE(nullptr == waiter.websocket_stream());
- ASSERT_TRUE(nullptr != waiter.stream());
- EXPECT_EQ(1, GetSpdySessionCount(session.get()));
- EXPECT_EQ(
- 1, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_TRUE(waiter.used_proxy_info().is_direct());
- }
- TEST_F(HttpStreamFactoryTest, RequestSpdyHttpStreamHttpURL) {
- url::SchemeHostPort scheme_host_port("http", "myproxy.org", 443);
- auto session_deps = std::make_unique<SpdySessionDependencies>(
- ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
- "HTTPS myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS));
- std::unique_ptr<ProxyResolutionService> proxy_resolution_service =
- ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
- "HTTPS myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
- MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING);
- SequencedSocketData socket_data(base::make_span(&mock_read, 1),
- base::span<MockWrite>());
- socket_data.set_connect_data(MockConnect(ASYNC, OK));
- session_deps->socket_factory->AddSocketDataProvider(&socket_data);
- SSLSocketDataProvider ssl_socket_data(ASYNC, OK);
- ssl_socket_data.next_proto = kProtoHTTP2;
- session_deps->socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
- session_deps->proxy_resolution_service = std::move(proxy_resolution_service);
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(session_deps.get()));
- HttpServerProperties* http_server_properties =
- session->spdy_session_pool()->http_server_properties();
- EXPECT_FALSE(http_server_properties->GetSupportsSpdy(scheme_host_port,
- NetworkIsolationKey()));
- // Now request a stream.
- HttpRequestInfo request_info;
- request_info.method = "GET";
- request_info.url = GURL("http://www.google.com");
- request_info.load_flags = 0;
- request_info.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- SSLConfig ssl_config;
- StreamRequestWaiter waiter;
- std::unique_ptr<HttpStreamRequest> request(
- session->http_stream_factory()->RequestStream(
- request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter.WaitForStream();
- EXPECT_TRUE(waiter.stream_done());
- EXPECT_TRUE(nullptr == waiter.websocket_stream());
- ASSERT_TRUE(nullptr != waiter.stream());
- EXPECT_EQ(1, GetSpdySessionCount(session.get()));
- EXPECT_EQ(
- 0, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_FALSE(waiter.used_proxy_info().is_direct());
- EXPECT_TRUE(http_server_properties->GetSupportsSpdy(scheme_host_port,
- NetworkIsolationKey()));
- }
- // Same as above, but checks HttpServerProperties is updated using the correct
- // NetworkIsolationKey. When/if NetworkIsolationKey is enabled by default, this
- // should probably be merged into the above test.
- TEST_F(HttpStreamFactoryTest,
- RequestSpdyHttpStreamHttpURLWithNetworkIsolationKey) {
- const SchemefulSite kSite1(GURL("https://foo.test/"));
- const NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
- const SchemefulSite kSite2(GURL("https://bar.test/"));
- const NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(
- features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
- url::SchemeHostPort scheme_host_port("http", "myproxy.org", 443);
- auto session_deps = std::make_unique<SpdySessionDependencies>(
- ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
- "HTTPS myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS));
- std::unique_ptr<ProxyResolutionService> proxy_resolution_service =
- ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
- "HTTPS myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
- MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING);
- SequencedSocketData socket_data(base::make_span(&mock_read, 1),
- base::span<MockWrite>());
- socket_data.set_connect_data(MockConnect(ASYNC, OK));
- session_deps->socket_factory->AddSocketDataProvider(&socket_data);
- SSLSocketDataProvider ssl_socket_data(ASYNC, OK);
- ssl_socket_data.next_proto = kProtoHTTP2;
- session_deps->socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
- session_deps->proxy_resolution_service = std::move(proxy_resolution_service);
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(session_deps.get()));
- HttpServerProperties* http_server_properties =
- session->spdy_session_pool()->http_server_properties();
- EXPECT_FALSE(http_server_properties->GetSupportsSpdy(scheme_host_port,
- kNetworkIsolationKey1));
- // Now request a stream.
- HttpRequestInfo request_info;
- request_info.method = "GET";
- request_info.url = GURL("http://www.google.com");
- request_info.load_flags = 0;
- request_info.network_isolation_key = kNetworkIsolationKey1;
- request_info.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- SSLConfig ssl_config;
- StreamRequestWaiter waiter;
- std::unique_ptr<HttpStreamRequest> request(
- session->http_stream_factory()->RequestStream(
- request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter.WaitForStream();
- EXPECT_TRUE(waiter.stream_done());
- EXPECT_TRUE(nullptr == waiter.websocket_stream());
- ASSERT_TRUE(nullptr != waiter.stream());
- EXPECT_EQ(1, GetSpdySessionCount(session.get()));
- EXPECT_EQ(
- 0, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_FALSE(waiter.used_proxy_info().is_direct());
- EXPECT_TRUE(http_server_properties->GetSupportsSpdy(scheme_host_port,
- kNetworkIsolationKey1));
- // Other NetworkIsolationKeys should not be recorded as supporting SPDY.
- EXPECT_FALSE(http_server_properties->GetSupportsSpdy(scheme_host_port,
- NetworkIsolationKey()));
- EXPECT_FALSE(http_server_properties->GetSupportsSpdy(scheme_host_port,
- kNetworkIsolationKey2));
- }
- // Tests that when a new SpdySession is established, duplicated idle H2 sockets
- // to the same server are closed.
- TEST_F(HttpStreamFactoryTest, NewSpdySessionCloseIdleH2Sockets) {
- SpdySessionDependencies session_deps(
- ConfiguredProxyResolutionService::CreateDirect());
- const int kNumIdleSockets = 4;
- MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
- std::vector<std::unique_ptr<SequencedSocketData>> providers;
- SSLSocketDataProvider ssl_socket_data(ASYNC, OK);
- ssl_socket_data.next_proto = kProtoHTTP2;
- for (int i = 0; i < kNumIdleSockets; i++) {
- auto provider =
- std::make_unique<SequencedSocketData>(reads, base::span<MockWrite>());
- provider->set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(provider.get());
- providers.push_back(std::move(provider));
- session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
- }
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- url::SchemeHostPort destination(url::kHttpsScheme, "www.google.com", 443);
- // Create some HTTP/2 sockets.
- std::vector<std::unique_ptr<ClientSocketHandle>> handles;
- for (size_t i = 0; i < kNumIdleSockets; i++) {
- auto connection = std::make_unique<ClientSocketHandle>();
- TestCompletionCallback callback;
- auto ssl_config_for_origin = std::make_unique<SSLConfig>();
- ssl_config_for_origin->alpn_protos = session->GetAlpnProtos();
- scoped_refptr<ClientSocketPool::SocketParams> socket_params =
- base::MakeRefCounted<ClientSocketPool::SocketParams>(
- std::move(ssl_config_for_origin),
- /*ssl_config_for_proxy=*/nullptr);
- ClientSocketPool::GroupId group_id(
- destination, PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
- SecureDnsPolicy::kAllow);
- int rv = connection->Init(
- group_id, socket_params, absl::nullopt /* proxy_annotation_tag */,
- MEDIUM, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback.callback(), ClientSocketPool::ProxyAuthCallback(),
- session->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
- ProxyServer::Direct()),
- NetLogWithSource());
- rv = callback.GetResult(rv);
- handles.push_back(std::move(connection));
- }
- // Releases handles now, and these sockets should go into the socket pool.
- handles.clear();
- EXPECT_EQ(kNumIdleSockets,
- session
- ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
- ProxyServer::Direct())
- ->IdleSocketCount());
- // Request two streams at once and make sure they use the same connection.
- HttpRequestInfo request_info;
- request_info.method = "GET";
- request_info.url = GURL("https://www.google.com");
- request_info.load_flags = 0;
- request_info.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- SSLConfig ssl_config;
- StreamRequestWaiter waiter1;
- StreamRequestWaiter waiter2;
- std::unique_ptr<HttpStreamRequest> request1(
- session->http_stream_factory()->RequestStream(
- request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter1,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- std::unique_ptr<HttpStreamRequest> request2(
- session->http_stream_factory()->RequestStream(
- request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter2,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter1.WaitForStream();
- waiter2.WaitForStream();
- EXPECT_TRUE(waiter1.stream_done());
- EXPECT_TRUE(waiter2.stream_done());
- ASSERT_NE(nullptr, waiter1.stream());
- ASSERT_NE(nullptr, waiter2.stream());
- ASSERT_NE(waiter1.stream(), waiter2.stream());
- // Establishing the SpdySession will close idle H2 sockets.
- EXPECT_EQ(0, session
- ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
- ProxyServer::Direct())
- ->IdleSocketCount());
- EXPECT_EQ(1, GetSpdySessionCount(session.get()));
- }
- // Regression test for https://crbug.com/706974.
- TEST_F(HttpStreamFactoryTest, TwoSpdyConnects) {
- SpdySessionDependencies session_deps(
- ConfiguredProxyResolutionService::CreateDirect());
- SSLSocketDataProvider ssl_socket_data0(ASYNC, OK);
- ssl_socket_data0.next_proto = kProtoHTTP2;
- session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data0);
- MockRead reads0[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
- SequencedSocketData data0(reads0, base::span<MockWrite>());
- data0.set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(&data0);
- SSLSocketDataProvider ssl_socket_data1(ASYNC, OK);
- ssl_socket_data1.next_proto = kProtoHTTP2;
- session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data1);
- SequencedSocketData data1;
- data1.set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(&data1);
- std::unique_ptr<HttpNetworkSession> session =
- SpdySessionDependencies::SpdyCreateSession(&session_deps);
- HttpRequestInfo request_info;
- request_info.method = "GET";
- request_info.url = GURL("https://www.google.com");
- request_info.load_flags = 0;
- request_info.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- SSLConfig ssl_config;
- // Request two streams at once and make sure they use the same connection.
- StreamRequestWaiter waiter1;
- std::unique_ptr<HttpStreamRequest> request1 =
- session->http_stream_factory()->RequestStream(
- request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter1,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource());
- StreamRequestWaiter waiter2;
- std::unique_ptr<HttpStreamRequest> request2 =
- session->http_stream_factory()->RequestStream(
- request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter2,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource());
- waiter1.WaitForStream();
- waiter2.WaitForStream();
- EXPECT_TRUE(waiter1.stream_done());
- EXPECT_TRUE(waiter2.stream_done());
- ASSERT_NE(nullptr, waiter1.stream());
- ASSERT_NE(nullptr, waiter2.stream());
- ASSERT_NE(waiter1.stream(), waiter2.stream());
- // Establishing the SpdySession will close the extra H2 socket.
- EXPECT_EQ(0, session
- ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
- ProxyServer::Direct())
- ->IdleSocketCount());
- EXPECT_EQ(1, GetSpdySessionCount(session.get()));
- EXPECT_TRUE(data0.AllReadDataConsumed());
- EXPECT_TRUE(data1.AllReadDataConsumed());
- }
- TEST_F(HttpStreamFactoryTest, RequestBidirectionalStreamImpl) {
- SpdySessionDependencies session_deps(
- ConfiguredProxyResolutionService::CreateDirect());
- MockRead mock_read(ASYNC, OK);
- SequencedSocketData socket_data(base::make_span(&mock_read, 1),
- base::span<MockWrite>());
- socket_data.set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data);
- SSLSocketDataProvider ssl_socket_data(ASYNC, OK);
- ssl_socket_data.next_proto = kProtoHTTP2;
- session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- // Now request a stream.
- HttpRequestInfo request_info;
- request_info.method = "GET";
- request_info.url = GURL("https://www.google.com");
- request_info.load_flags = 0;
- request_info.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- SSLConfig ssl_config;
- StreamRequestWaiter waiter;
- std::unique_ptr<HttpStreamRequest> request(
- session->http_stream_factory()->RequestBidirectionalStreamImpl(
- request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter.WaitForStream();
- EXPECT_TRUE(waiter.stream_done());
- EXPECT_FALSE(waiter.websocket_stream());
- ASSERT_FALSE(waiter.stream());
- ASSERT_TRUE(waiter.bidirectional_stream_impl());
- EXPECT_EQ(
- 1, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_TRUE(waiter.used_proxy_info().is_direct());
- }
- struct TestParams {
- quic::ParsedQuicVersion version;
- bool client_headers_include_h2_stream_dependency;
- };
- // Used by ::testing::PrintToStringParamName().
- std::string PrintToString(const TestParams& p) {
- return base::StrCat(
- {ParsedQuicVersionToString(p.version), "_",
- (p.client_headers_include_h2_stream_dependency ? "" : "No"),
- "Dependency"});
- }
- std::vector<TestParams> GetTestParams() {
- std::vector<TestParams> params;
- quic::ParsedQuicVersionVector all_supported_versions =
- quic::AllSupportedVersions();
- for (const auto& version : all_supported_versions) {
- params.push_back(TestParams{version, false});
- params.push_back(TestParams{version, true});
- }
- return params;
- }
- class HttpStreamFactoryBidirectionalQuicTest
- : public TestWithTaskEnvironment,
- public ::testing::WithParamInterface<TestParams> {
- protected:
- HttpStreamFactoryBidirectionalQuicTest()
- : default_url_(kDefaultUrl),
- version_(GetParam().version),
- client_headers_include_h2_stream_dependency_(
- GetParam().client_headers_include_h2_stream_dependency),
- client_packet_maker_(version_,
- quic::QuicUtils::CreateRandomConnectionId(
- quic_context_.random_generator()),
- quic_context_.clock(),
- "www.example.org",
- quic::Perspective::IS_CLIENT,
- client_headers_include_h2_stream_dependency_),
- server_packet_maker_(version_,
- quic::QuicUtils::CreateRandomConnectionId(
- quic_context_.random_generator()),
- quic_context_.clock(),
- "www.example.org",
- quic::Perspective::IS_SERVER,
- false),
- proxy_resolution_service_(
- ConfiguredProxyResolutionService::CreateDirect()),
- ssl_config_service_(std::make_unique<SSLConfigServiceDefaults>()) {
- FLAGS_quic_enable_http3_grease_randomness = false;
- quic_context_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(20));
- quic::QuicEnableVersion(version_);
- }
- void TearDown() override { session_.reset(); }
- // Disable bidirectional stream over QUIC. This should be invoked before
- // Initialize().
- void DisableQuicBidirectionalStream() {
- quic_context_.params()->disable_bidirectional_streams = true;
- }
- void Initialize() {
- params_.enable_quic = true;
- quic_context_.params()->supported_versions =
- quic::test::SupportedVersions(version_);
- quic_context_.params()->headers_include_h2_stream_dependency =
- client_headers_include_h2_stream_dependency_;
- HttpNetworkSessionContext session_context;
- session_context.http_server_properties = &http_server_properties_;
- session_context.quic_context = &quic_context_;
- // Load a certificate that is valid for *.example.org
- scoped_refptr<X509Certificate> test_cert(
- ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
- EXPECT_TRUE(test_cert.get());
- verify_details_.cert_verify_result.verified_cert = test_cert;
- verify_details_.cert_verify_result.is_issued_by_known_root = true;
- crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
- crypto_client_stream_factory_.set_handshake_mode(
- MockCryptoClientStream::CONFIRM_HANDSHAKE);
- session_context.cert_verifier = &cert_verifier_;
- session_context.quic_crypto_client_stream_factory =
- &crypto_client_stream_factory_;
- session_context.transport_security_state = &transport_security_state_;
- session_context.ct_policy_enforcer = &ct_policy_enforcer_;
- session_context.host_resolver = &host_resolver_;
- session_context.proxy_resolution_service = proxy_resolution_service_.get();
- session_context.ssl_config_service = ssl_config_service_.get();
- session_context.client_socket_factory = &socket_factory_;
- session_ = std::make_unique<HttpNetworkSession>(params_, session_context);
- session_->quic_stream_factory()
- ->set_is_quic_known_to_work_on_current_network(true);
- }
- void AddQuicAlternativeService(const url::SchemeHostPort& request_url,
- const std::string& alternative_destination) {
- const AlternativeService alternative_service(kProtoQUIC,
- alternative_destination, 443);
- base::Time expiration = base::Time::Now() + base::Days(1);
- http_server_properties_.SetQuicAlternativeService(
- request_url, NetworkIsolationKey(), alternative_service, expiration,
- session_->context().quic_context->params()->supported_versions);
- }
- void AddQuicAlternativeService() {
- AddQuicAlternativeService(url::SchemeHostPort(default_url_),
- "www.example.org");
- }
- test::QuicTestPacketMaker& client_packet_maker() {
- return client_packet_maker_;
- }
- test::QuicTestPacketMaker& server_packet_maker() {
- return server_packet_maker_;
- }
- MockTaggingClientSocketFactory& socket_factory() { return socket_factory_; }
- HttpNetworkSession* session() { return session_.get(); }
- const GURL default_url_;
- quic::QuicStreamId GetNthClientInitiatedBidirectionalStreamId(int n) {
- return quic::test::GetNthClientInitiatedBidirectionalStreamId(
- version_.transport_version, n);
- }
- quic::ParsedQuicVersion version() const { return version_; }
- MockHostResolver* host_resolver() { return &host_resolver_; }
- private:
- quic::test::QuicFlagSaver saver_;
- const quic::ParsedQuicVersion version_;
- const bool client_headers_include_h2_stream_dependency_;
- MockQuicContext quic_context_;
- test::QuicTestPacketMaker client_packet_maker_;
- test::QuicTestPacketMaker server_packet_maker_;
- MockTaggingClientSocketFactory socket_factory_;
- std::unique_ptr<HttpNetworkSession> session_;
- MockCertVerifier cert_verifier_;
- ProofVerifyDetailsChromium verify_details_;
- MockCryptoClientStreamFactory crypto_client_stream_factory_;
- HttpServerProperties http_server_properties_;
- TransportSecurityState transport_security_state_;
- DefaultCTPolicyEnforcer ct_policy_enforcer_;
- MockHostResolver host_resolver_{
- /*default_result=*/
- MockHostResolverBase::RuleResolver::GetLocalhostResult()};
- std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
- std::unique_ptr<SSLConfigServiceDefaults> ssl_config_service_;
- HttpNetworkSessionParams params_;
- };
- INSTANTIATE_TEST_SUITE_P(VersionIncludeStreamDependencySequence,
- HttpStreamFactoryBidirectionalQuicTest,
- ::testing::ValuesIn(GetTestParams()),
- ::testing::PrintToStringParamName());
- TEST_P(HttpStreamFactoryBidirectionalQuicTest,
- RequestBidirectionalStreamImplQuicAlternative) {
- MockQuicData mock_quic_data(version());
- // When using IETF QUIC, set priority to default value so that
- // QuicTestPacketMaker::MakeRequestHeadersPacket() does not add mock
- // PRIORITY_UPDATE frame, which BidirectionalStreamQuicImpl currently does not
- // send.
- // TODO(https://crbug.com/1059250): Implement PRIORITY_UPDATE in
- // BidirectionalStreamQuicImpl.
- spdy::SpdyPriority priority =
- ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
- size_t spdy_headers_frame_length;
- int packet_num = 1;
- if (VersionUsesHttp3(version().transport_version)) {
- mock_quic_data.AddWrite(
- client_packet_maker().MakeInitialSettingsPacket(packet_num++));
- }
- mock_quic_data.AddWrite(client_packet_maker().MakeRequestHeadersPacket(
- packet_num++, GetNthClientInitiatedBidirectionalStreamId(0),
- /*should_include_version=*/true,
- /*fin=*/true, priority,
- client_packet_maker().GetRequestHeaders("GET", "https", "/"),
- /*parent_stream_id=*/0, &spdy_headers_frame_length));
- size_t spdy_response_headers_frame_length;
- mock_quic_data.AddRead(server_packet_maker().MakeResponseHeadersPacket(
- 1, GetNthClientInitiatedBidirectionalStreamId(0),
- /*should_include_version=*/false,
- /*fin=*/true, server_packet_maker().GetResponseHeaders("200"),
- &spdy_response_headers_frame_length));
- mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more read data.
- mock_quic_data.AddSocketDataToFactory(&socket_factory());
- // Add hanging data for http job.
- auto hanging_data = std::make_unique<StaticSocketDataProvider>();
- MockConnect hanging_connect(SYNCHRONOUS, ERR_IO_PENDING);
- hanging_data->set_connect_data(hanging_connect);
- socket_factory().AddSocketDataProvider(hanging_data.get());
- SSLSocketDataProvider ssl_data(ASYNC, OK);
- socket_factory().AddSSLSocketDataProvider(&ssl_data);
- // Set up QUIC as alternative_service.
- Initialize();
- AddQuicAlternativeService();
- // Now request a stream.
- SSLConfig ssl_config;
- HttpRequestInfo request_info;
- request_info.method = "GET";
- request_info.url = default_url_;
- request_info.load_flags = 0;
- request_info.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- StreamRequestWaiter waiter;
- std::unique_ptr<HttpStreamRequest> request(
- session()->http_stream_factory()->RequestBidirectionalStreamImpl(
- request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter.WaitForStream();
- EXPECT_TRUE(waiter.stream_done());
- EXPECT_FALSE(waiter.websocket_stream());
- ASSERT_FALSE(waiter.stream());
- ASSERT_TRUE(waiter.bidirectional_stream_impl());
- BidirectionalStreamImpl* stream_impl = waiter.bidirectional_stream_impl();
- BidirectionalStreamRequestInfo bidi_request_info;
- bidi_request_info.method = "GET";
- bidi_request_info.url = default_url_;
- bidi_request_info.end_stream_on_headers = true;
- bidi_request_info.priority = LOWEST;
- TestBidirectionalDelegate delegate;
- stream_impl->Start(&bidi_request_info, NetLogWithSource(),
- /*send_request_headers_automatically=*/true, &delegate,
- nullptr, TRAFFIC_ANNOTATION_FOR_TESTS);
- delegate.WaitUntilDone();
- scoped_refptr<IOBuffer> buffer = base::MakeRefCounted<net::IOBuffer>(1);
- EXPECT_THAT(stream_impl->ReadData(buffer.get(), 1), IsOk());
- EXPECT_EQ(kProtoQUIC, stream_impl->GetProtocol());
- EXPECT_EQ("200", delegate.response_headers().find(":status")->second);
- EXPECT_EQ(
- 0, GetSocketPoolGroupCount(session()->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_TRUE(waiter.used_proxy_info().is_direct());
- }
- // Tests that when QUIC is not enabled for bidirectional streaming, HTTP/2 is
- // used instead.
- TEST_P(HttpStreamFactoryBidirectionalQuicTest,
- RequestBidirectionalStreamImplQuicNotEnabled) {
- // Make the http job fail.
- auto http_job_data = std::make_unique<StaticSocketDataProvider>();
- MockConnect failed_connect(ASYNC, ERR_CONNECTION_REFUSED);
- http_job_data->set_connect_data(failed_connect);
- socket_factory().AddSocketDataProvider(http_job_data.get());
- SSLSocketDataProvider ssl_data(ASYNC, OK);
- socket_factory().AddSSLSocketDataProvider(&ssl_data);
- // Set up QUIC as alternative_service.
- DisableQuicBidirectionalStream();
- Initialize();
- AddQuicAlternativeService();
- // Now request a stream.
- SSLConfig ssl_config;
- HttpRequestInfo request_info;
- request_info.method = "GET";
- request_info.url = default_url_;
- request_info.load_flags = 0;
- request_info.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- StreamRequestWaiter waiter;
- std::unique_ptr<HttpStreamRequest> request(
- session()->http_stream_factory()->RequestBidirectionalStreamImpl(
- request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter.WaitForStream();
- EXPECT_TRUE(waiter.stream_done());
- EXPECT_FALSE(waiter.websocket_stream());
- ASSERT_FALSE(waiter.stream());
- ASSERT_FALSE(waiter.bidirectional_stream_impl());
- // Since the alternative service job is not started, we will get the error
- // from the http job.
- ASSERT_THAT(waiter.error_status(), IsError(ERR_CONNECTION_REFUSED));
- }
- // Tests that if Http job fails, but Quic job succeeds, we return
- // BidirectionalStreamQuicImpl.
- TEST_P(HttpStreamFactoryBidirectionalQuicTest,
- RequestBidirectionalStreamImplHttpJobFailsQuicJobSucceeds) {
- // Set up Quic data.
- MockQuicData mock_quic_data(version());
- // When using IETF QUIC, set priority to default value so that
- // QuicTestPacketMaker::MakeRequestHeadersPacket() does not add mock
- // PRIORITY_UPDATE frame, which BidirectionalStreamQuicImpl currently does not
- // send.
- // TODO(https://crbug.com/1059250): Implement PRIORITY_UPDATE in
- // BidirectionalStreamQuicImpl.
- spdy::SpdyPriority priority =
- ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
- size_t spdy_headers_frame_length;
- int packet_num = 1;
- if (VersionUsesHttp3(version().transport_version)) {
- mock_quic_data.AddWrite(
- client_packet_maker().MakeInitialSettingsPacket(packet_num++));
- }
- mock_quic_data.AddWrite(client_packet_maker().MakeRequestHeadersPacket(
- packet_num++, GetNthClientInitiatedBidirectionalStreamId(0),
- /*should_include_version=*/true,
- /*fin=*/true, priority,
- client_packet_maker().GetRequestHeaders("GET", "https", "/"),
- /*parent_stream_id=*/0, &spdy_headers_frame_length));
- size_t spdy_response_headers_frame_length;
- mock_quic_data.AddRead(server_packet_maker().MakeResponseHeadersPacket(
- 1, GetNthClientInitiatedBidirectionalStreamId(0),
- /*should_include_version=*/false,
- /*fin=*/true, server_packet_maker().GetResponseHeaders("200"),
- &spdy_response_headers_frame_length));
- mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more read data.
- mock_quic_data.AddSocketDataToFactory(&socket_factory());
- // Make the http job fail.
- auto http_job_data = std::make_unique<StaticSocketDataProvider>();
- MockConnect failed_connect(ASYNC, ERR_CONNECTION_REFUSED);
- http_job_data->set_connect_data(failed_connect);
- socket_factory().AddSocketDataProvider(http_job_data.get());
- SSLSocketDataProvider ssl_data(ASYNC, OK);
- socket_factory().AddSSLSocketDataProvider(&ssl_data);
- // Set up QUIC as alternative_service.
- Initialize();
- AddQuicAlternativeService();
- // Now request a stream.
- SSLConfig ssl_config;
- HttpRequestInfo request_info;
- request_info.method = "GET";
- request_info.url = default_url_;
- request_info.load_flags = 0;
- request_info.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- StreamRequestWaiter waiter;
- std::unique_ptr<HttpStreamRequest> request(
- session()->http_stream_factory()->RequestBidirectionalStreamImpl(
- request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter.WaitForStream();
- EXPECT_TRUE(waiter.stream_done());
- EXPECT_FALSE(waiter.websocket_stream());
- ASSERT_FALSE(waiter.stream());
- ASSERT_TRUE(waiter.bidirectional_stream_impl());
- BidirectionalStreamImpl* stream_impl = waiter.bidirectional_stream_impl();
- BidirectionalStreamRequestInfo bidi_request_info;
- bidi_request_info.method = "GET";
- bidi_request_info.url = default_url_;
- bidi_request_info.end_stream_on_headers = true;
- bidi_request_info.priority = LOWEST;
- TestBidirectionalDelegate delegate;
- stream_impl->Start(&bidi_request_info, NetLogWithSource(),
- /*send_request_headers_automatically=*/true, &delegate,
- nullptr, TRAFFIC_ANNOTATION_FOR_TESTS);
- delegate.WaitUntilDone();
- // Make sure the BidirectionalStream negotiated goes through QUIC.
- scoped_refptr<IOBuffer> buffer = base::MakeRefCounted<net::IOBuffer>(1);
- EXPECT_THAT(stream_impl->ReadData(buffer.get(), 1), IsOk());
- EXPECT_EQ(kProtoQUIC, stream_impl->GetProtocol());
- EXPECT_EQ("200", delegate.response_headers().find(":status")->second);
- // There is no Http2 socket pool.
- EXPECT_EQ(
- 0, GetSocketPoolGroupCount(session()->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_TRUE(waiter.used_proxy_info().is_direct());
- }
- TEST_F(HttpStreamFactoryTest, RequestBidirectionalStreamImplFailure) {
- SpdySessionDependencies session_deps(
- ConfiguredProxyResolutionService::CreateDirect());
- MockRead mock_read(ASYNC, OK);
- SequencedSocketData socket_data(base::make_span(&mock_read, 1),
- base::span<MockWrite>());
- socket_data.set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data);
- SSLSocketDataProvider ssl_socket_data(ASYNC, OK);
- // If HTTP/1 is used, BidirectionalStreamImpl should not be obtained.
- ssl_socket_data.next_proto = kProtoHTTP11;
- session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- // Now request a stream.
- HttpRequestInfo request_info;
- request_info.method = "GET";
- request_info.url = GURL("https://www.google.com");
- request_info.load_flags = 0;
- request_info.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- SSLConfig ssl_config;
- StreamRequestWaiter waiter;
- std::unique_ptr<HttpStreamRequest> request(
- session->http_stream_factory()->RequestBidirectionalStreamImpl(
- request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter.WaitForStream();
- EXPECT_TRUE(waiter.stream_done());
- ASSERT_THAT(waiter.error_status(), IsError(ERR_FAILED));
- EXPECT_FALSE(waiter.websocket_stream());
- ASSERT_FALSE(waiter.stream());
- ASSERT_FALSE(waiter.bidirectional_stream_impl());
- EXPECT_EQ(
- 1, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- }
- #if BUILDFLAG(IS_ANDROID)
- // Verify HttpStreamFactory::Job passes socket tag along properly and that
- // SpdySessions have unique socket tags (e.g. one sessions should not be shared
- // amongst streams with different socket tags).
- TEST_F(HttpStreamFactoryTest, Tag) {
- SpdySessionDependencies session_deps;
- auto socket_factory = std::make_unique<MockTaggingClientSocketFactory>();
- auto* socket_factory_ptr = socket_factory.get();
- session_deps.socket_factory = std::move(socket_factory);
- // Prepare for two HTTPS connects.
- MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING);
- SequencedSocketData socket_data(base::make_span(&mock_read, 1),
- base::span<MockWrite>());
- socket_data.set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data);
- MockRead mock_read2(SYNCHRONOUS, ERR_IO_PENDING);
- SequencedSocketData socket_data2(base::make_span(&mock_read2, 1),
- base::span<MockWrite>());
- socket_data2.set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data2);
- SSLSocketDataProvider ssl_socket_data(ASYNC, OK);
- ssl_socket_data.ssl_info.cert =
- ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
- ssl_socket_data.next_proto = kProtoHTTP2;
- session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
- SSLSocketDataProvider ssl_socket_data2(ASYNC, OK);
- ssl_socket_data2.ssl_info.cert =
- ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
- ssl_socket_data2.next_proto = kProtoHTTP2;
- session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data2);
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- // Prepare two different tags and corresponding HttpRequestInfos.
- SocketTag tag1(SocketTag::UNSET_UID, 0x12345678);
- HttpRequestInfo request_info1;
- request_info1.method = "GET";
- request_info1.url = GURL("https://example.org");
- request_info1.load_flags = 0;
- request_info1.socket_tag = tag1;
- request_info1.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- SocketTag tag2(getuid(), 0x87654321);
- HttpRequestInfo request_info2 = request_info1;
- request_info2.socket_tag = tag2;
- request_info2.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- // Verify one stream with one tag results in one session, group and
- // socket.
- SSLConfig ssl_config;
- StreamRequestWaiter waiter1;
- std::unique_ptr<HttpStreamRequest> request1(
- session->http_stream_factory()->RequestStream(
- request_info1, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter1,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter1.WaitForStream();
- EXPECT_TRUE(waiter1.stream_done());
- EXPECT_TRUE(nullptr == waiter1.websocket_stream());
- ASSERT_TRUE(nullptr != waiter1.stream());
- EXPECT_EQ(1, GetSpdySessionCount(session.get()));
- EXPECT_EQ(
- 1, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_EQ(
- 1, GetHandedOutSocketCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- // Verify socket tagged appropriately.
- EXPECT_TRUE(tag1 == socket_factory_ptr->GetLastProducedTCPSocket()->tag());
- EXPECT_TRUE(socket_factory_ptr->GetLastProducedTCPSocket()
- ->tagged_before_connected());
- // Verify one more stream with a different tag results in one more session and
- // socket.
- StreamRequestWaiter waiter2;
- std::unique_ptr<HttpStreamRequest> request2(
- session->http_stream_factory()->RequestStream(
- request_info2, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter2,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter2.WaitForStream();
- EXPECT_TRUE(waiter2.stream_done());
- EXPECT_TRUE(nullptr == waiter2.websocket_stream());
- ASSERT_TRUE(nullptr != waiter2.stream());
- EXPECT_EQ(2, GetSpdySessionCount(session.get()));
- EXPECT_EQ(
- 1, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_EQ(
- 2, GetHandedOutSocketCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- // Verify socket tagged appropriately.
- EXPECT_TRUE(tag2 == socket_factory_ptr->GetLastProducedTCPSocket()->tag());
- EXPECT_TRUE(socket_factory_ptr->GetLastProducedTCPSocket()
- ->tagged_before_connected());
- // Verify one more stream reusing a tag does not create new sessions, groups
- // or sockets.
- StreamRequestWaiter waiter3;
- std::unique_ptr<HttpStreamRequest> request3(
- session->http_stream_factory()->RequestStream(
- request_info2, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter3,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter3.WaitForStream();
- EXPECT_TRUE(waiter3.stream_done());
- EXPECT_TRUE(nullptr == waiter3.websocket_stream());
- ASSERT_TRUE(nullptr != waiter3.stream());
- EXPECT_EQ(2, GetSpdySessionCount(session.get()));
- EXPECT_EQ(
- 1, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_EQ(
- 2, GetHandedOutSocketCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- }
- // Verify HttpStreamFactory::Job passes socket tag along properly to QUIC
- // sessions and that QuicSessions have unique socket tags (e.g. one sessions
- // should not be shared amongst streams with different socket tags).
- TEST_P(HttpStreamFactoryBidirectionalQuicTest, Tag) {
- // Prepare mock QUIC data for a first session establishment.
- MockQuicData mock_quic_data(version());
- spdy::SpdyPriority priority =
- ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
- size_t spdy_headers_frame_length;
- int packet_num = 1;
- if (VersionUsesHttp3(version().transport_version)) {
- mock_quic_data.AddWrite(
- client_packet_maker().MakeInitialSettingsPacket(packet_num++));
- }
- mock_quic_data.AddWrite(client_packet_maker().MakeRequestHeadersPacket(
- packet_num++, GetNthClientInitiatedBidirectionalStreamId(0),
- /*should_include_version=*/true,
- /*fin=*/true, priority,
- client_packet_maker().GetRequestHeaders("GET", "https", "/"),
- /*parent_stream_id=*/0, &spdy_headers_frame_length));
- size_t spdy_response_headers_frame_length;
- mock_quic_data.AddRead(server_packet_maker().MakeResponseHeadersPacket(
- 1, GetNthClientInitiatedBidirectionalStreamId(0),
- /*should_include_version=*/false,
- /*fin=*/true, server_packet_maker().GetResponseHeaders("200"),
- &spdy_response_headers_frame_length));
- mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more read data.
- mock_quic_data.AddSocketDataToFactory(&socket_factory());
- // Prepare mock QUIC data for a second session establishment.
- client_packet_maker().Reset();
- MockQuicData mock_quic_data2(version());
- packet_num = 1;
- if (VersionUsesHttp3(version().transport_version)) {
- mock_quic_data2.AddWrite(
- client_packet_maker().MakeInitialSettingsPacket(packet_num++));
- }
- mock_quic_data2.AddWrite(client_packet_maker().MakeRequestHeadersPacket(
- packet_num++, GetNthClientInitiatedBidirectionalStreamId(0),
- /*should_include_version=*/true,
- /*fin=*/true, priority,
- client_packet_maker().GetRequestHeaders("GET", "https", "/"),
- /*parent_stream_id=*/0, &spdy_headers_frame_length));
- mock_quic_data2.AddRead(server_packet_maker().MakeResponseHeadersPacket(
- 1, GetNthClientInitiatedBidirectionalStreamId(0),
- /*should_include_version=*/false,
- /*fin=*/true, server_packet_maker().GetResponseHeaders("200"),
- &spdy_response_headers_frame_length));
- mock_quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more read data.
- mock_quic_data2.AddSocketDataToFactory(&socket_factory());
- // Add hanging data for http job.
- auto hanging_data = std::make_unique<StaticSocketDataProvider>();
- MockConnect hanging_connect(SYNCHRONOUS, ERR_IO_PENDING);
- hanging_data->set_connect_data(hanging_connect);
- socket_factory().AddSocketDataProvider(hanging_data.get());
- SSLSocketDataProvider ssl_data(ASYNC, OK);
- socket_factory().AddSSLSocketDataProvider(&ssl_data);
- // Set up QUIC as alternative_service.
- Initialize();
- AddQuicAlternativeService();
- // Prepare two different tags and corresponding HttpRequestInfos.
- SocketTag tag1(SocketTag::UNSET_UID, 0x12345678);
- HttpRequestInfo request_info1;
- request_info1.method = "GET";
- request_info1.url = default_url_;
- request_info1.load_flags = 0;
- request_info1.socket_tag = tag1;
- request_info1.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- SocketTag tag2(getuid(), 0x87654321);
- HttpRequestInfo request_info2 = request_info1;
- request_info2.socket_tag = tag2;
- request_info2.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- // Verify one stream with one tag results in one QUIC session.
- SSLConfig ssl_config;
- StreamRequestWaiter waiter1;
- std::unique_ptr<HttpStreamRequest> request1(
- session()->http_stream_factory()->RequestStream(
- request_info1, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter1,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter1.WaitForStream();
- EXPECT_TRUE(waiter1.stream_done());
- EXPECT_TRUE(nullptr == waiter1.websocket_stream());
- ASSERT_TRUE(nullptr != waiter1.stream());
- EXPECT_EQ(kProtoQUIC, request1->negotiated_protocol());
- EXPECT_EQ(1, GetQuicSessionCount(session()));
- // Verify socket tagged appropriately.
- EXPECT_TRUE(tag1 == socket_factory().GetLastProducedUDPSocket()->tag());
- EXPECT_TRUE(socket_factory()
- .GetLastProducedUDPSocket()
- ->tagged_before_data_transferred());
- // Verify one more stream with a different tag results in one more session and
- // socket.
- StreamRequestWaiter waiter2;
- std::unique_ptr<HttpStreamRequest> request2(
- session()->http_stream_factory()->RequestStream(
- request_info2, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter2,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter2.WaitForStream();
- EXPECT_TRUE(waiter2.stream_done());
- EXPECT_TRUE(nullptr == waiter2.websocket_stream());
- ASSERT_TRUE(nullptr != waiter2.stream());
- EXPECT_EQ(kProtoQUIC, request2->negotiated_protocol());
- EXPECT_EQ(2, GetQuicSessionCount(session()));
- // Verify socket tagged appropriately.
- EXPECT_TRUE(tag2 == socket_factory().GetLastProducedUDPSocket()->tag());
- EXPECT_TRUE(socket_factory()
- .GetLastProducedUDPSocket()
- ->tagged_before_data_transferred());
- // Verify one more stream reusing a tag does not create new sessions.
- StreamRequestWaiter waiter3;
- std::unique_ptr<HttpStreamRequest> request3(
- session()->http_stream_factory()->RequestStream(
- request_info2, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter3,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter3.WaitForStream();
- EXPECT_TRUE(waiter3.stream_done());
- EXPECT_TRUE(nullptr == waiter3.websocket_stream());
- ASSERT_TRUE(nullptr != waiter3.stream());
- EXPECT_EQ(kProtoQUIC, request3->negotiated_protocol());
- EXPECT_EQ(2, GetQuicSessionCount(session()));
- }
- TEST_F(HttpStreamFactoryTest, ChangeSocketTag) {
- SpdySessionDependencies session_deps;
- auto socket_factory = std::make_unique<MockTaggingClientSocketFactory>();
- auto* socket_factory_ptr = socket_factory.get();
- session_deps.socket_factory = std::move(socket_factory);
- // Prepare for two HTTPS connects.
- MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING);
- SequencedSocketData socket_data(base::make_span(&mock_read, 1),
- base::span<MockWrite>());
- socket_data.set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data);
- MockRead mock_read2(SYNCHRONOUS, ERR_IO_PENDING);
- SequencedSocketData socket_data2(base::make_span(&mock_read2, 1),
- base::span<MockWrite>());
- socket_data2.set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data2);
- SSLSocketDataProvider ssl_socket_data(ASYNC, OK);
- // Use cert for *.example.org
- ssl_socket_data.ssl_info.cert =
- ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
- ssl_socket_data.next_proto = kProtoHTTP2;
- session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
- SSLSocketDataProvider ssl_socket_data2(ASYNC, OK);
- // Use cert for *.example.org
- ssl_socket_data2.ssl_info.cert =
- ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
- ssl_socket_data2.next_proto = kProtoHTTP2;
- session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data2);
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- // Prepare two different tags and corresponding HttpRequestInfos.
- SocketTag tag1(SocketTag::UNSET_UID, 0x12345678);
- HttpRequestInfo request_info1;
- request_info1.method = "GET";
- request_info1.url = GURL("https://www.example.org");
- request_info1.load_flags = 0;
- request_info1.socket_tag = tag1;
- request_info1.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- SocketTag tag2(getuid(), 0x87654321);
- HttpRequestInfo request_info2 = request_info1;
- request_info2.socket_tag = tag2;
- request_info2.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- // Prepare another HttpRequestInfo with tag1 and a different host name.
- HttpRequestInfo request_info3 = request_info1;
- request_info3.url = GURL("https://foo.example.org");
- request_info3.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- // Verify one stream with one tag results in one session, group and
- // socket.
- SSLConfig ssl_config;
- StreamRequestWaiter waiter1;
- std::unique_ptr<HttpStreamRequest> request1(
- session->http_stream_factory()->RequestStream(
- request_info1, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter1,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter1.WaitForStream();
- EXPECT_TRUE(waiter1.stream_done());
- EXPECT_FALSE(waiter1.websocket_stream());
- ASSERT_TRUE(waiter1.stream());
- EXPECT_EQ(1, GetSpdySessionCount(session.get()));
- EXPECT_EQ(
- 1, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_EQ(
- 1, GetHandedOutSocketCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- // Verify socket tagged appropriately.
- MockTaggingStreamSocket* socket =
- socket_factory_ptr->GetLastProducedTCPSocket();
- EXPECT_TRUE(tag1 == socket->tag());
- EXPECT_TRUE(socket->tagged_before_connected());
- // Verify the socket tag on the first session can be changed.
- StreamRequestWaiter waiter2;
- std::unique_ptr<HttpStreamRequest> request2(
- session->http_stream_factory()->RequestStream(
- request_info2, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter2,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter2.WaitForStream();
- EXPECT_TRUE(waiter2.stream_done());
- EXPECT_FALSE(waiter2.websocket_stream());
- ASSERT_TRUE(waiter2.stream());
- // Verify still have just one session.
- EXPECT_EQ(1, GetSpdySessionCount(session.get()));
- EXPECT_EQ(
- 1, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_EQ(
- 1, GetHandedOutSocketCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- // Verify no new sockets created.
- EXPECT_EQ(socket, socket_factory_ptr->GetLastProducedTCPSocket());
- // Verify socket tag changed.
- EXPECT_TRUE(tag2 == socket->tag());
- EXPECT_FALSE(socket->tagged_before_connected());
- // Verify attempting to use the first stream fails because the session's
- // socket tag has since changed.
- TestCompletionCallback callback1;
- waiter1.stream()->RegisterRequest(&request_info1);
- EXPECT_EQ(ERR_FAILED, waiter1.stream()->InitializeStream(
- /* can_send_early = */ false, DEFAULT_PRIORITY,
- NetLogWithSource(), callback1.callback()));
- // Verify the socket tag can be changed, this time using an IP alias
- // (different host, same IP).
- StreamRequestWaiter waiter3;
- std::unique_ptr<HttpStreamRequest> request3(
- session->http_stream_factory()->RequestStream(
- request_info3, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter3,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter3.WaitForStream();
- EXPECT_TRUE(waiter3.stream_done());
- EXPECT_FALSE(waiter3.websocket_stream());
- ASSERT_TRUE(waiter3.stream());
- // Verify still have just one session.
- EXPECT_EQ(1, GetSpdySessionCount(session.get()));
- EXPECT_EQ(
- 1, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_EQ(
- 1, GetHandedOutSocketCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- // Verify no new sockets created.
- EXPECT_EQ(socket, socket_factory_ptr->GetLastProducedTCPSocket());
- // Verify socket tag changed.
- EXPECT_TRUE(tag1 == socket->tag());
- EXPECT_FALSE(socket->tagged_before_connected());
- // Initialize the third stream, thus marking the session active, so it cannot
- // have its socket tag changed.
- TestCompletionCallback callback3;
- waiter3.stream()->RegisterRequest(&request_info3);
- EXPECT_EQ(OK, waiter3.stream()->InitializeStream(
- /* can_send_early = */ false, DEFAULT_PRIORITY,
- NetLogWithSource(), callback3.callback()));
- // Verify a new session is created when a request with a different tag is
- // started.
- StreamRequestWaiter waiter4;
- std::unique_ptr<HttpStreamRequest> request4(
- session->http_stream_factory()->RequestStream(
- request_info2, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter4,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter4.WaitForStream();
- EXPECT_TRUE(waiter4.stream_done());
- EXPECT_FALSE(waiter4.websocket_stream());
- ASSERT_TRUE(waiter4.stream());
- // Verify we now have two sessions.
- EXPECT_EQ(2, GetSpdySessionCount(session.get()));
- EXPECT_EQ(
- 1, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_EQ(
- 2, GetHandedOutSocketCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- // Verify a new socket was created.
- MockTaggingStreamSocket* socket2 =
- socket_factory_ptr->GetLastProducedTCPSocket();
- EXPECT_NE(socket, socket2);
- // Verify tag set appropriately.
- EXPECT_TRUE(tag2 == socket2->tag());
- EXPECT_TRUE(socket2->tagged_before_connected());
- // Verify tag on original socket is unchanged.
- EXPECT_TRUE(tag1 == socket->tag());
- waiter3.stream()->Close(/* not_reusable = */ true);
- }
- // Regression test for https://crbug.com/954503.
- TEST_F(HttpStreamFactoryTest, ChangeSocketTagAvoidOverwrite) {
- SpdySessionDependencies session_deps;
- auto socket_factory = std::make_unique<MockTaggingClientSocketFactory>();
- auto* socket_factory_ptr = socket_factory.get();
- session_deps.socket_factory = std::move(socket_factory);
- // Prepare for two HTTPS connects.
- MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING);
- SequencedSocketData socket_data(base::make_span(&mock_read, 1),
- base::span<MockWrite>());
- socket_data.set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data);
- MockRead mock_read2(SYNCHRONOUS, ERR_IO_PENDING);
- SequencedSocketData socket_data2(base::make_span(&mock_read2, 1),
- base::span<MockWrite>());
- socket_data2.set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data2);
- SSLSocketDataProvider ssl_socket_data(ASYNC, OK);
- // Use cert for *.example.org
- ssl_socket_data.ssl_info.cert =
- ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
- ssl_socket_data.next_proto = kProtoHTTP2;
- session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
- SSLSocketDataProvider ssl_socket_data2(ASYNC, OK);
- // Use cert for *.example.org
- ssl_socket_data2.ssl_info.cert =
- ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
- ssl_socket_data2.next_proto = kProtoHTTP2;
- session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data2);
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- // Prepare three different tags and corresponding HttpRequestInfos.
- SocketTag tag1(SocketTag::UNSET_UID, 2);
- HttpRequestInfo request_info1;
- request_info1.method = "GET";
- request_info1.url = GURL("https://www.example.org");
- request_info1.load_flags = 0;
- request_info1.socket_tag = tag1;
- request_info1.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- SocketTag tag2(SocketTag::UNSET_UID, 1);
- HttpRequestInfo request_info2 = request_info1;
- request_info2.socket_tag = tag2;
- HttpRequestInfo request_info3 = request_info1;
- SocketTag tag3(SocketTag::UNSET_UID, 3);
- request_info3.socket_tag = tag3;
- // Prepare another HttpRequestInfo with tag3 and a different host name.
- HttpRequestInfo request_info4 = request_info1;
- request_info4.socket_tag = tag3;
- request_info4.url = GURL("https://foo.example.org");
- // Verify one stream with one tag results in one session, group and
- // socket.
- SSLConfig ssl_config;
- StreamRequestWaiter waiter1;
- std::unique_ptr<HttpStreamRequest> request1(
- session->http_stream_factory()->RequestStream(
- request_info1, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter1,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter1.WaitForStream();
- EXPECT_TRUE(waiter1.stream_done());
- EXPECT_FALSE(waiter1.websocket_stream());
- ASSERT_TRUE(waiter1.stream());
- EXPECT_EQ(1, GetSpdySessionCount(session.get()));
- EXPECT_EQ(
- 1, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_EQ(
- 1, GetHandedOutSocketCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- // Verify socket tagged appropriately.
- MockTaggingStreamSocket* socket =
- socket_factory_ptr->GetLastProducedTCPSocket();
- EXPECT_TRUE(tag1 == socket->tag());
- EXPECT_TRUE(socket->tagged_before_connected());
- // Initialize the first stream, thus marking the session active, so it cannot
- // have its socket tag changed and be reused for the second session.
- TestCompletionCallback callback1;
- waiter1.stream()->RegisterRequest(&request_info1);
- EXPECT_EQ(OK, waiter1.stream()->InitializeStream(
- /* can_send_early = */ false, DEFAULT_PRIORITY,
- NetLogWithSource(), callback1.callback()));
- // Create a second stream with a new tag.
- StreamRequestWaiter waiter2;
- std::unique_ptr<HttpStreamRequest> request2(
- session->http_stream_factory()->RequestStream(
- request_info2, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter2,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter2.WaitForStream();
- EXPECT_TRUE(waiter2.stream_done());
- EXPECT_FALSE(waiter2.websocket_stream());
- ASSERT_TRUE(waiter2.stream());
- // Verify we now have two sessions.
- EXPECT_EQ(2, GetSpdySessionCount(session.get()));
- EXPECT_EQ(
- 1, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_EQ(
- 2, GetHandedOutSocketCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- // Verify a new socket was created.
- MockTaggingStreamSocket* socket2 =
- socket_factory_ptr->GetLastProducedTCPSocket();
- EXPECT_NE(socket, socket2);
- // Verify tag set appropriately.
- EXPECT_TRUE(tag2 == socket2->tag());
- EXPECT_TRUE(socket2->tagged_before_connected());
- // Verify tag on original socket is unchanged.
- EXPECT_TRUE(tag1 == socket->tag());
- // Initialize the second stream, thus marking the session active, so it cannot
- // have its socket tag changed and be reused for the third session.
- TestCompletionCallback callback2;
- waiter2.stream()->RegisterRequest(&request_info2);
- EXPECT_EQ(OK, waiter2.stream()->InitializeStream(
- /* can_send_early = */ false, DEFAULT_PRIORITY,
- NetLogWithSource(), callback2.callback()));
- // Release first stream so first session can be retagged for third request.
- waiter1.stream()->Close(/* not_reusable = */ true);
- // Verify the first session can be retagged for a third request.
- StreamRequestWaiter waiter3;
- std::unique_ptr<HttpStreamRequest> request3(
- session->http_stream_factory()->RequestStream(
- request_info3, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter3,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter3.WaitForStream();
- EXPECT_TRUE(waiter3.stream_done());
- EXPECT_FALSE(waiter3.websocket_stream());
- ASSERT_TRUE(waiter3.stream());
- // Verify still have two sessions.
- EXPECT_EQ(2, GetSpdySessionCount(session.get()));
- EXPECT_EQ(
- 1, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_EQ(
- 2, GetHandedOutSocketCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- // Verify no new sockets created.
- EXPECT_EQ(socket2, socket_factory_ptr->GetLastProducedTCPSocket());
- // Verify socket tag changed.
- EXPECT_TRUE(tag3 == socket->tag());
- EXPECT_FALSE(socket->tagged_before_connected());
- // Release second stream so second session can be retagged for fourth request.
- waiter2.stream()->Close(/* not_reusable = */ true);
- // Request a stream with a new tag and a different host that aliases existing
- // sessions.
- StreamRequestWaiter waiter4;
- std::unique_ptr<HttpStreamRequest> request4(
- session->http_stream_factory()->RequestStream(
- request_info4, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter4,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter4.WaitForStream();
- EXPECT_TRUE(waiter4.stream_done());
- EXPECT_FALSE(waiter4.websocket_stream());
- ASSERT_TRUE(waiter4.stream());
- // Verify no new sockets created.
- EXPECT_EQ(socket2, socket_factory_ptr->GetLastProducedTCPSocket());
- }
- #endif
- // Test that when creating a stream all sessions that alias an IP are tried,
- // not just one. This is important because there can be multiple sessions
- // that could satisfy a stream request and they should all be tried.
- TEST_F(HttpStreamFactoryTest, MultiIPAliases) {
- SpdySessionDependencies session_deps;
- // Prepare for two HTTPS connects.
- MockRead mock_read1(SYNCHRONOUS, ERR_IO_PENDING);
- SequencedSocketData socket_data1(base::make_span(&mock_read1, 1),
- base::span<MockWrite>());
- socket_data1.set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data1);
- MockRead mock_read2(SYNCHRONOUS, ERR_IO_PENDING);
- SequencedSocketData socket_data2(base::make_span(&mock_read2, 1),
- base::span<MockWrite>());
- socket_data2.set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data2);
- SSLSocketDataProvider ssl_socket_data1(ASYNC, OK);
- // Load cert for *.example.org
- ssl_socket_data1.ssl_info.cert =
- ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
- ssl_socket_data1.next_proto = kProtoHTTP2;
- session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data1);
- SSLSocketDataProvider ssl_socket_data2(ASYNC, OK);
- // Load cert for *.example.org
- ssl_socket_data2.ssl_info.cert =
- ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
- ssl_socket_data2.next_proto = kProtoHTTP2;
- session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data2);
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- // Create two HttpRequestInfos, differing only in host name.
- // Both will resolve to 127.0.0.1 and hence be IP aliases.
- HttpRequestInfo request_info1;
- request_info1.method = "GET";
- request_info1.url = GURL("https://a.example.org");
- request_info1.privacy_mode = PRIVACY_MODE_DISABLED;
- request_info1.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- HttpRequestInfo request_info1_alias = request_info1;
- request_info1.url = GURL("https://b.example.org");
- // Create two more HttpRequestInfos but with different privacy_mode.
- HttpRequestInfo request_info2;
- request_info2.method = "GET";
- request_info2.url = GURL("https://a.example.org");
- request_info2.privacy_mode = PRIVACY_MODE_ENABLED;
- request_info2.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- HttpRequestInfo request_info2_alias = request_info2;
- request_info2.url = GURL("https://b.example.org");
- // Open one session.
- SSLConfig ssl_config;
- StreamRequestWaiter waiter1;
- std::unique_ptr<HttpStreamRequest> request1(
- session->http_stream_factory()->RequestStream(
- request_info1, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter1,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter1.WaitForStream();
- EXPECT_TRUE(waiter1.stream_done());
- EXPECT_FALSE(waiter1.websocket_stream());
- ASSERT_TRUE(waiter1.stream());
- // Verify just one session created.
- EXPECT_EQ(1, GetSpdySessionCount(session.get()));
- EXPECT_EQ(
- 1, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_EQ(
- 1, GetHandedOutSocketCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- // Open another session to same IP but with different privacy mode.
- StreamRequestWaiter waiter2;
- std::unique_ptr<HttpStreamRequest> request2(
- session->http_stream_factory()->RequestStream(
- request_info2, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter2,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter2.WaitForStream();
- EXPECT_TRUE(waiter2.stream_done());
- EXPECT_FALSE(waiter2.websocket_stream());
- ASSERT_TRUE(waiter2.stream());
- // Verify two sessions are now open.
- EXPECT_EQ(2, GetSpdySessionCount(session.get()));
- EXPECT_EQ(
- 2, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_EQ(
- 2, GetHandedOutSocketCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- // Open a third session that IP aliases first session.
- StreamRequestWaiter waiter3;
- std::unique_ptr<HttpStreamRequest> request3(
- session->http_stream_factory()->RequestStream(
- request_info1_alias, DEFAULT_PRIORITY, ssl_config, ssl_config,
- &waiter3,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter3.WaitForStream();
- EXPECT_TRUE(waiter3.stream_done());
- EXPECT_FALSE(waiter3.websocket_stream());
- ASSERT_TRUE(waiter3.stream());
- // Verify the session pool reused the first session and no new session is
- // created. This will fail unless the session pool supports multiple
- // sessions aliasing a single IP.
- EXPECT_EQ(2, GetSpdySessionCount(session.get()));
- EXPECT_EQ(
- 2, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_EQ(
- 2, GetHandedOutSocketCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- // Open a fourth session that IP aliases the second session.
- StreamRequestWaiter waiter4;
- std::unique_ptr<HttpStreamRequest> request4(
- session->http_stream_factory()->RequestStream(
- request_info2_alias, DEFAULT_PRIORITY, ssl_config, ssl_config,
- &waiter4,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter4.WaitForStream();
- EXPECT_TRUE(waiter4.stream_done());
- EXPECT_FALSE(waiter4.websocket_stream());
- ASSERT_TRUE(waiter4.stream());
- // Verify the session pool reused the second session. This will fail unless
- // the session pool supports multiple sessions aliasing a single IP.
- EXPECT_EQ(2, GetSpdySessionCount(session.get()));
- EXPECT_EQ(
- 2, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_EQ(
- 2, GetHandedOutSocketCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- }
- TEST_F(HttpStreamFactoryTest, SpdyIPPoolingWithDnsAliases) {
- SpdySessionDependencies session_deps;
- const std::set<std::string> kDnsAliasesA({"alias1", "alias2"});
- const std::set<std::string> kDnsAliasesB({"b.com", "b.org", "b.net"});
- const std::string kHostnameC("c.example.org");
- session_deps.host_resolver->rules()->AddIPLiteralRuleWithDnsAliases(
- "a.example.org", "127.0.0.1", kDnsAliasesA);
- session_deps.host_resolver->rules()->AddIPLiteralRuleWithDnsAliases(
- "b.example.org", "127.0.0.1", kDnsAliasesB);
- session_deps.host_resolver->rules()->AddIPLiteralRuleWithDnsAliases(
- "c.example.org", "127.0.0.1", /*dns_aliases=*/std::set<std::string>());
- // Prepare for an HTTPS connect.
- MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING);
- SequencedSocketData socket_data(base::make_span(&mock_read, 1),
- base::span<MockWrite>());
- socket_data.set_connect_data(MockConnect(ASYNC, OK));
- session_deps.socket_factory->AddSocketDataProvider(&socket_data);
- SSLSocketDataProvider ssl_socket_data(ASYNC, OK);
- // Load cert for *.example.org
- ssl_socket_data.ssl_info.cert =
- ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
- ssl_socket_data.next_proto = kProtoHTTP2;
- session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
- std::unique_ptr<HttpNetworkSession> session(
- SpdySessionDependencies::SpdyCreateSession(&session_deps));
- // Create three HttpRequestInfos, differing only in host name.
- // All three will resolve to 127.0.0.1 and hence be IP aliases.
- HttpRequestInfo request_info_a;
- request_info_a.method = "GET";
- request_info_a.url = GURL("https://a.example.org");
- request_info_a.privacy_mode = PRIVACY_MODE_DISABLED;
- request_info_a.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- HttpRequestInfo request_info_b = request_info_a;
- HttpRequestInfo request_info_c = request_info_a;
- request_info_b.url = GURL("https://b.example.org");
- request_info_c.url = GURL("https://c.example.org");
- // Open one session.
- SSLConfig ssl_config;
- StreamRequestWaiter waiter1;
- std::unique_ptr<HttpStreamRequest> request1(
- session->http_stream_factory()->RequestStream(
- request_info_a, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter1,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter1.WaitForStream();
- EXPECT_TRUE(waiter1.stream_done());
- EXPECT_FALSE(waiter1.websocket_stream());
- ASSERT_TRUE(waiter1.stream());
- EXPECT_EQ(kDnsAliasesA, waiter1.stream()->GetDnsAliases());
- // Verify just one session created.
- EXPECT_EQ(1, GetSpdySessionCount(session.get()));
- EXPECT_EQ(
- 1, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_EQ(
- 1, GetHandedOutSocketCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- // Open a session that IP aliases first session.
- StreamRequestWaiter waiter2;
- std::unique_ptr<HttpStreamRequest> request2(
- session->http_stream_factory()->RequestStream(
- request_info_b, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter2,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter2.WaitForStream();
- EXPECT_TRUE(waiter2.stream_done());
- EXPECT_FALSE(waiter2.websocket_stream());
- ASSERT_TRUE(waiter2.stream());
- EXPECT_EQ(kDnsAliasesB, waiter2.stream()->GetDnsAliases());
- // Verify the session pool reused the first session and no new session is
- // created. This will fail unless the session pool supports multiple
- // sessions aliasing a single IP.
- EXPECT_EQ(1, GetSpdySessionCount(session.get()));
- EXPECT_EQ(
- 1, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_EQ(
- 1, GetHandedOutSocketCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- // Open another session that IP aliases the first session.
- StreamRequestWaiter waiter3;
- std::unique_ptr<HttpStreamRequest> request3(
- session->http_stream_factory()->RequestStream(
- request_info_c, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter3,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter3.WaitForStream();
- EXPECT_TRUE(waiter3.stream_done());
- EXPECT_FALSE(waiter3.websocket_stream());
- ASSERT_TRUE(waiter3.stream());
- EXPECT_THAT(waiter3.stream()->GetDnsAliases(), ElementsAre(kHostnameC));
- // Verify the session pool reused the first session and no new session is
- // created. This will fail unless the session pool supports multiple
- // sessions aliasing a single IP.
- EXPECT_EQ(1, GetSpdySessionCount(session.get()));
- EXPECT_EQ(
- 1, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_EQ(
- 1, GetHandedOutSocketCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- // Clear host resolver rules to ensure that cached values for DNS aliases
- // are used.
- session_deps.host_resolver->rules()->ClearRules();
- // Re-request the original resource using `request_info_a`, which had
- // non-default DNS aliases.
- std::unique_ptr<HttpStreamRequest> request4(
- session->http_stream_factory()->RequestStream(
- request_info_a, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter1,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter1.WaitForStream();
- EXPECT_TRUE(waiter1.stream_done());
- EXPECT_FALSE(waiter1.websocket_stream());
- ASSERT_TRUE(waiter1.stream());
- EXPECT_EQ(kDnsAliasesA, waiter1.stream()->GetDnsAliases());
- // Verify the session pool reused the first session and no new session is
- // created.
- EXPECT_EQ(1, GetSpdySessionCount(session.get()));
- EXPECT_EQ(
- 1, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_EQ(
- 1, GetHandedOutSocketCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- // Re-request a resource using `request_info_b`, which had non-default DNS
- // aliases.
- std::unique_ptr<HttpStreamRequest> request5(
- session->http_stream_factory()->RequestStream(
- request_info_b, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter2,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter2.WaitForStream();
- EXPECT_TRUE(waiter2.stream_done());
- EXPECT_FALSE(waiter2.websocket_stream());
- ASSERT_TRUE(waiter2.stream());
- EXPECT_EQ(kDnsAliasesB, waiter2.stream()->GetDnsAliases());
- // Verify the session pool reused the first session and no new session is
- // created. This will fail unless the session pool supports multiple
- // sessions aliasing a single IP.
- EXPECT_EQ(1, GetSpdySessionCount(session.get()));
- EXPECT_EQ(
- 1, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_EQ(
- 1, GetHandedOutSocketCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- // Re-request a resource using `request_info_c`, which had only the default
- // DNS alias (the host name).
- std::unique_ptr<HttpStreamRequest> request6(
- session->http_stream_factory()->RequestStream(
- request_info_c, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter3,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter3.WaitForStream();
- EXPECT_TRUE(waiter3.stream_done());
- EXPECT_FALSE(waiter3.websocket_stream());
- ASSERT_TRUE(waiter3.stream());
- EXPECT_THAT(waiter3.stream()->GetDnsAliases(), ElementsAre(kHostnameC));
- // Verify the session pool reused the first session and no new session is
- // created. This will fail unless the session pool supports multiple
- // sessions aliasing a single IP.
- EXPECT_EQ(1, GetSpdySessionCount(session.get()));
- EXPECT_EQ(
- 1, GetSocketPoolGroupCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- EXPECT_EQ(
- 1, GetHandedOutSocketCount(session->GetSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
- }
- TEST_P(HttpStreamFactoryBidirectionalQuicTest, QuicIPPoolingWithDnsAliases) {
- const GURL kUrlA("https://a.example.org");
- const GURL kUrlB("https://b.example.org");
- const GURL kUrlC("https://c.example.org");
- const std::set<std::string> kDnsAliasesA({"alias1", "alias2"});
- const std::set<std::string> kDnsAliasesB({"b.com", "b.org", "b.net"});
- host_resolver()->rules()->AddIPLiteralRuleWithDnsAliases(
- kUrlA.host(), "127.0.0.1", kDnsAliasesA);
- host_resolver()->rules()->AddIPLiteralRuleWithDnsAliases(
- kUrlB.host(), "127.0.0.1", kDnsAliasesB);
- host_resolver()->rules()->AddIPLiteralRuleWithDnsAliases(
- kUrlC.host(), "127.0.0.1",
- /*dns_aliases=*/std::set<std::string>());
- // Prepare mock QUIC data for a first session establishment.
- MockQuicData mock_quic_data(version());
- spdy::SpdyPriority priority =
- ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
- size_t spdy_headers_frame_length;
- int packet_num = 1;
- if (VersionUsesHttp3(version().transport_version)) {
- mock_quic_data.AddWrite(
- client_packet_maker().MakeInitialSettingsPacket(packet_num++));
- }
- mock_quic_data.AddWrite(client_packet_maker().MakeRequestHeadersPacket(
- packet_num++, GetNthClientInitiatedBidirectionalStreamId(0),
- /*should_include_version=*/true,
- /*fin=*/true, priority,
- client_packet_maker().GetRequestHeaders("GET", "https", "/"),
- /*parent_stream_id=*/0, &spdy_headers_frame_length));
- size_t spdy_response_headers_frame_length;
- mock_quic_data.AddRead(server_packet_maker().MakeResponseHeadersPacket(
- 1, GetNthClientInitiatedBidirectionalStreamId(0),
- /*should_include_version=*/false,
- /*fin=*/true, server_packet_maker().GetResponseHeaders("200"),
- &spdy_response_headers_frame_length));
- mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more read data.
- mock_quic_data.AddSocketDataToFactory(&socket_factory());
- // Add hanging data for http job.
- auto hanging_data = std::make_unique<StaticSocketDataProvider>();
- MockConnect hanging_connect(SYNCHRONOUS, ERR_IO_PENDING);
- hanging_data->set_connect_data(hanging_connect);
- socket_factory().AddSocketDataProvider(hanging_data.get());
- SSLSocketDataProvider ssl_data(ASYNC, OK);
- socket_factory().AddSSLSocketDataProvider(&ssl_data);
- // Set up QUIC as alternative_service.
- Initialize();
- AddQuicAlternativeService(url::SchemeHostPort(kUrlA), kUrlA.host());
- AddQuicAlternativeService(url::SchemeHostPort(kUrlB), kUrlB.host());
- AddQuicAlternativeService(url::SchemeHostPort(kUrlC), kUrlC.host());
- // Create three HttpRequestInfos, differing only in host name.
- // All three will resolve to 127.0.0.1 and hence be IP aliases.
- HttpRequestInfo request_info_a;
- request_info_a.method = "GET";
- request_info_a.url = kUrlA;
- request_info_a.privacy_mode = PRIVACY_MODE_DISABLED;
- request_info_a.traffic_annotation =
- MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
- HttpRequestInfo request_info_b = request_info_a;
- HttpRequestInfo request_info_c = request_info_a;
- request_info_b.url = kUrlB;
- request_info_c.url = kUrlC;
- // Open one session.
- SSLConfig ssl_config;
- StreamRequestWaiter waiter1;
- std::unique_ptr<HttpStreamRequest> request1(
- session()->http_stream_factory()->RequestStream(
- request_info_a, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter1,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter1.WaitForStream();
- EXPECT_TRUE(waiter1.stream_done());
- EXPECT_FALSE(waiter1.websocket_stream());
- ASSERT_TRUE(waiter1.stream());
- EXPECT_EQ(kDnsAliasesA, waiter1.stream()->GetDnsAliases());
- // Verify just one session created.
- EXPECT_EQ(1, GetQuicSessionCount(session()));
- EXPECT_EQ(kProtoQUIC, request1->negotiated_protocol());
- // Create a request that will alias and reuse the first session.
- StreamRequestWaiter waiter2;
- std::unique_ptr<HttpStreamRequest> request2(
- session()->http_stream_factory()->RequestStream(
- request_info_b, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter2,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter2.WaitForStream();
- EXPECT_TRUE(waiter2.stream_done());
- EXPECT_FALSE(waiter2.websocket_stream());
- ASSERT_TRUE(waiter2.stream());
- EXPECT_EQ(kDnsAliasesB, waiter2.stream()->GetDnsAliases());
- // Verify the session pool reused the first session and no new session is
- // created. This will fail unless the session pool supports multiple
- // sessions aliasing a single IP.
- EXPECT_EQ(1, GetQuicSessionCount(session()));
- EXPECT_EQ(kProtoQUIC, request2->negotiated_protocol());
- // Create another request that will alias and reuse the first session.
- StreamRequestWaiter waiter3;
- std::unique_ptr<HttpStreamRequest> request3(
- session()->http_stream_factory()->RequestStream(
- request_info_c, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter3,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter3.WaitForStream();
- EXPECT_TRUE(waiter3.stream_done());
- EXPECT_FALSE(waiter3.websocket_stream());
- ASSERT_TRUE(waiter3.stream());
- EXPECT_THAT(waiter3.stream()->GetDnsAliases(), ElementsAre(kUrlC.host()));
- // Clear the host resolve rules to ensure that we are using cached info.
- host_resolver()->rules()->ClearRules();
- // Verify the session pool reused the first session and no new session is
- // created. This will fail unless the session pool supports multiple
- // sessions aliasing a single IP.
- EXPECT_EQ(1, GetQuicSessionCount(session()));
- EXPECT_EQ(kProtoQUIC, request3->negotiated_protocol());
- // Create a request that will reuse the first session.
- std::unique_ptr<HttpStreamRequest> request4(
- session()->http_stream_factory()->RequestStream(
- request_info_a, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter1,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter1.WaitForStream();
- EXPECT_TRUE(waiter1.stream_done());
- EXPECT_FALSE(waiter1.websocket_stream());
- ASSERT_TRUE(waiter1.stream());
- EXPECT_EQ(kDnsAliasesA, waiter1.stream()->GetDnsAliases());
- // Verify the session pool reused the first session and no new session is
- // created.
- EXPECT_EQ(1, GetQuicSessionCount(session()));
- EXPECT_EQ(kProtoQUIC, request4->negotiated_protocol());
- // Create another request that will alias and reuse the first session.
- std::unique_ptr<HttpStreamRequest> request5(
- session()->http_stream_factory()->RequestStream(
- request_info_b, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter2,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter2.WaitForStream();
- EXPECT_TRUE(waiter2.stream_done());
- EXPECT_FALSE(waiter2.websocket_stream());
- ASSERT_TRUE(waiter2.stream());
- EXPECT_EQ(kDnsAliasesB, waiter2.stream()->GetDnsAliases());
- // Verify the session pool reused the first session and no new session is
- // created. This will fail unless the session pool supports multiple
- // sessions aliasing a single IP.
- EXPECT_EQ(1, GetQuicSessionCount(session()));
- EXPECT_EQ(kProtoQUIC, request5->negotiated_protocol());
- // Create another request that will alias and reuse the first session.
- std::unique_ptr<HttpStreamRequest> request6(
- session()->http_stream_factory()->RequestStream(
- request_info_c, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter3,
- /* enable_ip_based_pooling = */ true,
- /* enable_alternative_services = */ true, NetLogWithSource()));
- waiter3.WaitForStream();
- EXPECT_TRUE(waiter3.stream_done());
- EXPECT_FALSE(waiter3.websocket_stream());
- ASSERT_TRUE(waiter3.stream());
- EXPECT_THAT(waiter3.stream()->GetDnsAliases(), ElementsAre(kUrlC.host()));
- // Verify the session pool reused the first session and no new session is
- // created. This will fail unless the session pool supports multiple
- // sessions aliasing a single IP.
- EXPECT_EQ(1, GetQuicSessionCount(session()));
- EXPECT_EQ(kProtoQUIC, request6->negotiated_protocol());
- }
- class ProcessAlternativeServicesTest : public TestWithTaskEnvironment {
- public:
- ProcessAlternativeServicesTest() {
- session_params_.enable_quic = true;
- session_context_.proxy_resolution_service = proxy_resolution_service_.get();
- session_context_.host_resolver = &host_resolver_;
- session_context_.cert_verifier = &cert_verifier_;
- session_context_.transport_security_state = &transport_security_state_;
- session_context_.client_socket_factory = &socket_factory_;
- session_context_.ct_policy_enforcer = &ct_policy_enforcer_;
- session_context_.ssl_config_service = &ssl_config_service_;
- session_context_.http_server_properties = &http_server_properties_;
- session_context_.quic_context = &quic_context_;
- }
- protected:
- HttpNetworkSessionParams session_params_;
- HttpNetworkSessionContext session_context_;
- std::unique_ptr<HttpNetworkSession> session_;
- HttpServerProperties http_server_properties_;
- QuicContext quic_context_;
- private:
- std::unique_ptr<ProxyResolutionService> proxy_resolution_service_ =
- ConfiguredProxyResolutionService::CreateDirect();
- SSLConfigServiceDefaults ssl_config_service_;
- MockClientSocketFactory socket_factory_;
- MockHostResolver host_resolver_;
- MockCertVerifier cert_verifier_;
- TransportSecurityState transport_security_state_;
- DefaultCTPolicyEnforcer ct_policy_enforcer_;
- };
- TEST_F(ProcessAlternativeServicesTest, ProcessEmptyAltSvc) {
- session_ =
- std::make_unique<HttpNetworkSession>(session_params_, session_context_);
- url::SchemeHostPort origin;
- NetworkIsolationKey network_isolation_key;
- auto headers = base::MakeRefCounted<HttpResponseHeaders>("");
- session_->http_stream_factory()->ProcessAlternativeServices(
- session_.get(), network_isolation_key, headers.get(), origin);
- AlternativeServiceInfoVector alternatives =
- http_server_properties_.GetAlternativeServiceInfos(origin,
- network_isolation_key);
- EXPECT_TRUE(alternatives.empty());
- }
- TEST_F(ProcessAlternativeServicesTest, ProcessAltSvcClear) {
- session_ =
- std::make_unique<HttpNetworkSession>(session_params_, session_context_);
- url::SchemeHostPort origin(url::kHttpsScheme, "example.com", 443);
- NetworkIsolationKey network_isolation_key(
- SchemefulSite(GURL("https://example.com")),
- SchemefulSite(GURL("https://example.com")));
- http_server_properties_.SetAlternativeServices(
- origin, network_isolation_key,
- {AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
- {kProtoQUIC, "", 443}, base::Time::Now() + base::Seconds(30),
- quic::AllSupportedVersions())});
- EXPECT_FALSE(http_server_properties_
- .GetAlternativeServiceInfos(origin, network_isolation_key)
- .empty());
- auto headers = base::MakeRefCounted<HttpResponseHeaders>("");
- headers->AddHeader("alt-svc", "clear");
- session_->http_stream_factory()->ProcessAlternativeServices(
- session_.get(), network_isolation_key, headers.get(), origin);
- AlternativeServiceInfoVector alternatives =
- http_server_properties_.GetAlternativeServiceInfos(origin,
- network_isolation_key);
- EXPECT_TRUE(alternatives.empty());
- }
- TEST_F(ProcessAlternativeServicesTest, ProcessAltSvcQuicIetf) {
- quic_context_.params()->supported_versions = quic::AllSupportedVersions();
- session_ =
- std::make_unique<HttpNetworkSession>(session_params_, session_context_);
- url::SchemeHostPort origin(url::kHttpsScheme, "example.com", 443);
- NetworkIsolationKey network_isolation_key(
- SchemefulSite(GURL("https://example.com")),
- SchemefulSite(GURL("https://example.com")));
- auto headers = base::MakeRefCounted<HttpResponseHeaders>("");
- headers->AddHeader("alt-svc",
- "h3-29=\":443\","
- "h3-Q050=\":443\","
- "h3-Q043=\":443\"");
- session_->http_stream_factory()->ProcessAlternativeServices(
- session_.get(), network_isolation_key, headers.get(), origin);
- quic::ParsedQuicVersionVector versions = {
- quic::ParsedQuicVersion::Draft29(),
- quic::ParsedQuicVersion::Q050(),
- quic::ParsedQuicVersion::Q043(),
- };
- AlternativeServiceInfoVector alternatives =
- http_server_properties_.GetAlternativeServiceInfos(origin,
- network_isolation_key);
- ASSERT_EQ(versions.size(), alternatives.size());
- for (size_t i = 0; i < alternatives.size(); ++i) {
- EXPECT_EQ(kProtoQUIC, alternatives[i].protocol());
- EXPECT_EQ(HostPortPair("example.com", 443),
- alternatives[i].host_port_pair());
- EXPECT_EQ(1u, alternatives[i].advertised_versions().size());
- EXPECT_EQ(versions[i], alternatives[i].advertised_versions()[0]);
- }
- }
- TEST_F(ProcessAlternativeServicesTest, ProcessAltSvcHttp2) {
- quic_context_.params()->supported_versions = quic::AllSupportedVersions();
- session_ =
- std::make_unique<HttpNetworkSession>(session_params_, session_context_);
- url::SchemeHostPort origin(url::kHttpsScheme, "example.com", 443);
- NetworkIsolationKey network_isolation_key(
- SchemefulSite(GURL("https://example.com")),
- SchemefulSite(GURL("https://example.com")));
- auto headers = base::MakeRefCounted<HttpResponseHeaders>("");
- headers->AddHeader("alt-svc", "h2=\"other.example.com:443\"");
- session_->http_stream_factory()->ProcessAlternativeServices(
- session_.get(), network_isolation_key, headers.get(), origin);
- AlternativeServiceInfoVector alternatives =
- http_server_properties_.GetAlternativeServiceInfos(origin,
- network_isolation_key);
- ASSERT_EQ(1u, alternatives.size());
- EXPECT_EQ(kProtoHTTP2, alternatives[0].protocol());
- EXPECT_EQ(HostPortPair("other.example.com", 443),
- alternatives[0].host_port_pair());
- EXPECT_EQ(0u, alternatives[0].advertised_versions().size());
- }
- } // namespace
- } // namespace net
|