12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198 |
- // 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 <stdint.h>
- #include <algorithm>
- #include <iterator>
- #include <limits>
- #include <memory>
- #include <utility>
- #include "base/memory/raw_ptr.h"
- // This must be before Windows headers
- #include "base/callback_helpers.h"
- #include "base/memory/ptr_util.h"
- #include "base/time/time.h"
- #include "build/build_config.h"
- #include "net/dns/public/secure_dns_policy.h"
- #include "net/log/net_log.h"
- #include "url/url_constants.h"
- #if BUILDFLAG(IS_WIN)
- #include <objbase.h>
- #include <shlobj.h>
- #include <windows.h>
- #include <wrl/client.h>
- #endif
- #include "base/base64url.h"
- #include "base/bind.h"
- #include "base/compiler_specific.h"
- #include "base/files/file_path.h"
- #include "base/files/file_util.h"
- #include "base/files/scoped_temp_dir.h"
- #include "base/format_macros.h"
- #include "base/json/json_reader.h"
- #include "base/location.h"
- #include "base/memory/weak_ptr.h"
- #include "base/path_service.h"
- #include "base/run_loop.h"
- #include "base/strings/escape.h"
- #include "base/strings/strcat.h"
- #include "base/strings/string_number_conversions.h"
- #include "base/strings/string_piece.h"
- #include "base/strings/string_split.h"
- #include "base/strings/string_util.h"
- #include "base/strings/stringprintf.h"
- #include "base/strings/utf_string_conversions.h"
- #include "base/task/single_thread_task_runner.h"
- #include "base/test/bind.h"
- #include "base/test/metrics/histogram_tester.h"
- #include "base/test/scoped_feature_list.h"
- #include "base/threading/thread_task_runner_handle.h"
- #include "base/values.h"
- #include "build/buildflag.h"
- #include "crypto/sha2.h"
- #include "net/base/chunked_upload_data_stream.h"
- #include "net/base/directory_listing.h"
- #include "net/base/elements_upload_data_stream.h"
- #include "net/base/features.h"
- #include "net/base/hash_value.h"
- #include "net/base/ip_address.h"
- #include "net/base/ip_endpoint.h"
- #include "net/base/isolation_info.h"
- #include "net/base/load_flags.h"
- #include "net/base/load_timing_info.h"
- #include "net/base/load_timing_info_test_util.h"
- #include "net/base/net_errors.h"
- #include "net/base/net_module.h"
- #include "net/base/proxy_server.h"
- #include "net/base/proxy_string_util.h"
- #include "net/base/request_priority.h"
- #include "net/base/test_completion_callback.h"
- #include "net/base/transport_info.h"
- #include "net/base/upload_bytes_element_reader.h"
- #include "net/base/upload_data_stream.h"
- #include "net/base/upload_file_element_reader.h"
- #include "net/base/url_util.h"
- #include "net/cert/asn1_util.h"
- #include "net/cert/cert_net_fetcher.h"
- #include "net/cert/crl_set.h"
- #include "net/cert/ct_policy_enforcer.h"
- #include "net/cert/ct_policy_status.h"
- #include "net/cert/do_nothing_ct_verifier.h"
- #include "net/cert/ev_root_ca_metadata.h"
- #include "net/cert/mock_cert_verifier.h"
- #include "net/cert/multi_log_ct_verifier.h"
- #include "net/cert/signed_certificate_timestamp_and_status.h"
- #include "net/cert/test_root_certs.h"
- #include "net/cert/x509_util.h"
- #include "net/cert_net/cert_net_fetcher_url_request.h"
- #include "net/cookies/canonical_cookie_test_helpers.h"
- #include "net/cookies/cookie_inclusion_status.h"
- #include "net/cookies/cookie_monster.h"
- #include "net/cookies/cookie_store_test_helpers.h"
- #include "net/cookies/test_cookie_access_delegate.h"
- #include "net/disk_cache/disk_cache.h"
- #include "net/dns/host_resolver_results.h"
- #include "net/dns/mock_host_resolver.h"
- #include "net/dns/public/secure_dns_policy.h"
- #include "net/http/http_byte_range.h"
- #include "net/http/http_cache.h"
- #include "net/http/http_network_layer.h"
- #include "net/http/http_network_session.h"
- #include "net/http/http_request_headers.h"
- #include "net/http/http_response_headers.h"
- #include "net/http/http_server_properties.h"
- #include "net/http/http_transaction_test_util.h"
- #include "net/http/http_util.h"
- #include "net/http/transport_security_state.h"
- #include "net/http/transport_security_state_source.h"
- #include "net/log/file_net_log_observer.h"
- #include "net/log/net_log_event_type.h"
- #include "net/log/net_log_source.h"
- #include "net/log/test_net_log.h"
- #include "net/log/test_net_log_util.h"
- #include "net/net_buildflags.h"
- #include "net/proxy_resolution/configured_proxy_resolution_service.h"
- #include "net/quic/mock_crypto_client_stream_factory.h"
- #include "net/quic/quic_server_info.h"
- #include "net/socket/read_buffering_stream_socket.h"
- #include "net/socket/socket_test_util.h"
- #include "net/socket/ssl_client_socket.h"
- #include "net/ssl/client_cert_identity_test_util.h"
- #include "net/ssl/ssl_connection_status_flags.h"
- #include "net/ssl/ssl_private_key.h"
- #include "net/ssl/ssl_server_config.h"
- #include "net/ssl/test_ssl_config_service.h"
- #include "net/test/cert_test_util.h"
- #include "net/test/embedded_test_server/http_request.h"
- #include "net/test/embedded_test_server/http_response.h"
- #include "net/test/gtest_util.h"
- #include "net/test/spawned_test_server/spawned_test_server.h"
- #include "net/test/test_data_directory.h"
- #include "net/test/test_with_task_environment.h"
- #include "net/test/url_request/url_request_failed_job.h"
- #include "net/test/url_request/url_request_mock_http_job.h"
- #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
- #include "net/url_request/redirect_util.h"
- #include "net/url_request/referrer_policy.h"
- #include "net/url_request/static_http_user_agent_settings.h"
- #include "net/url_request/url_request.h"
- #include "net/url_request/url_request_context.h"
- #include "net/url_request/url_request_context_builder.h"
- #include "net/url_request/url_request_filter.h"
- #include "net/url_request/url_request_http_job.h"
- #include "net/url_request/url_request_interceptor.h"
- #include "net/url_request/url_request_redirect_job.h"
- #include "net/url_request/url_request_test_job.h"
- #include "net/url_request/url_request_test_util.h"
- #include "net/url_request/websocket_handshake_userdata_key.h"
- #include "testing/gmock/include/gmock/gmock-matchers.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "testing/platform_test.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- #include "third_party/boringssl/src/include/openssl/ssl.h"
- #include "url/url_constants.h"
- #include "url/url_util.h"
- #if BUILDFLAG(IS_WIN)
- #include "base/win/scoped_com_initializer.h"
- #endif
- #if BUILDFLAG(IS_APPLE)
- #include "base/mac/mac_util.h"
- #endif
- #if BUILDFLAG(ENABLE_REPORTING)
- #include "net/network_error_logging/network_error_logging_service.h"
- #include "net/network_error_logging/network_error_logging_test_util.h"
- #endif // BUILDFLAG(ENABLE_REPORTING)
- #if BUILDFLAG(ENABLE_WEBSOCKETS)
- #include "net/websockets/websocket_test_util.h"
- #endif // BUILDFLAG(ENABLE_WEBSOCKETS)
- using net::test::IsError;
- using net::test::IsOk;
- using net::test_server::RegisterDefaultHandlers;
- using testing::_;
- using testing::AnyOf;
- using testing::ElementsAre;
- using testing::IsEmpty;
- using testing::Optional;
- using testing::UnorderedElementsAre;
- using base::ASCIIToUTF16;
- using base::Time;
- using std::string;
- namespace net {
- namespace {
- namespace test_default {
- #include "net/http/transport_security_state_static_unittest_default.h"
- }
- const std::u16string kChrome(u"chrome");
- const std::u16string kSecret(u"secret");
- const std::u16string kUser(u"user");
- const base::FilePath::CharType kTestFilePath[] =
- FILE_PATH_LITERAL("net/data/url_request_unittest");
- // Tests load timing information in the case a fresh connection was used, with
- // no proxy.
- void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info,
- int connect_timing_flags) {
- EXPECT_FALSE(load_timing_info.socket_reused);
- EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
- EXPECT_FALSE(load_timing_info.request_start_time.is_null());
- EXPECT_FALSE(load_timing_info.request_start.is_null());
- EXPECT_LE(load_timing_info.request_start,
- load_timing_info.connect_timing.connect_start);
- ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
- connect_timing_flags);
- EXPECT_LE(load_timing_info.connect_timing.connect_end,
- load_timing_info.send_start);
- EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
- EXPECT_LE(load_timing_info.send_end, load_timing_info.receive_headers_start);
- EXPECT_LE(load_timing_info.receive_headers_start,
- load_timing_info.receive_headers_end);
- EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
- EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
- }
- // Same as above, but with proxy times.
- void TestLoadTimingNotReusedWithProxy(const LoadTimingInfo& load_timing_info,
- int connect_timing_flags) {
- EXPECT_FALSE(load_timing_info.socket_reused);
- EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
- EXPECT_FALSE(load_timing_info.request_start_time.is_null());
- EXPECT_FALSE(load_timing_info.request_start.is_null());
- EXPECT_LE(load_timing_info.request_start,
- load_timing_info.proxy_resolve_start);
- EXPECT_LE(load_timing_info.proxy_resolve_start,
- load_timing_info.proxy_resolve_end);
- EXPECT_LE(load_timing_info.proxy_resolve_end,
- load_timing_info.connect_timing.connect_start);
- ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
- connect_timing_flags);
- EXPECT_LE(load_timing_info.connect_timing.connect_end,
- load_timing_info.send_start);
- EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
- EXPECT_LE(load_timing_info.send_end, load_timing_info.receive_headers_start);
- EXPECT_LE(load_timing_info.receive_headers_start,
- load_timing_info.receive_headers_end);
- }
- // Same as above, but with a reused socket and proxy times.
- void TestLoadTimingReusedWithProxy(const LoadTimingInfo& load_timing_info) {
- EXPECT_TRUE(load_timing_info.socket_reused);
- EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
- EXPECT_FALSE(load_timing_info.request_start_time.is_null());
- EXPECT_FALSE(load_timing_info.request_start.is_null());
- ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
- EXPECT_LE(load_timing_info.request_start,
- load_timing_info.proxy_resolve_start);
- EXPECT_LE(load_timing_info.proxy_resolve_start,
- load_timing_info.proxy_resolve_end);
- EXPECT_LE(load_timing_info.proxy_resolve_end, load_timing_info.send_start);
- EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
- EXPECT_LE(load_timing_info.send_end, load_timing_info.receive_headers_start);
- EXPECT_LE(load_timing_info.receive_headers_start,
- load_timing_info.receive_headers_end);
- }
- CookieList GetAllCookies(URLRequestContext* request_context) {
- CookieList cookie_list;
- base::RunLoop run_loop;
- request_context->cookie_store()->GetAllCookiesAsync(
- base::BindLambdaForTesting([&](const CookieList& cookies) {
- cookie_list = cookies;
- run_loop.Quit();
- }));
- run_loop.Run();
- return cookie_list;
- }
- void TestLoadTimingCacheHitNoNetwork(const LoadTimingInfo& load_timing_info) {
- EXPECT_FALSE(load_timing_info.socket_reused);
- EXPECT_EQ(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
- EXPECT_FALSE(load_timing_info.request_start_time.is_null());
- EXPECT_FALSE(load_timing_info.request_start.is_null());
- ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
- EXPECT_LE(load_timing_info.request_start, load_timing_info.send_start);
- EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
- EXPECT_LE(load_timing_info.send_end, load_timing_info.receive_headers_start);
- EXPECT_LE(load_timing_info.receive_headers_start,
- load_timing_info.receive_headers_end);
- EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
- EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
- }
- // Job that allows monitoring of its priority.
- class PriorityMonitoringURLRequestJob : public URLRequestTestJob {
- public:
- // The latest priority of the job is always written to |request_priority_|.
- PriorityMonitoringURLRequestJob(URLRequest* request,
- RequestPriority* request_priority)
- : URLRequestTestJob(request), request_priority_(request_priority) {
- *request_priority_ = DEFAULT_PRIORITY;
- }
- void SetPriority(RequestPriority priority) override {
- *request_priority_ = priority;
- URLRequestTestJob::SetPriority(priority);
- }
- private:
- const raw_ptr<RequestPriority> request_priority_;
- };
- // Do a case-insensitive search through |haystack| for |needle|.
- bool ContainsString(const std::string& haystack, const char* needle) {
- std::string::const_iterator it = std::search(
- haystack.begin(), haystack.end(), needle, needle + strlen(needle),
- base::CaseInsensitiveCompareASCII<char>());
- return it != haystack.end();
- }
- std::unique_ptr<UploadDataStream> CreateSimpleUploadData(const char* data) {
- auto reader = std::make_unique<UploadBytesElementReader>(data, strlen(data));
- return ElementsUploadDataStream::CreateWithReader(std::move(reader), 0);
- }
- // Verify that the SSLInfo of a successful SSL connection has valid values.
- void CheckSSLInfo(const SSLInfo& ssl_info) {
- // The cipher suite TLS_NULL_WITH_NULL_NULL (0) must not be negotiated.
- uint16_t cipher_suite =
- SSLConnectionStatusToCipherSuite(ssl_info.connection_status);
- EXPECT_NE(0U, cipher_suite);
- }
- // A network delegate that allows the user to choose a subset of request stages
- // to block in. When blocking, the delegate can do one of the following:
- // * synchronously return a pre-specified error code, or
- // * asynchronously return that value via an automatically called callback,
- // or
- // * block and wait for the user to do a callback.
- // Additionally, the user may also specify a redirect URL -- then each request
- // with the current URL different from the redirect target will be redirected
- // to that target, in the on-before-URL-request stage, independent of whether
- // the delegate blocks in ON_BEFORE_URL_REQUEST or not.
- class BlockingNetworkDelegate : public TestNetworkDelegate {
- public:
- // Stages in which the delegate can block.
- enum Stage {
- NOT_BLOCKED = 0,
- ON_BEFORE_URL_REQUEST = 1 << 0,
- ON_BEFORE_SEND_HEADERS = 1 << 1,
- ON_HEADERS_RECEIVED = 1 << 2,
- };
- // Behavior during blocked stages. During other stages, just
- // returns OK or NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION.
- enum BlockMode {
- SYNCHRONOUS, // No callback, returns specified return values.
- AUTO_CALLBACK, // |this| posts a task to run the callback using the
- // specified return codes.
- USER_CALLBACK, // User takes care of doing a callback. |retval_| and
- // |auth_retval_| are ignored. In every blocking stage the
- // message loop is quit.
- };
- // Creates a delegate which does not block at all.
- explicit BlockingNetworkDelegate(BlockMode block_mode);
- BlockingNetworkDelegate(const BlockingNetworkDelegate&) = delete;
- BlockingNetworkDelegate& operator=(const BlockingNetworkDelegate&) = delete;
- // Runs the message loop until the delegate blocks.
- void RunUntilBlocked();
- // For users to trigger a callback returning |response|.
- // Side-effects: resets |stage_blocked_for_callback_| and stored callbacks.
- // Only call if |block_mode_| == USER_CALLBACK.
- void DoCallback(int response);
- // Setters.
- void set_retval(int retval) {
- ASSERT_NE(USER_CALLBACK, block_mode_);
- ASSERT_NE(ERR_IO_PENDING, retval);
- ASSERT_NE(OK, retval);
- retval_ = retval;
- }
- void set_redirect_url(const GURL& url) { redirect_url_ = url; }
- void set_block_on(int block_on) { block_on_ = block_on; }
- // Allows the user to check in which state did we block.
- Stage stage_blocked_for_callback() const {
- EXPECT_EQ(USER_CALLBACK, block_mode_);
- return stage_blocked_for_callback_;
- }
- private:
- void OnBlocked();
- void RunCallback(int response, CompletionOnceCallback callback);
- // TestNetworkDelegate implementation.
- int OnBeforeURLRequest(URLRequest* request,
- CompletionOnceCallback callback,
- GURL* new_url) override;
- int OnBeforeStartTransaction(
- URLRequest* request,
- const HttpRequestHeaders& headers,
- OnBeforeStartTransactionCallback callback) override;
- int OnHeadersReceived(
- URLRequest* request,
- CompletionOnceCallback callback,
- const HttpResponseHeaders* original_response_headers,
- scoped_refptr<HttpResponseHeaders>* override_response_headers,
- const IPEndPoint& endpoint,
- absl::optional<GURL>* preserve_fragment_on_redirect_url) override;
- // Resets the callbacks and |stage_blocked_for_callback_|.
- void Reset();
- // Checks whether we should block in |stage|. If yes, returns an error code
- // and optionally sets up callback based on |block_mode_|. If no, returns OK.
- int MaybeBlockStage(Stage stage, CompletionOnceCallback callback);
- // Configuration parameters, can be adjusted by public methods:
- const BlockMode block_mode_;
- // Values returned on blocking stages when mode is SYNCHRONOUS or
- // AUTO_CALLBACK. For USER_CALLBACK these are set automatically to IO_PENDING.
- int retval_ = OK;
- GURL redirect_url_; // Used if non-empty during OnBeforeURLRequest.
- int block_on_ = 0; // Bit mask: in which stages to block.
- // Internal variables, not set by not the user:
- // Last blocked stage waiting for user callback (unused if |block_mode_| !=
- // USER_CALLBACK).
- Stage stage_blocked_for_callback_ = NOT_BLOCKED;
- // Callback objects stored during blocking stages.
- CompletionOnceCallback callback_;
- // Closure to run to exit RunUntilBlocked().
- base::OnceClosure on_blocked_;
- base::WeakPtrFactory<BlockingNetworkDelegate> weak_factory_{this};
- };
- BlockingNetworkDelegate::BlockingNetworkDelegate(BlockMode block_mode)
- : block_mode_(block_mode) {}
- void BlockingNetworkDelegate::RunUntilBlocked() {
- base::RunLoop run_loop;
- on_blocked_ = run_loop.QuitClosure();
- run_loop.Run();
- }
- void BlockingNetworkDelegate::DoCallback(int response) {
- ASSERT_EQ(USER_CALLBACK, block_mode_);
- ASSERT_NE(NOT_BLOCKED, stage_blocked_for_callback_);
- CompletionOnceCallback callback = std::move(callback_);
- Reset();
- // |callback| may trigger completion of a request, so post it as a task, so
- // it will run under a subsequent TestDelegate::RunUntilComplete() loop.
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&BlockingNetworkDelegate::RunCallback,
- weak_factory_.GetWeakPtr(), response,
- std::move(callback)));
- }
- void BlockingNetworkDelegate::OnBlocked() {
- // If this fails due to |on_blocked_| being null then OnBlocked() was run by
- // a RunLoop other than RunUntilBlocked(), indicating a bug in the calling
- // test.
- std::move(on_blocked_).Run();
- }
- void BlockingNetworkDelegate::RunCallback(int response,
- CompletionOnceCallback callback) {
- std::move(callback).Run(response);
- }
- int BlockingNetworkDelegate::OnBeforeURLRequest(URLRequest* request,
- CompletionOnceCallback callback,
- GURL* new_url) {
- if (redirect_url_ == request->url())
- return OK; // We've already seen this request and redirected elsewhere.
- // TestNetworkDelegate always completes synchronously.
- CHECK_NE(ERR_IO_PENDING, TestNetworkDelegate::OnBeforeURLRequest(
- request, base::NullCallback(), new_url));
- if (!redirect_url_.is_empty())
- *new_url = redirect_url_;
- return MaybeBlockStage(ON_BEFORE_URL_REQUEST, std::move(callback));
- }
- int BlockingNetworkDelegate::OnBeforeStartTransaction(
- URLRequest* request,
- const HttpRequestHeaders& headers,
- OnBeforeStartTransactionCallback callback) {
- // TestNetworkDelegate always completes synchronously.
- CHECK_NE(ERR_IO_PENDING, TestNetworkDelegate::OnBeforeStartTransaction(
- request, headers, base::NullCallback()));
- return MaybeBlockStage(
- ON_BEFORE_SEND_HEADERS,
- base::BindOnce(
- [](OnBeforeStartTransactionCallback callback, int result) {
- std::move(callback).Run(result, absl::nullopt);
- },
- std::move(callback)));
- }
- int BlockingNetworkDelegate::OnHeadersReceived(
- URLRequest* request,
- CompletionOnceCallback callback,
- const HttpResponseHeaders* original_response_headers,
- scoped_refptr<HttpResponseHeaders>* override_response_headers,
- const IPEndPoint& endpoint,
- absl::optional<GURL>* preserve_fragment_on_redirect_url) {
- // TestNetworkDelegate always completes synchronously.
- CHECK_NE(ERR_IO_PENDING,
- TestNetworkDelegate::OnHeadersReceived(
- request, base::NullCallback(), original_response_headers,
- override_response_headers, endpoint,
- preserve_fragment_on_redirect_url));
- return MaybeBlockStage(ON_HEADERS_RECEIVED, std::move(callback));
- }
- void BlockingNetworkDelegate::Reset() {
- EXPECT_NE(NOT_BLOCKED, stage_blocked_for_callback_);
- stage_blocked_for_callback_ = NOT_BLOCKED;
- callback_.Reset();
- }
- int BlockingNetworkDelegate::MaybeBlockStage(
- BlockingNetworkDelegate::Stage stage,
- CompletionOnceCallback callback) {
- // Check that the user has provided callback for the previous blocked stage.
- EXPECT_EQ(NOT_BLOCKED, stage_blocked_for_callback_);
- if ((block_on_ & stage) == 0) {
- return OK;
- }
- switch (block_mode_) {
- case SYNCHRONOUS:
- EXPECT_NE(OK, retval_);
- return retval_;
- case AUTO_CALLBACK:
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&BlockingNetworkDelegate::RunCallback,
- weak_factory_.GetWeakPtr(), retval_,
- std::move(callback)));
- return ERR_IO_PENDING;
- case USER_CALLBACK:
- callback_ = std::move(callback);
- stage_blocked_for_callback_ = stage;
- // We may reach here via a callback prior to RunUntilBlocked(), so post
- // a task to fetch and run the |on_blocked_| closure.
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&BlockingNetworkDelegate::OnBlocked,
- weak_factory_.GetWeakPtr()));
- return ERR_IO_PENDING;
- }
- NOTREACHED();
- return 0;
- }
- // A mock ReportSenderInterface that just remembers the latest report
- // URI and report to be sent.
- class MockCertificateReportSender
- : public TransportSecurityState::ReportSenderInterface {
- public:
- MockCertificateReportSender() = default;
- ~MockCertificateReportSender() override = default;
- void Send(
- const GURL& report_uri,
- base::StringPiece content_type,
- base::StringPiece report,
- const NetworkIsolationKey& network_isolation_key,
- base::OnceCallback<void()> success_callback,
- base::OnceCallback<void(const GURL&, int, int)> error_callback) override {
- latest_report_uri_ = report_uri;
- latest_report_.assign(report.data(), report.size());
- latest_content_type_.assign(content_type.data(), content_type.size());
- latest_network_isolation_key_ = network_isolation_key;
- }
- const GURL& latest_report_uri() { return latest_report_uri_; }
- const std::string& latest_report() { return latest_report_; }
- const std::string& latest_content_type() { return latest_content_type_; }
- const NetworkIsolationKey& latest_network_isolation_key() {
- return latest_network_isolation_key_;
- }
- private:
- GURL latest_report_uri_;
- std::string latest_report_;
- std::string latest_content_type_;
- NetworkIsolationKey latest_network_isolation_key_;
- };
- // OCSPErrorTestDelegate caches the SSLInfo passed to OnSSLCertificateError.
- // This is needed because after the certificate failure, the URLRequest will
- // retry the connection, and return a partial SSLInfo with a cached cert status.
- // The partial SSLInfo does not have the OCSP information filled out.
- class OCSPErrorTestDelegate : public TestDelegate {
- public:
- void OnSSLCertificateError(URLRequest* request,
- int net_error,
- const SSLInfo& ssl_info,
- bool fatal) override {
- ssl_info_ = ssl_info;
- on_ssl_certificate_error_called_ = true;
- TestDelegate::OnSSLCertificateError(request, net_error, ssl_info, fatal);
- }
- bool on_ssl_certificate_error_called() {
- return on_ssl_certificate_error_called_;
- }
- SSLInfo ssl_info() { return ssl_info_; }
- private:
- bool on_ssl_certificate_error_called_ = false;
- SSLInfo ssl_info_;
- };
- #if !BUILDFLAG(IS_IOS)
- // Compute the root cert's SPKI hash on the fly, to avoid hardcoding it within
- // tests.
- bool GetTestRootCertSPKIHash(SHA256HashValue* root_hash) {
- scoped_refptr<X509Certificate> root_cert =
- ImportCertFromFile(GetTestCertsDirectory(), "root_ca_cert.pem");
- if (!root_cert)
- return false;
- base::StringPiece root_spki;
- if (!asn1::ExtractSPKIFromDERCert(
- x509_util::CryptoBufferAsStringPiece(root_cert->cert_buffer()),
- &root_spki)) {
- return false;
- }
- crypto::SHA256HashString(root_spki, root_hash, sizeof(SHA256HashValue));
- return true;
- }
- #endif
- } // namespace
- // Inherit PlatformTest since we require the autorelease pool on Mac OS X.
- class URLRequestTest : public PlatformTest, public WithTaskEnvironment {
- public:
- URLRequestTest() = default;
- ~URLRequestTest() override {
- // URLRequestJobs may post clean-up tasks on destruction.
- base::RunLoop().RunUntilIdle();
- SetTransportSecurityStateSourceForTesting(nullptr);
- }
- void SetUp() override {
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_net_log(NetLog::Get());
- SetUpContextBuilder(*context_builder);
- // We set the TestNetworkDelegate after calling SetUpContextBuilder as
- // default_network_delegate() relies on this set up and we don't want to
- // allow subclasses to break the assumption.
- context_builder->set_network_delegate(
- std::make_unique<TestNetworkDelegate>());
- default_context_ = context_builder->Build();
- PlatformTest::SetUp();
- }
- void TearDown() override { default_context_.reset(); }
- virtual void SetUpContextBuilder(URLRequestContextBuilder& builder) {}
- TestNetworkDelegate& default_network_delegate() {
- // This cast is safe because we provided a TestNetworkDelegate in SetUp().
- return *static_cast<TestNetworkDelegate*>(
- default_context_->network_delegate());
- }
- URLRequestContext& default_context() const { return *default_context_; }
- // Creates a temp test file and writes |data| to the file. The file will be
- // deleted after the test completes.
- void CreateTestFile(const char* data,
- size_t data_size,
- base::FilePath* test_file) {
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- // Get an absolute path since |temp_dir| can contain a symbolic link. As of
- // now, Mac and Android bots return a path with a symbolic link.
- base::FilePath absolute_temp_dir =
- base::MakeAbsoluteFilePath(temp_dir_.GetPath());
- ASSERT_TRUE(base::CreateTemporaryFileInDir(absolute_temp_dir, test_file));
- ASSERT_EQ(static_cast<int>(data_size),
- base::WriteFile(*test_file, data, data_size));
- }
- static std::unique_ptr<ConfiguredProxyResolutionService>
- CreateFixedProxyResolutionService(const std::string& proxy) {
- return ConfiguredProxyResolutionService::CreateFixedForTest(
- proxy, TRAFFIC_ANNOTATION_FOR_TESTS);
- }
- std::unique_ptr<URLRequest> CreateFirstPartyRequest(
- const URLRequestContext& context,
- const GURL& url,
- URLRequest::Delegate* delegate) {
- auto req = context.CreateRequest(url, DEFAULT_PRIORITY, delegate,
- TRAFFIC_ANNOTATION_FOR_TESTS);
- req->set_initiator(url::Origin::Create(url));
- req->set_site_for_cookies(SiteForCookies::FromUrl(url));
- return req;
- }
- protected:
- RecordingNetLogObserver net_log_observer_;
- std::unique_ptr<URLRequestContext> default_context_;
- base::ScopedTempDir temp_dir_;
- };
- TEST_F(URLRequestTest, AboutBlankTest) {
- TestDelegate d;
- {
- std::unique_ptr<URLRequest> r(
- default_context().CreateRequest(GURL("about:blank"), DEFAULT_PRIORITY,
- &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_TRUE(!r->is_pending());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_EQ(d.bytes_received(), 0);
- EXPECT_TRUE(r->GetResponseRemoteEndpoint().address().empty());
- EXPECT_EQ(0, r->GetResponseRemoteEndpoint().port());
- }
- }
- TEST_F(URLRequestTest, InvalidUrlTest) {
- TestDelegate d;
- {
- std::unique_ptr<URLRequest> r(
- default_context().CreateRequest(GURL("invalid url"), DEFAULT_PRIORITY,
- &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_TRUE(d.request_failed());
- }
- }
- // Test that URLRequest rejects WS URLs by default.
- TEST_F(URLRequestTest, WsUrlTest) {
- const url::Origin kOrigin = url::Origin::Create(GURL("http://foo.test/"));
- TestDelegate d;
- std::unique_ptr<URLRequest> r(
- default_context().CreateRequest(GURL("ws://foo.test/"), DEFAULT_PRIORITY,
- &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- // This is not strictly necessary for this test, but used to trigger a DCHECK.
- // See https://crbug.com/1245115.
- r->set_isolation_info(
- IsolationInfo::Create(IsolationInfo::RequestType::kMainFrame, kOrigin,
- kOrigin, SiteForCookies::FromOrigin(kOrigin)));
- r->Start();
- d.RunUntilComplete();
- EXPECT_TRUE(d.request_failed());
- EXPECT_THAT(d.request_status(), IsError(ERR_UNKNOWN_URL_SCHEME));
- }
- // Test that URLRequest rejects WSS URLs by default.
- TEST_F(URLRequestTest, WssUrlTest) {
- const url::Origin kOrigin = url::Origin::Create(GURL("https://foo.test/"));
- TestDelegate d;
- std::unique_ptr<URLRequest> r(
- default_context().CreateRequest(GURL("wss://foo.test/"), DEFAULT_PRIORITY,
- &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- // This is not strictly necessary for this test, but used to trigger a DCHECK.
- // See https://crbug.com/1245115.
- r->set_isolation_info(
- IsolationInfo::Create(IsolationInfo::RequestType::kMainFrame, kOrigin,
- kOrigin, SiteForCookies::FromOrigin(kOrigin)));
- r->Start();
- d.RunUntilComplete();
- EXPECT_TRUE(d.request_failed());
- EXPECT_THAT(d.request_status(), IsError(ERR_UNKNOWN_URL_SCHEME));
- }
- TEST_F(URLRequestTest, InvalidReferrerTest) {
- default_network_delegate().set_cancel_request_with_policy_violating_referrer(
- true);
- TestDelegate d;
- std::unique_ptr<URLRequest> req = default_context().CreateRequest(
- GURL("http://localhost/"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS);
- req->SetReferrer("https://somewhere.com/");
- req->Start();
- d.RunUntilComplete();
- EXPECT_TRUE(d.request_failed());
- }
- TEST_F(URLRequestTest, RecordsSameOriginReferrerHistogram) {
- default_network_delegate().set_cancel_request_with_policy_violating_referrer(
- false);
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- GURL("http://google.com/"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->SetReferrer("http://google.com");
- req->set_referrer_policy(ReferrerPolicy::NEVER_CLEAR);
- base::HistogramTester histograms;
- req->Start();
- d.RunUntilComplete();
- histograms.ExpectUniqueSample(
- "Net.URLRequest.ReferrerPolicyForRequest.SameOrigin",
- static_cast<int>(ReferrerPolicy::NEVER_CLEAR), 1);
- }
- TEST_F(URLRequestTest, RecordsCrossOriginReferrerHistogram) {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- GURL("http://google.com/"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->SetReferrer("http://origin.com");
- // Set a different policy just to make sure we aren't always logging the same
- // policy.
- req->set_referrer_policy(
- ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE);
- base::HistogramTester histograms;
- req->Start();
- d.RunUntilComplete();
- histograms.ExpectUniqueSample(
- "Net.URLRequest.ReferrerPolicyForRequest.CrossOrigin",
- static_cast<int>(
- ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE),
- 1);
- }
- TEST_F(URLRequestTest, RecordsReferrerHistogramAgainOnRedirect) {
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto network_delegate = std::make_unique<BlockingNetworkDelegate>(
- BlockingNetworkDelegate::SYNCHRONOUS);
- network_delegate->set_redirect_url(GURL("http://redirect.com/"));
- context_builder->set_network_delegate(std::move(network_delegate));
- auto context = context_builder->Build();
- TestDelegate d;
- std::unique_ptr<URLRequest> req(
- context->CreateRequest(GURL("http://google.com/"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->SetReferrer("http://google.com");
- req->set_referrer_policy(
- ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE);
- base::HistogramTester histograms;
- req->Start();
- d.RunUntilRedirect();
- histograms.ExpectUniqueSample(
- "Net.URLRequest.ReferrerPolicyForRequest.SameOrigin",
- static_cast<int>(
- ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE),
- 1);
- req->FollowDeferredRedirect(/*removed_headers=*/absl::nullopt,
- /*modified_headers=*/absl::nullopt);
- d.RunUntilComplete();
- histograms.ExpectUniqueSample(
- "Net.URLRequest.ReferrerPolicyForRequest.CrossOrigin",
- static_cast<int>(
- ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE),
- 1);
- }
- TEST_F(URLRequestTest, RecordsReferrrerWithInformativePath) {
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto network_delegate = std::make_unique<BlockingNetworkDelegate>(
- BlockingNetworkDelegate::SYNCHRONOUS);
- network_delegate->set_cancel_request_with_policy_violating_referrer(true);
- network_delegate->set_redirect_url(GURL("http://redirect.com/"));
- context_builder->set_network_delegate(std::move(network_delegate));
- auto context = context_builder->Build();
- TestDelegate d;
- std::unique_ptr<URLRequest> req(
- context->CreateRequest(GURL("http://google.com/"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- // Since this referrer is much more informative than the initiating origin,
- // we should see the histograms' true buckets populated.
- req->SetReferrer("http://google.com/very-informative-path");
- base::HistogramTester histograms;
- req->Start();
- d.RunUntilRedirect();
- histograms.ExpectUniqueSample(
- "Net.URLRequest.ReferrerHasInformativePath.SameOrigin",
- /* Check the count of the "true" bucket in the boolean histogram. */ true,
- 1);
- req->FollowDeferredRedirect(/*removed_headers=*/absl::nullopt,
- /*modified_headers=*/absl::nullopt);
- d.RunUntilComplete();
- histograms.ExpectUniqueSample(
- "Net.URLRequest.ReferrerHasInformativePath.CrossOrigin", true, 1);
- }
- TEST_F(URLRequestTest, RecordsReferrerWithInformativeQuery) {
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto network_delegate = std::make_unique<BlockingNetworkDelegate>(
- BlockingNetworkDelegate::SYNCHRONOUS);
- network_delegate->set_cancel_request_with_policy_violating_referrer(true);
- network_delegate->set_redirect_url(GURL("http://redirect.com/"));
- context_builder->set_network_delegate(std::move(network_delegate));
- auto context = context_builder->Build();
- TestDelegate d;
- std::unique_ptr<URLRequest> req(
- context->CreateRequest(GURL("http://google.com/"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- // Since this referrer is much more informative than the initiating origin,
- // we should see the histograms' true buckets populated.
- req->SetReferrer("http://google.com/?very-informative-query");
- base::HistogramTester histograms;
- req->Start();
- d.RunUntilRedirect();
- histograms.ExpectUniqueSample(
- "Net.URLRequest.ReferrerHasInformativePath.SameOrigin",
- /* Check the count of the "true" bucket in the boolean histogram. */ true,
- 1);
- req->FollowDeferredRedirect(/*removed_headers=*/absl::nullopt,
- /*modified_headers=*/absl::nullopt);
- d.RunUntilComplete();
- histograms.ExpectUniqueSample(
- "Net.URLRequest.ReferrerHasInformativePath.CrossOrigin", true, 1);
- }
- TEST_F(URLRequestTest, RecordsReferrerWithoutInformativePathOrQuery) {
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto network_delegate = std::make_unique<BlockingNetworkDelegate>(
- BlockingNetworkDelegate::SYNCHRONOUS);
- network_delegate->set_cancel_request_with_policy_violating_referrer(false);
- network_delegate->set_redirect_url(GURL("http://origin.com/"));
- context_builder->set_network_delegate(std::move(network_delegate));
- auto context = context_builder->Build();
- TestDelegate d;
- std::unique_ptr<URLRequest> req(
- context->CreateRequest(GURL("http://google.com/"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- // Since this referrer _isn't_ more informative than the initiating origin,
- // we should see the histograms' false buckets populated.
- req->SetReferrer("http://origin.com");
- base::HistogramTester histograms;
- req->Start();
- d.RunUntilRedirect();
- histograms.ExpectUniqueSample(
- "Net.URLRequest.ReferrerHasInformativePath.CrossOrigin", false, 1);
- req->FollowDeferredRedirect(/*removed_headers=*/absl::nullopt,
- /*modified_headers=*/absl::nullopt);
- d.RunUntilComplete();
- histograms.ExpectUniqueSample(
- "Net.URLRequest.ReferrerHasInformativePath.SameOrigin", false, 1);
- }
- // A URLRequestInterceptor that allows setting the LoadTimingInfo value of the
- // URLRequestJobs it creates.
- class URLRequestInterceptorWithLoadTimingInfo : public URLRequestInterceptor {
- public:
- // Static getters for canned response header and data strings.
- static std::string ok_data() { return URLRequestTestJob::test_data_1(); }
- static std::string ok_headers() { return URLRequestTestJob::test_headers(); }
- URLRequestInterceptorWithLoadTimingInfo() = default;
- ~URLRequestInterceptorWithLoadTimingInfo() override = default;
- // URLRequestInterceptor implementation:
- std::unique_ptr<URLRequestJob> MaybeInterceptRequest(
- URLRequest* request) const override {
- std::unique_ptr<URLRequestTestJob> job =
- std::make_unique<URLRequestTestJob>(request, ok_headers(), ok_data(),
- true);
- job->set_load_timing_info(main_request_load_timing_info_);
- return job;
- }
- void set_main_request_load_timing_info(
- const LoadTimingInfo& main_request_load_timing_info) {
- main_request_load_timing_info_ = main_request_load_timing_info;
- }
- private:
- mutable LoadTimingInfo main_request_load_timing_info_;
- };
- // These tests inject a MockURLRequestInterceptor
- class URLRequestLoadTimingTest : public URLRequestTest {
- public:
- URLRequestLoadTimingTest() {
- std::unique_ptr<URLRequestInterceptorWithLoadTimingInfo> interceptor =
- std::make_unique<URLRequestInterceptorWithLoadTimingInfo>();
- interceptor_ = interceptor.get();
- URLRequestFilter::GetInstance()->AddHostnameInterceptor(
- "http", "test_intercept", std::move(interceptor));
- }
- ~URLRequestLoadTimingTest() override {
- URLRequestFilter::GetInstance()->ClearHandlers();
- }
- URLRequestInterceptorWithLoadTimingInfo* interceptor() const {
- return interceptor_;
- }
- private:
- raw_ptr<URLRequestInterceptorWithLoadTimingInfo> interceptor_;
- };
- // "Normal" LoadTimingInfo as returned by a job. Everything is in order, not
- // reused. |connect_time_flags| is used to indicate if there should be dns
- // or SSL times, and |used_proxy| is used for proxy times.
- LoadTimingInfo NormalLoadTimingInfo(base::TimeTicks now,
- int connect_time_flags,
- bool used_proxy) {
- LoadTimingInfo load_timing;
- load_timing.socket_log_id = 1;
- if (used_proxy) {
- load_timing.proxy_resolve_start = now + base::Days(1);
- load_timing.proxy_resolve_end = now + base::Days(2);
- }
- LoadTimingInfo::ConnectTiming& connect_timing = load_timing.connect_timing;
- if (connect_time_flags & CONNECT_TIMING_HAS_DNS_TIMES) {
- connect_timing.dns_start = now + base::Days(3);
- connect_timing.dns_end = now + base::Days(4);
- }
- connect_timing.connect_start = now + base::Days(5);
- if (connect_time_flags & CONNECT_TIMING_HAS_SSL_TIMES) {
- connect_timing.ssl_start = now + base::Days(6);
- connect_timing.ssl_end = now + base::Days(7);
- }
- connect_timing.connect_end = now + base::Days(8);
- load_timing.send_start = now + base::Days(9);
- load_timing.send_end = now + base::Days(10);
- load_timing.receive_headers_start = now + base::Days(11);
- load_timing.receive_headers_end = now + base::Days(12);
- return load_timing;
- }
- // Same as above, but in the case of a reused socket.
- LoadTimingInfo NormalLoadTimingInfoReused(base::TimeTicks now,
- bool used_proxy) {
- LoadTimingInfo load_timing;
- load_timing.socket_log_id = 1;
- load_timing.socket_reused = true;
- if (used_proxy) {
- load_timing.proxy_resolve_start = now + base::Days(1);
- load_timing.proxy_resolve_end = now + base::Days(2);
- }
- load_timing.send_start = now + base::Days(9);
- load_timing.send_end = now + base::Days(10);
- load_timing.receive_headers_start = now + base::Days(11);
- load_timing.receive_headers_end = now + base::Days(12);
- return load_timing;
- }
- LoadTimingInfo RunURLRequestInterceptorLoadTimingTest(
- const LoadTimingInfo& job_load_timing,
- const URLRequestContext& context,
- URLRequestInterceptorWithLoadTimingInfo* interceptor) {
- interceptor->set_main_request_load_timing_info(job_load_timing);
- TestDelegate d;
- std::unique_ptr<URLRequest> req(
- context.CreateRequest(GURL("http://test_intercept/foo"), DEFAULT_PRIORITY,
- &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- LoadTimingInfo resulting_load_timing;
- req->GetLoadTimingInfo(&resulting_load_timing);
- // None of these should be modified by the URLRequest.
- EXPECT_EQ(job_load_timing.socket_reused, resulting_load_timing.socket_reused);
- EXPECT_EQ(job_load_timing.socket_log_id, resulting_load_timing.socket_log_id);
- EXPECT_EQ(job_load_timing.send_start, resulting_load_timing.send_start);
- EXPECT_EQ(job_load_timing.send_end, resulting_load_timing.send_end);
- EXPECT_EQ(job_load_timing.receive_headers_start,
- resulting_load_timing.receive_headers_start);
- EXPECT_EQ(job_load_timing.receive_headers_end,
- resulting_load_timing.receive_headers_end);
- EXPECT_EQ(job_load_timing.push_start, resulting_load_timing.push_start);
- EXPECT_EQ(job_load_timing.push_end, resulting_load_timing.push_end);
- return resulting_load_timing;
- }
- // Basic test that the intercept + load timing tests work.
- TEST_F(URLRequestLoadTimingTest, InterceptLoadTiming) {
- base::TimeTicks now = base::TimeTicks::Now();
- LoadTimingInfo job_load_timing =
- NormalLoadTimingInfo(now, CONNECT_TIMING_HAS_DNS_TIMES, false);
- LoadTimingInfo load_timing_result = RunURLRequestInterceptorLoadTimingTest(
- job_load_timing, default_context(), interceptor());
- // Nothing should have been changed by the URLRequest.
- EXPECT_EQ(job_load_timing.proxy_resolve_start,
- load_timing_result.proxy_resolve_start);
- EXPECT_EQ(job_load_timing.proxy_resolve_end,
- load_timing_result.proxy_resolve_end);
- EXPECT_EQ(job_load_timing.connect_timing.dns_start,
- load_timing_result.connect_timing.dns_start);
- EXPECT_EQ(job_load_timing.connect_timing.dns_end,
- load_timing_result.connect_timing.dns_end);
- EXPECT_EQ(job_load_timing.connect_timing.connect_start,
- load_timing_result.connect_timing.connect_start);
- EXPECT_EQ(job_load_timing.connect_timing.connect_end,
- load_timing_result.connect_timing.connect_end);
- EXPECT_EQ(job_load_timing.connect_timing.ssl_start,
- load_timing_result.connect_timing.ssl_start);
- EXPECT_EQ(job_load_timing.connect_timing.ssl_end,
- load_timing_result.connect_timing.ssl_end);
- // Redundant sanity check.
- TestLoadTimingNotReused(load_timing_result, CONNECT_TIMING_HAS_DNS_TIMES);
- }
- // Another basic test, with proxy and SSL times, but no DNS times.
- TEST_F(URLRequestLoadTimingTest, InterceptLoadTimingProxy) {
- base::TimeTicks now = base::TimeTicks::Now();
- LoadTimingInfo job_load_timing =
- NormalLoadTimingInfo(now, CONNECT_TIMING_HAS_SSL_TIMES, true);
- LoadTimingInfo load_timing_result = RunURLRequestInterceptorLoadTimingTest(
- job_load_timing, default_context(), interceptor());
- // Nothing should have been changed by the URLRequest.
- EXPECT_EQ(job_load_timing.proxy_resolve_start,
- load_timing_result.proxy_resolve_start);
- EXPECT_EQ(job_load_timing.proxy_resolve_end,
- load_timing_result.proxy_resolve_end);
- EXPECT_EQ(job_load_timing.connect_timing.dns_start,
- load_timing_result.connect_timing.dns_start);
- EXPECT_EQ(job_load_timing.connect_timing.dns_end,
- load_timing_result.connect_timing.dns_end);
- EXPECT_EQ(job_load_timing.connect_timing.connect_start,
- load_timing_result.connect_timing.connect_start);
- EXPECT_EQ(job_load_timing.connect_timing.connect_end,
- load_timing_result.connect_timing.connect_end);
- EXPECT_EQ(job_load_timing.connect_timing.ssl_start,
- load_timing_result.connect_timing.ssl_start);
- EXPECT_EQ(job_load_timing.connect_timing.ssl_end,
- load_timing_result.connect_timing.ssl_end);
- // Redundant sanity check.
- TestLoadTimingNotReusedWithProxy(load_timing_result,
- CONNECT_TIMING_HAS_SSL_TIMES);
- }
- // Make sure that URLRequest correctly adjusts proxy times when they're before
- // |request_start|, due to already having a connected socket. This happens in
- // the case of reusing a SPDY session. The connected socket is not considered
- // reused in this test (May be a preconnect).
- //
- // To mix things up from the test above, assumes DNS times but no SSL times.
- TEST_F(URLRequestLoadTimingTest, InterceptLoadTimingEarlyProxyResolution) {
- base::TimeTicks now = base::TimeTicks::Now();
- LoadTimingInfo job_load_timing =
- NormalLoadTimingInfo(now, CONNECT_TIMING_HAS_DNS_TIMES, true);
- job_load_timing.proxy_resolve_start = now - base::Days(6);
- job_load_timing.proxy_resolve_end = now - base::Days(5);
- job_load_timing.connect_timing.dns_start = now - base::Days(4);
- job_load_timing.connect_timing.dns_end = now - base::Days(3);
- job_load_timing.connect_timing.connect_start = now - base::Days(2);
- job_load_timing.connect_timing.connect_end = now - base::Days(1);
- LoadTimingInfo load_timing_result = RunURLRequestInterceptorLoadTimingTest(
- job_load_timing, default_context(), interceptor());
- // Proxy times, connect times, and DNS times should all be replaced with
- // request_start.
- EXPECT_EQ(load_timing_result.request_start,
- load_timing_result.proxy_resolve_start);
- EXPECT_EQ(load_timing_result.request_start,
- load_timing_result.proxy_resolve_end);
- EXPECT_EQ(load_timing_result.request_start,
- load_timing_result.connect_timing.dns_start);
- EXPECT_EQ(load_timing_result.request_start,
- load_timing_result.connect_timing.dns_end);
- EXPECT_EQ(load_timing_result.request_start,
- load_timing_result.connect_timing.connect_start);
- EXPECT_EQ(load_timing_result.request_start,
- load_timing_result.connect_timing.connect_end);
- // Other times should have been left null.
- TestLoadTimingNotReusedWithProxy(load_timing_result,
- CONNECT_TIMING_HAS_DNS_TIMES);
- }
- // Same as above, but in the reused case.
- TEST_F(URLRequestLoadTimingTest,
- InterceptLoadTimingEarlyProxyResolutionReused) {
- base::TimeTicks now = base::TimeTicks::Now();
- LoadTimingInfo job_load_timing = NormalLoadTimingInfoReused(now, true);
- job_load_timing.proxy_resolve_start = now - base::Days(4);
- job_load_timing.proxy_resolve_end = now - base::Days(3);
- LoadTimingInfo load_timing_result = RunURLRequestInterceptorLoadTimingTest(
- job_load_timing, default_context(), interceptor());
- // Proxy times and connect times should all be replaced with request_start.
- EXPECT_EQ(load_timing_result.request_start,
- load_timing_result.proxy_resolve_start);
- EXPECT_EQ(load_timing_result.request_start,
- load_timing_result.proxy_resolve_end);
- // Other times should have been left null.
- TestLoadTimingReusedWithProxy(load_timing_result);
- }
- // Make sure that URLRequest correctly adjusts connect times when they're before
- // |request_start|, due to reusing a connected socket. The connected socket is
- // not considered reused in this test (May be a preconnect).
- //
- // To mix things up, the request has SSL times, but no DNS times.
- TEST_F(URLRequestLoadTimingTest, InterceptLoadTimingEarlyConnect) {
- base::TimeTicks now = base::TimeTicks::Now();
- LoadTimingInfo job_load_timing =
- NormalLoadTimingInfo(now, CONNECT_TIMING_HAS_SSL_TIMES, false);
- job_load_timing.connect_timing.connect_start = now - base::Days(1);
- job_load_timing.connect_timing.ssl_start = now - base::Days(2);
- job_load_timing.connect_timing.ssl_end = now - base::Days(3);
- job_load_timing.connect_timing.connect_end = now - base::Days(4);
- LoadTimingInfo load_timing_result = RunURLRequestInterceptorLoadTimingTest(
- job_load_timing, default_context(), interceptor());
- // Connect times, and SSL times should be replaced with request_start.
- EXPECT_EQ(load_timing_result.request_start,
- load_timing_result.connect_timing.connect_start);
- EXPECT_EQ(load_timing_result.request_start,
- load_timing_result.connect_timing.ssl_start);
- EXPECT_EQ(load_timing_result.request_start,
- load_timing_result.connect_timing.ssl_end);
- EXPECT_EQ(load_timing_result.request_start,
- load_timing_result.connect_timing.connect_end);
- // Other times should have been left null.
- TestLoadTimingNotReused(load_timing_result, CONNECT_TIMING_HAS_SSL_TIMES);
- }
- // Make sure that URLRequest correctly adjusts connect times when they're before
- // |request_start|, due to reusing a connected socket in the case that there
- // are also proxy times. The connected socket is not considered reused in this
- // test (May be a preconnect).
- //
- // In this test, there are no SSL or DNS times.
- TEST_F(URLRequestLoadTimingTest, InterceptLoadTimingEarlyConnectWithProxy) {
- base::TimeTicks now = base::TimeTicks::Now();
- LoadTimingInfo job_load_timing =
- NormalLoadTimingInfo(now, CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY, true);
- job_load_timing.connect_timing.connect_start = now - base::Days(1);
- job_load_timing.connect_timing.connect_end = now - base::Days(2);
- LoadTimingInfo load_timing_result = RunURLRequestInterceptorLoadTimingTest(
- job_load_timing, default_context(), interceptor());
- // Connect times should be replaced with proxy_resolve_end.
- EXPECT_EQ(load_timing_result.proxy_resolve_end,
- load_timing_result.connect_timing.connect_start);
- EXPECT_EQ(load_timing_result.proxy_resolve_end,
- load_timing_result.connect_timing.connect_end);
- // Other times should have been left null.
- TestLoadTimingNotReusedWithProxy(load_timing_result,
- CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
- }
- TEST_F(URLRequestTest, NetworkDelegateProxyError) {
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_proxy_resolution_service(
- CreateFixedProxyResolutionService("myproxy:70"));
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<TestNetworkDelegate>());
- auto host_resolver = std::make_unique<MockHostResolver>();
- host_resolver->rules()->AddSimulatedTimeoutFailure("*");
- context_builder->set_host_resolver(std::move(host_resolver));
- auto context = context_builder->Build();
- TestDelegate d;
- std::unique_ptr<URLRequest> req(
- context->CreateRequest(GURL("http://example.com"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_method("GET");
- req->Start();
- d.RunUntilComplete();
- // Check we see a failed request.
- // The proxy server should be set before failure.
- EXPECT_EQ(PacResultElementToProxyServer("PROXY myproxy:70"),
- req->proxy_server());
- EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, d.request_status());
- EXPECT_THAT(req->response_info().resolve_error_info.error,
- IsError(ERR_DNS_TIMED_OUT));
- EXPECT_EQ(1, network_delegate.error_count());
- EXPECT_THAT(network_delegate.last_error(),
- IsError(ERR_PROXY_CONNECTION_FAILED));
- EXPECT_EQ(1, network_delegate.completed_requests());
- }
- // Test that when host resolution fails with `ERR_DNS_NAME_HTTPS_ONLY` for
- // "http://" requests, scheme is upgraded to "https://".
- TEST_F(URLRequestTest, DnsNameHttpsOnlyErrorCausesSchemeUpgrade) {
- base::test::ScopedFeatureList features;
- features.InitAndEnableFeatureWithParameters(
- features::kUseDnsHttpsSvcb, {{"UseDnsHttpsSvcbHttpUpgrade", "true"}});
- EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS);
- https_server.SetSSLConfig(EmbeddedTestServer::CERT_TEST_NAMES);
- RegisterDefaultHandlers(&https_server);
- ASSERT_TRUE(https_server.Start());
- // Build an http URL that should be auto-upgraded to https.
- const std::string kHost = "foo.a.test"; // Covered by CERT_TEST_NAMES.
- const GURL https_url = https_server.GetURL(kHost, "/defaultresponse");
- GURL::Replacements replacements;
- replacements.SetSchemeStr(url::kHttpScheme);
- const GURL http_url = https_url.ReplaceComponents(replacements);
- // Return `ERR_DNS_NAME_HTTPS_ONLY` for "http://" requests and an address for
- // "https://" requests. This simulates the HostResolver behavior for a domain
- // with an HTTPS DNS record.
- auto host_resolver = std::make_unique<MockHostResolver>();
- MockHostResolverBase::RuleResolver::RuleKey unencrypted_resolve_key;
- unencrypted_resolve_key.scheme = url::kHttpScheme;
- unencrypted_resolve_key.hostname_pattern = kHost;
- host_resolver->rules()->AddRule(std::move(unencrypted_resolve_key),
- ERR_DNS_NAME_HTTPS_ONLY);
- MockHostResolverBase::RuleResolver::RuleKey encrypted_resolve_key;
- encrypted_resolve_key.scheme = url::kHttpsScheme;
- encrypted_resolve_key.hostname_pattern = kHost;
- host_resolver->rules()->AddRule(std::move(encrypted_resolve_key),
- https_server.GetIPLiteralString());
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_host_resolver(std::move(host_resolver));
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<TestNetworkDelegate>());
- auto context = context_builder->Build();
- TestDelegate d;
- std::unique_ptr<URLRequest> req(context->CreateRequest(
- http_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- EXPECT_FALSE(req->url().SchemeIsCryptographic());
- // Note that there is no http server running, so the request should fail or
- // hang if its scheme is not upgraded to https.
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(d.received_redirect_count(), 1);
- EXPECT_EQ(0, network_delegate.error_count());
- EXPECT_EQ(200, req->GetResponseCode());
- ASSERT_TRUE(req->response_headers());
- EXPECT_EQ(200, req->response_headers()->response_code());
- // Observe that the scheme has been upgraded to https.
- EXPECT_TRUE(req->url().SchemeIsCryptographic());
- EXPECT_TRUE(req->url().SchemeIs(url::kHttpsScheme));
- }
- // Test that DNS-based scheme upgrade supports deferred redirect.
- TEST_F(URLRequestTest, DnsNameHttpsOnlyErrorCausesSchemeUpgradeDeferred) {
- base::test::ScopedFeatureList features;
- features.InitAndEnableFeatureWithParameters(
- features::kUseDnsHttpsSvcb, {{"UseDnsHttpsSvcbHttpUpgrade", "true"}});
- EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS);
- https_server.SetSSLConfig(EmbeddedTestServer::CERT_TEST_NAMES);
- RegisterDefaultHandlers(&https_server);
- ASSERT_TRUE(https_server.Start());
- // Build an http URL that should be auto-upgraded to https.
- const std::string kHost = "foo.a.test"; // Covered by CERT_TEST_NAMES.
- const GURL https_url = https_server.GetURL(kHost, "/defaultresponse");
- GURL::Replacements replacements;
- replacements.SetSchemeStr(url::kHttpScheme);
- const GURL http_url = https_url.ReplaceComponents(replacements);
- // Return `ERR_DNS_NAME_HTTPS_ONLY` for "http://" requests and an address for
- // "https://" requests. This simulates the HostResolver behavior for a domain
- // with an HTTPS DNS record.
- auto host_resolver = std::make_unique<MockHostResolver>();
- MockHostResolverBase::RuleResolver::RuleKey unencrypted_resolve_key;
- unencrypted_resolve_key.scheme = url::kHttpScheme;
- unencrypted_resolve_key.hostname_pattern = kHost;
- host_resolver->rules()->AddRule(std::move(unencrypted_resolve_key),
- ERR_DNS_NAME_HTTPS_ONLY);
- MockHostResolverBase::RuleResolver::RuleKey encrypted_resolve_key;
- encrypted_resolve_key.scheme = url::kHttpsScheme;
- encrypted_resolve_key.hostname_pattern = kHost;
- host_resolver->rules()->AddRule(std::move(encrypted_resolve_key),
- https_server.GetIPLiteralString());
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_host_resolver(std::move(host_resolver));
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<TestNetworkDelegate>());
- auto context = context_builder->Build();
- TestDelegate d;
- std::unique_ptr<URLRequest> req(context->CreateRequest(
- http_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- EXPECT_FALSE(req->url().SchemeIsCryptographic());
- // Note that there is no http server running, so the request should fail or
- // hang if its scheme is not upgraded to https.
- req->Start();
- d.RunUntilRedirect();
- EXPECT_EQ(d.received_redirect_count(), 1);
- req->FollowDeferredRedirect(/*removed_headers=*/absl::nullopt,
- /*modified_headers=*/absl::nullopt);
- d.RunUntilComplete();
- EXPECT_EQ(0, network_delegate.error_count());
- EXPECT_EQ(200, req->GetResponseCode());
- ASSERT_TRUE(req->response_headers());
- EXPECT_EQ(200, req->response_headers()->response_code());
- // Observe that the scheme has been upgraded to https.
- EXPECT_TRUE(req->url().SchemeIsCryptographic());
- EXPECT_TRUE(req->url().SchemeIs(url::kHttpsScheme));
- }
- #if BUILDFLAG(ENABLE_WEBSOCKETS)
- // Test that requests with "ws" scheme are upgraded to "wss" when DNS
- // indicates that the name is HTTPS-only.
- TEST_F(URLRequestTest, DnsHttpsRecordPresentCausesWsSchemeUpgrade) {
- base::test::ScopedFeatureList features;
- features.InitAndEnableFeatureWithParameters(
- features::kUseDnsHttpsSvcb, {{"UseDnsHttpsSvcbHttpUpgrade", "true"}});
- EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS);
- https_server.SetSSLConfig(EmbeddedTestServer::CERT_TEST_NAMES);
- RegisterDefaultHandlers(&https_server);
- ASSERT_TRUE(https_server.Start());
- // Build an http URL that should be auto-upgraded to https.
- const std::string kHost = "foo.a.test"; // Covered by CERT_TEST_NAMES.
- const GURL https_url = https_server.GetURL(kHost, "/defaultresponse");
- GURL::Replacements replacements;
- replacements.SetSchemeStr(url::kWsScheme);
- const GURL ws_url = https_url.ReplaceComponents(replacements);
- auto host_resolver = std::make_unique<MockHostResolver>();
- MockHostResolverBase::RuleResolver::RuleKey unencrypted_resolve_key;
- unencrypted_resolve_key.scheme = url::kHttpScheme;
- unencrypted_resolve_key.hostname_pattern = kHost;
- host_resolver->rules()->AddRule(std::move(unencrypted_resolve_key),
- ERR_DNS_NAME_HTTPS_ONLY);
- MockHostResolverBase::RuleResolver::RuleKey encrypted_resolve_key;
- encrypted_resolve_key.scheme = url::kHttpsScheme;
- encrypted_resolve_key.hostname_pattern = kHost;
- host_resolver->rules()->AddRule(std::move(encrypted_resolve_key),
- https_server.GetIPLiteralString());
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_host_resolver(std::move(host_resolver));
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<TestNetworkDelegate>());
- auto context = context_builder->Build();
- TestDelegate d;
- std::unique_ptr<URLRequest> req(context->CreateRequest(
- ws_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS,
- /*is_for_websockets=*/true));
- EXPECT_FALSE(req->url().SchemeIsCryptographic());
- HttpRequestHeaders headers = WebSocketCommonTestHeaders();
- req->SetExtraRequestHeaders(headers);
- auto websocket_stream_create_helper =
- std::make_unique<TestWebSocketHandshakeStreamCreateHelper>();
- req->SetUserData(kWebSocketHandshakeUserDataKey,
- std::move(websocket_stream_create_helper));
- // Note that there is no ws server running, so the request should fail or hang
- // if its scheme is not upgraded to wss.
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(d.received_redirect_count(), 1);
- // Expect failure because test server is not set up to provide websocket
- // responses.
- EXPECT_EQ(network_delegate.error_count(), 1);
- EXPECT_EQ(network_delegate.last_error(), ERR_INVALID_RESPONSE);
- // Observe that the scheme has been upgraded to wss.
- EXPECT_TRUE(req->url().SchemeIsCryptographic());
- EXPECT_TRUE(req->url().SchemeIs(url::kWssScheme));
- }
- #endif // BUILDFLAG(ENABLE_WEBSOCKETS)
- TEST_F(URLRequestTest, DnsHttpsRecordAbsentNoSchemeUpgrade) {
- base::test::ScopedFeatureList features;
- features.InitAndEnableFeatureWithParameters(
- features::kUseDnsHttpsSvcb, {{"UseDnsHttpsSvcbHttpUpgrade", "true"}});
- EmbeddedTestServer http_server(EmbeddedTestServer::TYPE_HTTP);
- RegisterDefaultHandlers(&http_server);
- ASSERT_TRUE(http_server.Start());
- // Build an http URL that should be auto-upgraded to https.
- const std::string kHost = "foo.a.test"; // Covered by CERT_TEST_NAMES.
- const GURL http_url = http_server.GetURL(kHost, "/defaultresponse");
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto host_resolver = std::make_unique<MockHostResolver>();
- host_resolver->rules()->AddRule(kHost, http_server.GetIPLiteralString());
- context_builder->set_host_resolver(std::move(host_resolver));
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<TestNetworkDelegate>());
- auto context = context_builder->Build();
- TestDelegate d;
- std::unique_ptr<URLRequest> req(context->CreateRequest(
- http_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- EXPECT_FALSE(req->url().SchemeIsCryptographic());
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(d.received_redirect_count(), 0);
- EXPECT_EQ(0, network_delegate.error_count());
- EXPECT_EQ(200, req->GetResponseCode());
- ASSERT_TRUE(req->response_headers());
- EXPECT_EQ(200, req->response_headers()->response_code());
- // Observe that the scheme has not been upgraded.
- EXPECT_EQ(http_url, req->url());
- EXPECT_FALSE(req->url().SchemeIsCryptographic());
- EXPECT_TRUE(req->url().SchemeIs(url::kHttpScheme));
- }
- TEST_F(URLRequestTest, SkipSecureDnsDisabledByDefault) {
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto host_resolver = std::make_unique<MockHostResolver>();
- host_resolver->rules()->AddRule("example.com", "127.0.0.1");
- context_builder->set_host_resolver(std::move(host_resolver));
- auto context = context_builder->Build();
- TestDelegate d;
- std::unique_ptr<URLRequest> req(
- context->CreateRequest(GURL("http://example.com"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(SecureDnsPolicy::kAllow,
- static_cast<MockHostResolver*>(context->host_resolver())
- ->last_secure_dns_policy());
- }
- TEST_F(URLRequestTest, SkipSecureDnsEnabled) {
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto host_resolver = std::make_unique<MockHostResolver>();
- host_resolver->rules()->AddRule("example.com", "127.0.0.1");
- context_builder->set_host_resolver(std::move(host_resolver));
- auto context = context_builder->Build();
- TestDelegate d;
- std::unique_ptr<URLRequest> req(
- context->CreateRequest(GURL("http://example.com"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->SetSecureDnsPolicy(SecureDnsPolicy::kDisable);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(SecureDnsPolicy::kDisable,
- static_cast<MockHostResolver*>(context->host_resolver())
- ->last_secure_dns_policy());
- }
- // Make sure that NetworkDelegate::NotifyCompleted is called if
- // content is empty.
- TEST_F(URLRequestTest, RequestCompletionForEmptyResponse) {
- HttpTestServer test_server;
- ASSERT_TRUE(test_server.Start());
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- test_server.GetURL("/nocontent"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- EXPECT_THAT(d.request_status(), IsOk());
- EXPECT_EQ(204, req->GetResponseCode());
- EXPECT_EQ("", d.data_received());
- EXPECT_EQ(1, default_network_delegate().completed_requests());
- }
- // Make sure that SetPriority actually sets the URLRequest's priority
- // correctly, both before and after start.
- TEST_F(URLRequestTest, SetPriorityBasic) {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- GURL("http://test_intercept/foo"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- EXPECT_EQ(DEFAULT_PRIORITY, req->priority());
- req->SetPriority(LOW);
- EXPECT_EQ(LOW, req->priority());
- req->Start();
- EXPECT_EQ(LOW, req->priority());
- req->SetPriority(MEDIUM);
- EXPECT_EQ(MEDIUM, req->priority());
- }
- // Make sure that URLRequest calls SetPriority on a job before calling
- // Start on it.
- TEST_F(URLRequestTest, SetJobPriorityBeforeJobStart) {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- GURL("http://test_intercept/foo"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- EXPECT_EQ(DEFAULT_PRIORITY, req->priority());
- RequestPriority job_priority;
- std::unique_ptr<URLRequestJob> job =
- std::make_unique<PriorityMonitoringURLRequestJob>(req.get(),
- &job_priority);
- TestScopedURLInterceptor interceptor(req->url(), std::move(job));
- EXPECT_EQ(DEFAULT_PRIORITY, job_priority);
- req->SetPriority(LOW);
- req->Start();
- EXPECT_EQ(LOW, job_priority);
- }
- // Make sure that URLRequest passes on its priority updates to its
- // job.
- TEST_F(URLRequestTest, SetJobPriority) {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- GURL("http://test_intercept/foo"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- RequestPriority job_priority;
- std::unique_ptr<URLRequestJob> job =
- std::make_unique<PriorityMonitoringURLRequestJob>(req.get(),
- &job_priority);
- TestScopedURLInterceptor interceptor(req->url(), std::move(job));
- req->SetPriority(LOW);
- req->Start();
- EXPECT_EQ(LOW, job_priority);
- req->SetPriority(MEDIUM);
- EXPECT_EQ(MEDIUM, req->priority());
- EXPECT_EQ(MEDIUM, job_priority);
- }
- // Setting the IGNORE_LIMITS load flag should be okay if the priority
- // is MAXIMUM_PRIORITY.
- TEST_F(URLRequestTest, PriorityIgnoreLimits) {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- GURL("http://test_intercept/foo"), MAXIMUM_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- EXPECT_EQ(MAXIMUM_PRIORITY, req->priority());
- RequestPriority job_priority;
- std::unique_ptr<URLRequestJob> job =
- std::make_unique<PriorityMonitoringURLRequestJob>(req.get(),
- &job_priority);
- TestScopedURLInterceptor interceptor(req->url(), std::move(job));
- req->SetLoadFlags(LOAD_IGNORE_LIMITS);
- EXPECT_EQ(MAXIMUM_PRIORITY, req->priority());
- req->SetPriority(MAXIMUM_PRIORITY);
- EXPECT_EQ(MAXIMUM_PRIORITY, req->priority());
- req->Start();
- EXPECT_EQ(MAXIMUM_PRIORITY, req->priority());
- EXPECT_EQ(MAXIMUM_PRIORITY, job_priority);
- }
- // This test verifies that URLRequest::Delegate's OnConnected() callback is
- // never called if the request fails before connecting to a remote endpoint.
- TEST_F(URLRequestTest, NotifyDelegateConnectedSkippedOnEarlyFailure) {
- TestDelegate delegate;
- // The request will never connect to anything because the URL is invalid.
- auto request =
- default_context().CreateRequest(GURL("invalid url"), DEFAULT_PRIORITY,
- &delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
- request->Start();
- delegate.RunUntilComplete();
- EXPECT_THAT(delegate.transports(), IsEmpty());
- }
- // This test verifies that URLRequest::Delegate's OnConnected() method
- // is called once for simple redirect-less requests.
- TEST_F(URLRequestTest, OnConnected) {
- HttpTestServer test_server;
- ASSERT_TRUE(test_server.Start());
- TestDelegate delegate;
- auto request = default_context().CreateRequest(test_server.GetURL("/echo"),
- DEFAULT_PRIORITY, &delegate,
- TRAFFIC_ANNOTATION_FOR_TESTS);
- request->Start();
- delegate.RunUntilComplete();
- TransportInfo expected_transport;
- expected_transport.endpoint =
- IPEndPoint(IPAddress::IPv4Localhost(), test_server.port());
- EXPECT_THAT(delegate.transports(), ElementsAre(expected_transport));
- // Make sure URL_REQUEST_DELEGATE_CONNECTED is logged correctly.
- auto entries = net_log_observer_.GetEntries();
- size_t start_event_index = ExpectLogContainsSomewhere(
- entries, /*min_offset=*/0,
- NetLogEventType::URL_REQUEST_DELEGATE_CONNECTED, NetLogEventPhase::BEGIN);
- size_t end_event_index = ExpectLogContainsSomewhereAfter(
- entries, /*start_offset=*/start_event_index,
- NetLogEventType::URL_REQUEST_DELEGATE_CONNECTED, NetLogEventPhase::END);
- EXPECT_FALSE(LogContainsEntryWithTypeAfter(
- entries, end_event_index + 1,
- NetLogEventType::URL_REQUEST_DELEGATE_CONNECTED));
- ASSERT_LT(end_event_index, entries.size());
- EXPECT_FALSE(GetOptionalNetErrorCodeFromParams(entries[end_event_index]));
- }
- // This test verifies that URLRequest::Delegate's OnConnected() method is
- // called after each redirect.
- TEST_F(URLRequestTest, OnConnectedRedirect) {
- HttpTestServer test_server;
- ASSERT_TRUE(test_server.Start());
- TestDelegate delegate;
- // Fetch a page that redirects us once.
- GURL url = test_server.GetURL("/server-redirect?" +
- test_server.GetURL("/echo").spec());
- auto request = default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
- request->Start();
- delegate.RunUntilRedirect();
- TransportInfo expected_transport;
- expected_transport.endpoint =
- IPEndPoint(IPAddress::IPv4Localhost(), test_server.port());
- EXPECT_THAT(delegate.transports(), ElementsAre(expected_transport));
- request->FollowDeferredRedirect(/*removed_headers=*/{},
- /*modified_headers=*/{});
- delegate.RunUntilComplete();
- EXPECT_THAT(delegate.transports(),
- ElementsAre(expected_transport, expected_transport));
- }
- // This test verifies that when the URLRequest Delegate returns an error from
- // OnConnected(), the entire request fails with that error.
- TEST_F(URLRequestTest, OnConnectedError) {
- HttpTestServer test_server;
- ASSERT_TRUE(test_server.Start());
- TestDelegate delegate;
- delegate.set_on_connected_result(ERR_NOT_IMPLEMENTED);
- auto request = default_context().CreateRequest(test_server.GetURL("/echo"),
- DEFAULT_PRIORITY, &delegate,
- TRAFFIC_ANNOTATION_FOR_TESTS);
- request->Start();
- delegate.RunUntilComplete();
- TransportInfo expected_transport;
- expected_transport.endpoint =
- IPEndPoint(IPAddress::IPv4Localhost(), test_server.port());
- EXPECT_THAT(delegate.transports(), ElementsAre(expected_transport));
- EXPECT_TRUE(delegate.request_failed());
- EXPECT_THAT(delegate.request_status(), IsError(ERR_NOT_IMPLEMENTED));
- // Make sure URL_REQUEST_DELEGATE_CONNECTED is logged correctly.
- auto entries = net_log_observer_.GetEntries();
- size_t start_event_index = ExpectLogContainsSomewhere(
- entries, /*min_offset=*/0,
- NetLogEventType::URL_REQUEST_DELEGATE_CONNECTED, NetLogEventPhase::BEGIN);
- size_t end_event_index = ExpectLogContainsSomewhereAfter(
- entries, /*start_offset=*/start_event_index,
- NetLogEventType::URL_REQUEST_DELEGATE_CONNECTED, NetLogEventPhase::END);
- EXPECT_FALSE(LogContainsEntryWithTypeAfter(
- entries, end_event_index + 1,
- NetLogEventType::URL_REQUEST_DELEGATE_CONNECTED));
- ASSERT_LT(end_event_index, entries.size());
- EXPECT_EQ(ERR_NOT_IMPLEMENTED,
- GetOptionalNetErrorCodeFromParams(entries[end_event_index]));
- }
- TEST_F(URLRequestTest, OnConnectedAsync) {
- HttpTestServer test_server;
- ASSERT_TRUE(test_server.Start());
- TestDelegate d;
- d.set_on_connected_run_callback(true);
- d.set_on_connected_result(OK);
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(), test_server.GetURL("/defaultresponse"), &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_THAT(d.request_status(), IsOk());
- // Make sure URL_REQUEST_DELEGATE_CONNECTED is logged correctly.
- auto entries = net_log_observer_.GetEntries();
- size_t start_event_index = ExpectLogContainsSomewhere(
- entries, /*min_offset=*/0,
- NetLogEventType::URL_REQUEST_DELEGATE_CONNECTED, NetLogEventPhase::BEGIN);
- size_t end_event_index = ExpectLogContainsSomewhereAfter(
- entries, /*start_offset=*/start_event_index,
- NetLogEventType::URL_REQUEST_DELEGATE_CONNECTED, NetLogEventPhase::END);
- EXPECT_FALSE(LogContainsEntryWithTypeAfter(
- entries, end_event_index + 1,
- NetLogEventType::URL_REQUEST_DELEGATE_CONNECTED));
- ASSERT_LT(end_event_index, entries.size());
- EXPECT_FALSE(GetOptionalNetErrorCodeFromParams(entries[end_event_index]));
- }
- TEST_F(URLRequestTest, OnConnectedAsyncError) {
- HttpTestServer test_server;
- ASSERT_TRUE(test_server.Start());
- TestDelegate d;
- d.set_on_connected_run_callback(true);
- d.set_on_connected_result(ERR_NOT_IMPLEMENTED);
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(), test_server.GetURL("/defaultresponse"), &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_THAT(d.request_status(), IsError(ERR_NOT_IMPLEMENTED));
- // Make sure URL_REQUEST_DELEGATE_CONNECTED is logged correctly.
- auto entries = net_log_observer_.GetEntries();
- size_t start_event_index = ExpectLogContainsSomewhere(
- entries, /*min_offset=*/0,
- NetLogEventType::URL_REQUEST_DELEGATE_CONNECTED, NetLogEventPhase::BEGIN);
- size_t end_event_index = ExpectLogContainsSomewhereAfter(
- entries, /*start_offset=*/start_event_index,
- NetLogEventType::URL_REQUEST_DELEGATE_CONNECTED, NetLogEventPhase::END);
- EXPECT_FALSE(LogContainsEntryWithTypeAfter(
- entries, end_event_index + 1,
- NetLogEventType::URL_REQUEST_DELEGATE_CONNECTED));
- ASSERT_LT(end_event_index, entries.size());
- EXPECT_EQ(ERR_NOT_IMPLEMENTED,
- GetOptionalNetErrorCodeFromParams(entries[end_event_index]));
- }
- TEST_F(URLRequestTest, DelayedCookieCallback) {
- HttpTestServer test_server;
- ASSERT_TRUE(test_server.Start());
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->SetCookieStore(std::make_unique<DelayedCookieMonster>());
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<TestNetworkDelegate>());
- auto context = context_builder->Build();
- // Set up a cookie.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- *context, test_server.GetURL("/set-cookie?CookieToNotSend=1"), &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
- EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
- EXPECT_EQ(1, network_delegate.set_cookie_count());
- }
- // Verify that the cookie is set.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- *context, test_server.GetURL("/echoheader?Cookie"), &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_TRUE(d.data_received().find("CookieToNotSend=1") !=
- std::string::npos);
- EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
- EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
- }
- }
- TEST_F(URLRequestTest, DelayedCookieCallbackAsync) {
- HttpTestServer test_server;
- ASSERT_TRUE(test_server.Start());
- // Add a secure cookie so we can try to set an insecure cookie and have
- // SetCanonicalCookie fail.
- GURL::Replacements replace_scheme;
- replace_scheme.SetSchemeStr("https");
- GURL url = test_server.base_url().ReplaceComponents(replace_scheme);
- auto cookie1 = CanonicalCookie::Create(
- url, "AlreadySetCookie=1;Secure", base::Time::Now(),
- absl::nullopt /* server_time */,
- absl::nullopt /* cookie_partition_key */);
- auto delayed_cm = std::make_unique<DelayedCookieMonster>();
- delayed_cm->SetCanonicalCookieAsync(std::move(cookie1), url,
- net::CookieOptions::MakeAllInclusive(),
- CookieStore::SetCookiesCallback());
- auto cookie2 = CanonicalCookie::Create(
- url, "AlreadySetCookie=1;Secure", base::Time::Now(),
- absl::nullopt /* server_time */,
- absl::nullopt /* cookie_partition_key */);
- auto cm = std::make_unique<CookieMonster>(nullptr, nullptr,
- /*first_party_sets_enabled=*/false);
- cm->SetCanonicalCookieAsync(std::move(cookie2), url,
- net::CookieOptions::MakeAllInclusive(),
- CookieStore::SetCookiesCallback());
- auto async_context_builder = CreateTestURLRequestContextBuilder();
- async_context_builder->SetCookieStore(std::move(delayed_cm));
- auto& async_filter_network_delegate =
- *async_context_builder->set_network_delegate(
- std::make_unique<FilteringTestNetworkDelegate>());
- auto async_context = async_context_builder->Build();
- async_filter_network_delegate.SetCookieFilter("CookieBlockedOnCanGetCookie");
- TestDelegate async_delegate;
- auto sync_context_builder = CreateTestURLRequestContextBuilder();
- sync_context_builder->SetCookieStore(std::move(cm));
- auto& sync_filter_network_delegate =
- *sync_context_builder->set_network_delegate(
- std::make_unique<FilteringTestNetworkDelegate>());
- auto sync_context = sync_context_builder->Build();
- sync_filter_network_delegate.SetCookieFilter("CookieBlockedOnCanGetCookie");
- TestDelegate sync_delegate;
- std::vector<std::string> cookie_lines(
- {// Fails in SetCanonicalCookie for trying to set a secure cookie
- // on an insecure host.
- "CookieNotSet=1;Secure",
- // Fail in FilteringTestNetworkDelegate::CanGetCookie.
- "CookieBlockedOnCanGetCookie=1",
- // Fails in SetCanonicalCookie for trying to overwrite a secure cookie
- // with an insecure cookie.
- "AlreadySetCookie=1",
- // Succeeds and added cookie to store. Delayed (which makes the callback
- // run asynchronously) in DelayedCookieMonster.
- "CookieSet=1"});
- for (auto first_cookie_line : cookie_lines) {
- for (auto second_cookie_line : cookie_lines) {
- // Run with the delayed cookie monster.
- std::unique_ptr<URLRequest> request = CreateFirstPartyRequest(
- *async_context,
- test_server.GetURL("/set-cookie?" + first_cookie_line + "&" +
- second_cookie_line),
- &async_delegate);
- request->Start();
- async_delegate.RunUntilComplete();
- EXPECT_THAT(async_delegate.request_status(), IsOk());
- // Run with the regular cookie monster.
- request = CreateFirstPartyRequest(
- *sync_context,
- test_server.GetURL("/set-cookie?" + first_cookie_line + "&" +
- second_cookie_line),
- &sync_delegate);
- request->Start();
- sync_delegate.RunUntilComplete();
- EXPECT_THAT(sync_delegate.request_status(), IsOk());
- int expected_set_cookie_count = 0;
- int expected_blocked_cookie_count = 0;
- // 2 calls to the delegate's OnCanSetCookie method are expected, even if
- // the cookies don't end up getting set.
- expected_set_cookie_count += 2;
- if (first_cookie_line == "CookieBlockedOnCanGetCookie=1")
- ++expected_blocked_cookie_count;
- if (second_cookie_line == "CookieBlockedOnCanGetCookie=1")
- ++expected_blocked_cookie_count;
- EXPECT_EQ(expected_set_cookie_count,
- async_filter_network_delegate.set_cookie_called_count());
- EXPECT_EQ(expected_blocked_cookie_count,
- async_filter_network_delegate.blocked_set_cookie_count());
- EXPECT_EQ(expected_set_cookie_count,
- sync_filter_network_delegate.set_cookie_called_count());
- EXPECT_EQ(expected_blocked_cookie_count,
- sync_filter_network_delegate.blocked_set_cookie_count());
- async_filter_network_delegate.ResetSetCookieCalledCount();
- async_filter_network_delegate.ResetBlockedSetCookieCount();
- sync_filter_network_delegate.ResetSetCookieCalledCount();
- sync_filter_network_delegate.ResetBlockedSetCookieCount();
- }
- }
- }
- TEST_F(URLRequestTest, DoNotSendCookies) {
- HttpTestServer test_server;
- ASSERT_TRUE(test_server.Start());
- // Set up a cookie.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(), test_server.GetURL("/set-cookie?CookieToNotSend=1"),
- &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- }
- // Verify that the cookie is set.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(), test_server.GetURL("/echoheader?Cookie"), &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_TRUE(d.data_received().find("CookieToNotSend=1") !=
- std::string::npos);
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- }
- // Verify that the cookie isn't sent when credentials are not allowed.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(), test_server.GetURL("/echoheader?Cookie"), &d);
- req->set_allow_credentials(false);
- req->Start();
- d.RunUntilComplete();
- EXPECT_TRUE(d.data_received().find("Cookie: CookieToNotSend=1") ==
- std::string::npos);
- // When credentials are blocked, OnAnnotateAndMoveUserBlockedCookies() is
- // not invoked.
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- }
- }
- TEST_F(URLRequestTest, DoNotSaveCookies) {
- HttpTestServer test_server;
- ASSERT_TRUE(test_server.Start());
- // Set up a cookie.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(),
- test_server.GetURL("/set-cookie?CookieToNotUpdate=2"), &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- EXPECT_EQ(1, default_network_delegate().set_cookie_count());
- }
- // Try to set-up another cookie and update the previous cookie.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(),
- test_server.GetURL("/set-cookie?CookieToNotSave=1&CookieToNotUpdate=1"),
- &d);
- req->SetLoadFlags(LOAD_DO_NOT_SAVE_COOKIES);
- req->Start();
- d.RunUntilComplete();
- // LOAD_DO_NOT_SAVE_COOKIES does not trigger OnSetCookie.
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- EXPECT_EQ(1, default_network_delegate().set_cookie_count());
- }
- // Verify the cookies weren't saved or updated.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(), test_server.GetURL("/echoheader?Cookie"), &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_TRUE(d.data_received().find("CookieToNotSave=1") ==
- std::string::npos);
- EXPECT_TRUE(d.data_received().find("CookieToNotUpdate=2") !=
- std::string::npos);
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- EXPECT_EQ(1, default_network_delegate().set_cookie_count());
- }
- }
- TEST_F(URLRequestTest, DoNotSendCookies_ViaPolicy) {
- HttpTestServer test_server;
- ASSERT_TRUE(test_server.Start());
- // Set up a cookie.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(), test_server.GetURL("/set-cookie?CookieToNotSend=1"),
- &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- }
- // Verify that the cookie is set.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(), test_server.GetURL("/echoheader?Cookie"), &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_TRUE(d.data_received().find("CookieToNotSend=1") !=
- std::string::npos);
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- auto entries = net_log_observer_.GetEntries();
- for (const auto& entry : entries) {
- EXPECT_NE(entry.type,
- NetLogEventType::COOKIE_GET_BLOCKED_BY_NETWORK_DELEGATE);
- }
- }
- // Verify that the cookie isn't sent.
- {
- TestDelegate d;
- default_network_delegate().set_cookie_options(
- TestNetworkDelegate::NO_GET_COOKIES);
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(), test_server.GetURL("/echoheader?Cookie"), &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_TRUE(d.data_received().find("Cookie: CookieToNotSend=1") ==
- std::string::npos);
- EXPECT_EQ(1, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- auto entries = net_log_observer_.GetEntries();
- ExpectLogContainsSomewhereAfter(
- entries, 0, NetLogEventType::COOKIE_GET_BLOCKED_BY_NETWORK_DELEGATE,
- NetLogEventPhase::NONE);
- }
- }
- // TODO(crbug.com/564656) This test is flaky on iOS.
- #if BUILDFLAG(IS_IOS)
- #define MAYBE_DoNotSaveCookies_ViaPolicy FLAKY_DoNotSaveCookies_ViaPolicy
- #else
- #define MAYBE_DoNotSaveCookies_ViaPolicy DoNotSaveCookies_ViaPolicy
- #endif
- TEST_F(URLRequestTest, MAYBE_DoNotSaveCookies_ViaPolicy) {
- HttpTestServer test_server;
- ASSERT_TRUE(test_server.Start());
- // Set up a cookie.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(),
- test_server.GetURL("/set-cookie?CookieToNotUpdate=2"), &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- auto entries = net_log_observer_.GetEntries();
- for (const auto& entry : entries) {
- EXPECT_NE(entry.type,
- NetLogEventType::COOKIE_SET_BLOCKED_BY_NETWORK_DELEGATE);
- }
- }
- // Try to set-up another cookie and update the previous cookie.
- {
- TestDelegate d;
- default_network_delegate().set_cookie_options(
- TestNetworkDelegate::NO_SET_COOKIE);
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(),
- test_server.GetURL("/set-cookie?CookieToNotSave=1&CookieToNotUpdate=1"),
- &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(2, default_network_delegate().blocked_set_cookie_count());
- auto entries = net_log_observer_.GetEntries();
- ExpectLogContainsSomewhereAfter(
- entries, 0, NetLogEventType::COOKIE_SET_BLOCKED_BY_NETWORK_DELEGATE,
- NetLogEventPhase::NONE);
- }
- // Verify the cookies weren't saved or updated.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(), test_server.GetURL("/echoheader?Cookie"), &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_TRUE(d.data_received().find("CookieToNotSave=1") ==
- std::string::npos);
- EXPECT_TRUE(d.data_received().find("CookieToNotUpdate=2") !=
- std::string::npos);
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(2, default_network_delegate().blocked_set_cookie_count());
- }
- }
- TEST_F(URLRequestTest, DoNotSaveEmptyCookies) {
- HttpTestServer test_server;
- ASSERT_TRUE(test_server.Start());
- // Set up an empty cookie.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(), test_server.GetURL("/set-cookie"), &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- EXPECT_EQ(0, default_network_delegate().set_cookie_count());
- }
- }
- TEST_F(URLRequestTest, DoNotSendCookies_ViaPolicy_Async) {
- HttpTestServer test_server;
- ASSERT_TRUE(test_server.Start());
- // Set up a cookie.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(), test_server.GetURL("/set-cookie?CookieToNotSend=1"),
- &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- }
- // Verify that the cookie is set.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(), test_server.GetURL("/echoheader?Cookie"), &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_TRUE(d.data_received().find("CookieToNotSend=1") !=
- std::string::npos);
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- }
- // Verify that the cookie isn't sent.
- {
- TestDelegate d;
- default_network_delegate().set_cookie_options(
- TestNetworkDelegate::NO_GET_COOKIES);
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(), test_server.GetURL("/echoheader?Cookie"), &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_TRUE(d.data_received().find("Cookie: CookieToNotSend=1") ==
- std::string::npos);
- EXPECT_EQ(1, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- }
- }
- TEST_F(URLRequestTest, DoNotSaveCookies_ViaPolicy_Async) {
- HttpTestServer test_server;
- ASSERT_TRUE(test_server.Start());
- // Set up a cookie.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(),
- test_server.GetURL("/set-cookie?CookieToNotUpdate=2"), &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- }
- // Try to set-up another cookie and update the previous cookie.
- {
- TestDelegate d;
- default_network_delegate().set_cookie_options(
- TestNetworkDelegate::NO_SET_COOKIE);
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(),
- test_server.GetURL("/set-cookie?CookieToNotSave=1&CookieToNotUpdate=1"),
- &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(2, default_network_delegate().blocked_set_cookie_count());
- }
- // Verify the cookies weren't saved or updated.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(), test_server.GetURL("/echoheader?Cookie"), &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_TRUE(d.data_received().find("CookieToNotSave=1") ==
- std::string::npos);
- EXPECT_TRUE(d.data_received().find("CookieToNotUpdate=2") !=
- std::string::npos);
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(2, default_network_delegate().blocked_set_cookie_count());
- }
- }
- // Tests for SameSite cookies. The test param indicates whether the same-site
- // calculation considers redirect chains.
- class URLRequestSameSiteCookiesTest
- : public URLRequestTest,
- public ::testing::WithParamInterface<bool> {
- public:
- URLRequestSameSiteCookiesTest() {
- if (DoesCookieSameSiteConsiderRedirectChain()) {
- feature_list_.InitAndEnableFeature(
- features::kCookieSameSiteConsidersRedirectChain);
- }
- }
- bool DoesCookieSameSiteConsiderRedirectChain() { return GetParam(); }
- private:
- base::test::ScopedFeatureList feature_list_;
- };
- TEST_P(URLRequestSameSiteCookiesTest, SameSiteCookies) {
- HttpTestServer test_server;
- ASSERT_TRUE(test_server.Start());
- const std::string kHost = "example.test";
- const std::string kSubHost = "subdomain.example.test";
- const std::string kCrossHost = "cross-origin.test";
- const url::Origin kOrigin =
- url::Origin::Create(test_server.GetURL(kHost, "/"));
- const url::Origin kSubOrigin =
- url::Origin::Create(test_server.GetURL(kSubHost, "/"));
- const url::Origin kCrossOrigin =
- url::Origin::Create(test_server.GetURL(kCrossHost, "/"));
- const SiteForCookies kSiteForCookies = SiteForCookies::FromOrigin(kOrigin);
- const SiteForCookies kCrossSiteForCookies =
- SiteForCookies::FromOrigin(kCrossOrigin);
- // Set up two 'SameSite' cookies on 'example.test'
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(),
- test_server.GetURL(kHost,
- "/set-cookie?StrictSameSiteCookie=1;SameSite=Strict&"
- "LaxSameSiteCookie=1;SameSite=Lax"),
- &d);
- req->set_site_for_cookies(kSiteForCookies);
- req->set_initiator(kOrigin);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- EXPECT_EQ(2, default_network_delegate().set_cookie_count());
- }
- // Verify that both cookies are sent for same-site requests, whether they are
- // subresource requests, subframe navigations, or main frame navigations.
- for (IsolationInfo::RequestType request_type :
- {IsolationInfo::RequestType::kMainFrame,
- IsolationInfo::RequestType::kSubFrame,
- IsolationInfo::RequestType::kOther}) {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- test_server.GetURL(kHost, "/echoheader?Cookie"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(IsolationInfo::Create(request_type, kOrigin,
- kOrigin, kSiteForCookies,
- {} /* party_context */));
- req->set_site_for_cookies(kSiteForCookies);
- req->set_initiator(kOrigin);
- req->Start();
- d.RunUntilComplete();
- EXPECT_NE(std::string::npos,
- d.data_received().find("StrictSameSiteCookie=1"));
- EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- }
- // Verify that both cookies are sent when the request has no initiator (can
- // happen for main frame browser-initiated navigations).
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- test_server.GetURL(kHost, "/echoheader?Cookie"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_site_for_cookies(kSiteForCookies);
- req->Start();
- d.RunUntilComplete();
- EXPECT_NE(std::string::npos,
- d.data_received().find("StrictSameSiteCookie=1"));
- EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- }
- // Verify that both cookies are sent for same-registrable-domain requests.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- test_server.GetURL(kHost, "/echoheader?Cookie"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_site_for_cookies(
- SiteForCookies::FromUrl(test_server.GetURL(kSubHost, "/")));
- req->set_initiator(kSubOrigin);
- req->Start();
- d.RunUntilComplete();
- EXPECT_NE(std::string::npos,
- d.data_received().find("StrictSameSiteCookie=1"));
- EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- }
- // Verify that neither cookie is not sent for cross-site requests.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- test_server.GetURL(kHost, "/echoheader?Cookie"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_site_for_cookies(kCrossSiteForCookies);
- req->set_initiator(kCrossOrigin);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(std::string::npos,
- d.data_received().find("StrictSameSiteCookie=1"));
- EXPECT_EQ(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- }
- // Verify that the lax cookie is sent for cross-site initiators when the
- // method is "safe" and the request is a main frame navigation.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- test_server.GetURL(kHost, "/echoheader?Cookie"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(IsolationInfo::Create(
- IsolationInfo::RequestType::kMainFrame, kOrigin, kOrigin,
- kSiteForCookies, {} /* party_context */));
- req->set_site_for_cookies(kSiteForCookies);
- req->set_initiator(kCrossOrigin);
- req->set_method("GET");
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(std::string::npos,
- d.data_received().find("StrictSameSiteCookie=1"));
- EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- }
- // Verify that the lax cookie is sent for cross-site initiators when the
- // method is "safe" and the request is being forced to be considered as a
- // main frame navigation.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- test_server.GetURL(kHost, "/echoheader?Cookie"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(IsolationInfo::Create(
- IsolationInfo::RequestType::kOther, kOrigin, kOrigin, kSiteForCookies,
- {} /* party_context */));
- req->set_site_for_cookies(kSiteForCookies);
- req->set_initiator(kCrossOrigin);
- req->set_method("GET");
- req->set_force_main_frame_for_same_site_cookies(true);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(std::string::npos,
- d.data_received().find("StrictSameSiteCookie=1"));
- EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- }
- // Verify that neither cookie is sent for cross-site initiators when the
- // method is unsafe (e.g. POST), even if the request is a main frame
- // navigation.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- test_server.GetURL(kHost, "/echoheader?Cookie"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(IsolationInfo::Create(
- IsolationInfo::RequestType::kMainFrame, kOrigin, kOrigin,
- kSiteForCookies, {} /* party_context */));
- req->set_site_for_cookies(kSiteForCookies);
- req->set_initiator(kCrossOrigin);
- req->set_method("POST");
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(std::string::npos,
- d.data_received().find("StrictSameSiteCookie=1"));
- EXPECT_EQ(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- }
- // Verify that neither cookie is sent for cross-site initiators when the
- // method is safe and the site-for-cookies is same-site, but the request is
- // not a main frame navigation.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- test_server.GetURL(kHost, "/echoheader?Cookie"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(IsolationInfo::Create(
- IsolationInfo::RequestType::kSubFrame, kOrigin, kOrigin,
- kSiteForCookies, {} /* party_context */));
- req->set_site_for_cookies(kSiteForCookies);
- req->set_initiator(kCrossOrigin);
- req->set_method("GET");
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(std::string::npos,
- d.data_received().find("StrictSameSiteCookie=1"));
- EXPECT_EQ(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- // Check that the appropriate cookie inclusion status is set.
- ASSERT_EQ(2u, req->maybe_sent_cookies().size());
- CookieInclusionStatus expected_strict_status =
- CookieInclusionStatus::MakeFromReasonsForTesting(
- {CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT},
- {} /* warning_reasons */);
- CookieInclusionStatus expected_lax_status =
- CookieInclusionStatus::MakeFromReasonsForTesting(
- {CookieInclusionStatus::EXCLUDE_SAMESITE_LAX},
- {} /* warning_reasons */);
- EXPECT_EQ(expected_strict_status,
- req->maybe_sent_cookies()[0].access_result.status);
- EXPECT_EQ(expected_lax_status,
- req->maybe_sent_cookies()[1].access_result.status);
- }
- }
- TEST_P(URLRequestSameSiteCookiesTest, SameSiteCookies_Redirect) {
- EmbeddedTestServer http_server;
- RegisterDefaultHandlers(&http_server);
- EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS);
- https_server.SetSSLConfig(EmbeddedTestServer::CERT_TEST_NAMES);
- RegisterDefaultHandlers(&https_server);
- ASSERT_TRUE(http_server.Start());
- ASSERT_TRUE(https_server.Start());
- const std::string kHost = "foo.a.test";
- const std::string kSameSiteHost = "bar.a.test";
- const std::string kCrossSiteHost = "b.test";
- const url::Origin kOrigin =
- url::Origin::Create(https_server.GetURL(kHost, "/"));
- const url::Origin kHttpOrigin =
- url::Origin::Create(http_server.GetURL(kHost, "/"));
- const url::Origin kSameSiteOrigin =
- url::Origin::Create(https_server.GetURL(kSameSiteHost, "/"));
- const url::Origin kCrossSiteOrigin =
- url::Origin::Create(https_server.GetURL(kCrossSiteHost, "/"));
- const SiteForCookies kSiteForCookies = SiteForCookies::FromOrigin(kOrigin);
- const SiteForCookies kHttpSiteForCookies =
- SiteForCookies::FromOrigin(kHttpOrigin);
- const SiteForCookies kCrossSiteForCookies =
- SiteForCookies::FromOrigin(kCrossSiteOrigin);
- // Set up two 'SameSite' cookies on foo.a.test
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(),
- https_server.GetURL(
- kHost,
- "/set-cookie?StrictSameSiteCookie=1;SameSite=Strict&"
- "LaxSameSiteCookie=1;SameSite=Lax"),
- &d);
- req->set_site_for_cookies(kSiteForCookies);
- req->set_initiator(kOrigin);
- req->Start();
- d.RunUntilComplete();
- ASSERT_EQ(2u, GetAllCookies(&default_context()).size());
- }
- // Verify that both cookies are sent for same-site, unredirected requests.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- https_server.GetURL(kHost, "/echoheader?Cookie"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_site_for_cookies(kSiteForCookies);
- req->set_initiator(kOrigin);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(1u, req->url_chain().size());
- EXPECT_NE(std::string::npos,
- d.data_received().find("StrictSameSiteCookie=1"));
- EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
- }
- // Verify that both cookies are sent for a same-origin redirected top level
- // navigation.
- {
- TestDelegate d;
- GURL url = https_server.GetURL(
- kHost, "/server-redirect?" +
- https_server.GetURL(kHost, "/echoheader?Cookie").spec());
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(IsolationInfo::Create(
- IsolationInfo::RequestType::kMainFrame, kOrigin, kOrigin,
- kSiteForCookies, {} /* party_context */));
- req->set_first_party_url_policy(
- RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT);
- req->set_site_for_cookies(kSiteForCookies);
- req->set_initiator(kOrigin);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(2u, req->url_chain().size());
- EXPECT_NE(std::string::npos,
- d.data_received().find("StrictSameSiteCookie=1"));
- EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
- }
- // Verify that both cookies are sent for a same-site redirected top level
- // navigation.
- {
- TestDelegate d;
- GURL url = https_server.GetURL(
- kSameSiteHost,
- "/server-redirect?" +
- https_server.GetURL(kHost, "/echoheader?Cookie").spec());
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(IsolationInfo::Create(
- IsolationInfo::RequestType::kMainFrame, kSameSiteOrigin,
- kSameSiteOrigin, kSiteForCookies, {} /* party_context */));
- req->set_first_party_url_policy(
- RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT);
- req->set_site_for_cookies(kSiteForCookies);
- req->set_initiator(kOrigin);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(2u, req->url_chain().size());
- EXPECT_NE(std::string::npos,
- d.data_received().find("StrictSameSiteCookie=1"));
- EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
- }
- // If redirect chains are considered:
- // Verify that the Strict cookie may or may not be sent for a cross-scheme
- // (same-registrable-domain) redirected top level navigation, depending on the
- // status of Schemeful Same-Site. The Lax cookie is sent regardless, because
- // this is a top-level navigation.
- //
- // If redirect chains are not considered:
- // Verify that both cookies are sent, because this is a top-level navigation.
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndDisableFeature(features::kSchemefulSameSite);
- TestDelegate d;
- GURL url = http_server.GetURL(
- kHost, "/server-redirect?" +
- https_server.GetURL(kHost, "/echoheader?Cookie").spec());
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(IsolationInfo::Create(
- IsolationInfo::RequestType::kMainFrame, kHttpOrigin, kHttpOrigin,
- kHttpSiteForCookies, {} /* party_context */));
- req->set_first_party_url_policy(
- RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT);
- req->set_site_for_cookies(kHttpSiteForCookies);
- req->set_initiator(kOrigin);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(2u, req->url_chain().size());
- EXPECT_NE(std::string::npos,
- d.data_received().find("StrictSameSiteCookie=1"));
- EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
- }
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(features::kSchemefulSameSite);
- TestDelegate d;
- GURL url = http_server.GetURL(
- kHost, "/server-redirect?" +
- https_server.GetURL(kHost, "/echoheader?Cookie").spec());
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(IsolationInfo::Create(
- IsolationInfo::RequestType::kMainFrame, kHttpOrigin, kHttpOrigin,
- kHttpSiteForCookies, {} /* party_context */));
- req->set_first_party_url_policy(
- RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT);
- req->set_site_for_cookies(kHttpSiteForCookies);
- req->set_initiator(kOrigin);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(2u, req->url_chain().size());
- EXPECT_EQ(
- DoesCookieSameSiteConsiderRedirectChain(),
- std::string::npos == d.data_received().find("StrictSameSiteCookie=1"));
- EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
- }
- // Verify that (depending on whether redirect chains are considered), the
- // Strict cookie is (not) sent for a cross-site redirected top level
- // navigation...
- {
- TestDelegate d;
- GURL url = https_server.GetURL(
- kCrossSiteHost,
- "/server-redirect?" +
- https_server.GetURL(kHost, "/echoheader?Cookie").spec());
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(IsolationInfo::Create(
- IsolationInfo::RequestType::kMainFrame, kCrossSiteOrigin,
- kCrossSiteOrigin, kCrossSiteForCookies, {} /* party_context */));
- req->set_first_party_url_policy(
- RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT);
- req->set_site_for_cookies(kCrossSiteForCookies);
- req->set_initiator(kOrigin);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(2u, req->url_chain().size());
- EXPECT_EQ(
- DoesCookieSameSiteConsiderRedirectChain(),
- std::string::npos == d.data_received().find("StrictSameSiteCookie=1"));
- EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
- }
- // ... even if the initial URL is same-site.
- {
- TestDelegate d;
- GURL middle_url = https_server.GetURL(
- kCrossSiteHost,
- "/server-redirect?" +
- https_server.GetURL(kHost, "/echoheader?Cookie").spec());
- GURL url =
- https_server.GetURL(kHost, "/server-redirect?" + middle_url.spec());
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(IsolationInfo::Create(
- IsolationInfo::RequestType::kMainFrame, kOrigin, kOrigin,
- kSiteForCookies, {} /* party_context */));
- req->set_first_party_url_policy(
- RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT);
- req->set_site_for_cookies(kSiteForCookies);
- req->set_initiator(kOrigin);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(3u, req->url_chain().size());
- EXPECT_EQ(
- DoesCookieSameSiteConsiderRedirectChain(),
- std::string::npos == d.data_received().find("StrictSameSiteCookie=1"));
- EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
- }
- // Verify that (depending on whether redirect chains are considered), neither
- // (or both) SameSite cookie is sent for a cross-site redirected subresource
- // request...
- {
- TestDelegate d;
- GURL url = https_server.GetURL(
- kCrossSiteHost,
- "/server-redirect?" +
- https_server.GetURL(kHost, "/echoheader?Cookie").spec());
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(IsolationInfo::Create(
- IsolationInfo::RequestType::kOther, kOrigin, kOrigin, kSiteForCookies,
- {} /* party_context */));
- req->set_site_for_cookies(kSiteForCookies);
- req->set_initiator(kOrigin);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(2u, req->url_chain().size());
- EXPECT_EQ(
- DoesCookieSameSiteConsiderRedirectChain(),
- std::string::npos == d.data_received().find("StrictSameSiteCookie=1"));
- EXPECT_EQ(
- DoesCookieSameSiteConsiderRedirectChain(),
- std::string::npos == d.data_received().find("LaxSameSiteCookie=1"));
- }
- // ... even if the initial URL is same-site.
- {
- TestDelegate d;
- GURL middle_url = https_server.GetURL(
- kCrossSiteHost,
- "/server-redirect?" +
- https_server.GetURL(kHost, "/echoheader?Cookie").spec());
- GURL url =
- https_server.GetURL(kHost, "/server-redirect?" + middle_url.spec());
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(IsolationInfo::Create(
- IsolationInfo::RequestType::kOther, kOrigin, kOrigin, kSiteForCookies,
- {} /* party_context */));
- req->set_site_for_cookies(kSiteForCookies);
- req->set_initiator(kOrigin);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(3u, req->url_chain().size());
- EXPECT_EQ(
- DoesCookieSameSiteConsiderRedirectChain(),
- std::string::npos == d.data_received().find("StrictSameSiteCookie=1"));
- EXPECT_EQ(
- DoesCookieSameSiteConsiderRedirectChain(),
- std::string::npos == d.data_received().find("LaxSameSiteCookie=1"));
- }
- }
- TEST_P(URLRequestSameSiteCookiesTest, SettingSameSiteCookies) {
- HttpTestServer test_server;
- ASSERT_TRUE(test_server.Start());
- const std::string kHost = "example.test";
- const std::string kSubHost = "subdomain.example.test";
- const std::string kCrossHost = "cross-origin.test";
- const url::Origin kOrigin =
- url::Origin::Create(test_server.GetURL(kHost, "/"));
- const url::Origin kSubOrigin =
- url::Origin::Create(test_server.GetURL(kSubHost, "/"));
- const url::Origin kCrossOrigin =
- url::Origin::Create(test_server.GetURL(kCrossHost, "/"));
- const SiteForCookies kSiteForCookies = SiteForCookies::FromOrigin(kOrigin);
- const SiteForCookies kCrossSiteForCookies =
- SiteForCookies::FromOrigin(kCrossOrigin);
- int expected_cookies = 0;
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- test_server.GetURL(kHost,
- "/set-cookie?Strict1=1;SameSite=Strict&"
- "Lax1=1;SameSite=Lax"),
- DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_site_for_cookies(kSiteForCookies);
- req->set_initiator(kOrigin);
- // 'SameSite' cookies are settable from strict same-site contexts
- // (same-origin site_for_cookies, same-origin initiator), so this request
- // should result in two cookies being set.
- expected_cookies += 2;
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(expected_cookies,
- static_cast<int>(GetAllCookies(&default_context()).size()));
- EXPECT_EQ(expected_cookies, default_network_delegate().set_cookie_count());
- }
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- test_server.GetURL(kHost,
- "/set-cookie?Strict2=1;SameSite=Strict&"
- "Lax2=1;SameSite=Lax"),
- DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(IsolationInfo::Create(
- IsolationInfo::RequestType::kMainFrame, kOrigin, kOrigin,
- kSiteForCookies, {} /* party_context */));
- req->set_site_for_cookies(kSiteForCookies);
- req->set_initiator(kCrossOrigin);
- // 'SameSite' cookies are settable from lax same-site contexts (same-origin
- // site_for_cookies, cross-site initiator, main frame navigation), so this
- // request should result in two cookies being set.
- expected_cookies += 2;
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(expected_cookies,
- static_cast<int>(GetAllCookies(&default_context()).size()));
- EXPECT_EQ(expected_cookies, default_network_delegate().set_cookie_count());
- }
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- test_server.GetURL(kHost,
- "/set-cookie?Strict3=1;SameSite=Strict&"
- "Lax3=1;SameSite=Lax"),
- DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(IsolationInfo::Create(
- IsolationInfo::RequestType::kMainFrame, kSubOrigin, kSubOrigin,
- kSiteForCookies, {} /* party_context */));
- req->set_site_for_cookies(
- SiteForCookies::FromUrl(test_server.GetURL(kSubHost, "/")));
- req->set_initiator(kCrossOrigin);
- // 'SameSite' cookies are settable from lax same-site contexts (same-site
- // site_for_cookies, cross-site initiator, main frame navigation), so this
- // request should result in two cookies being set.
- expected_cookies += 2;
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(expected_cookies,
- static_cast<int>(GetAllCookies(&default_context()).size()));
- EXPECT_EQ(expected_cookies, default_network_delegate().set_cookie_count());
- }
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- test_server.GetURL(kHost,
- "/set-cookie?Strict4=1;SameSite=Strict&"
- "Lax4=1;SameSite=Lax"),
- DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_site_for_cookies(
- SiteForCookies::FromUrl(test_server.GetURL(kSubHost, "/")));
- // 'SameSite' cookies are settable from strict same-site contexts (same-site
- // site_for_cookies, no initiator), so this request should result in two
- // cookies being set.
- expected_cookies += 2;
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(expected_cookies,
- static_cast<int>(GetAllCookies(&default_context()).size()));
- EXPECT_EQ(expected_cookies, default_network_delegate().set_cookie_count());
- }
- int expected_network_delegate_set_cookie_count;
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- test_server.GetURL(kHost,
- "/set-cookie?Strict5=1;SameSite=Strict&"
- "Lax5=1;SameSite=Lax"),
- DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_site_for_cookies(kCrossSiteForCookies);
- req->set_initiator(kCrossOrigin);
- // 'SameSite' cookies are not settable from cross-site contexts, so this
- // should not result in any new cookies being set.
- expected_cookies += 0;
- // This counts the number of successful calls to CanSetCookie() when
- // attempting to set a cookie. The two cookies above were created and
- // attempted to be set, and were not rejected by the NetworkDelegate, so the
- // count here is 2 more than the number of cookies actually set.
- expected_network_delegate_set_cookie_count = expected_cookies + 2;
- req->Start();
- d.RunUntilComplete();
- // This counts the number of cookies actually set.
- EXPECT_EQ(expected_cookies,
- static_cast<int>(GetAllCookies(&default_context()).size()));
- EXPECT_EQ(expected_network_delegate_set_cookie_count,
- default_network_delegate().set_cookie_count());
- }
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- test_server.GetURL(kHost,
- "/set-cookie?Strict6=1;SameSite=Strict&"
- "Lax6=1;SameSite=Lax"),
- DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(IsolationInfo::Create(
- IsolationInfo::RequestType::kSubFrame, kOrigin, kOrigin,
- kSiteForCookies, {} /* party_context */));
- req->set_site_for_cookies(kSiteForCookies);
- req->set_initiator(kCrossOrigin);
- // Same-site site-for-cookies, cross-site initiator, non main frame
- // navigation -> context is considered cross-site so no SameSite cookies are
- // set.
- expected_cookies += 0;
- // This counts the number of successful calls to CanSetCookie() when
- // attempting to set a cookie. The two cookies above were created and
- // attempted to be set, and were not rejected by the NetworkDelegate, so the
- // count here is 2 more than the number of cookies actually set.
- expected_network_delegate_set_cookie_count += 2;
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(expected_cookies,
- static_cast<int>(GetAllCookies(&default_context()).size()));
- EXPECT_EQ(expected_network_delegate_set_cookie_count,
- default_network_delegate().set_cookie_count());
- // Check that the appropriate cookie inclusion status is set.
- ASSERT_EQ(2u, req->maybe_stored_cookies().size());
- CookieInclusionStatus expected_strict_status =
- CookieInclusionStatus::MakeFromReasonsForTesting(
- {CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT},
- {} /* warning_reasons */);
- CookieInclusionStatus expected_lax_status =
- CookieInclusionStatus::MakeFromReasonsForTesting(
- {CookieInclusionStatus::EXCLUDE_SAMESITE_LAX},
- {} /* warning_reasons */);
- EXPECT_EQ(expected_strict_status,
- req->maybe_stored_cookies()[0].access_result.status);
- EXPECT_EQ(expected_lax_status,
- req->maybe_stored_cookies()[1].access_result.status);
- }
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- test_server.GetURL(kHost,
- "/set-cookie?Strict7=1;SameSite=Strict&"
- "Lax7=1;SameSite=Lax"),
- DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(IsolationInfo::Create(
- IsolationInfo::RequestType::kOther, kOrigin, kOrigin, kSiteForCookies,
- {} /* party_context */));
- req->set_site_for_cookies(kSiteForCookies);
- req->set_initiator(kCrossOrigin);
- req->set_force_main_frame_for_same_site_cookies(true);
- // 'SameSite' cookies are settable from lax same-site contexts (same-origin
- // site_for_cookies, cross-site initiator, main frame navigation), so this
- // request should result in two cookies being set.
- expected_cookies += 2;
- expected_network_delegate_set_cookie_count += 2;
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(expected_cookies,
- static_cast<int>(GetAllCookies(&default_context()).size()));
- EXPECT_EQ(expected_network_delegate_set_cookie_count,
- default_network_delegate().set_cookie_count());
- }
- }
- // Tests special chrome:// scheme that is supposed to always attach SameSite
- // cookies if the requested site is secure.
- TEST_P(URLRequestSameSiteCookiesTest, SameSiteCookiesSpecialScheme) {
- url::ScopedSchemeRegistryForTests scoped_registry;
- url::AddStandardScheme("chrome", url::SchemeType::SCHEME_WITH_HOST);
- EmbeddedTestServer https_test_server(EmbeddedTestServer::TYPE_HTTPS);
- RegisterDefaultHandlers(&https_test_server);
- ASSERT_TRUE(https_test_server.Start());
- EmbeddedTestServer http_test_server(EmbeddedTestServer::TYPE_HTTP);
- RegisterDefaultHandlers(&http_test_server);
- ASSERT_TRUE(http_test_server.Start());
- ASSERT_NE(https_test_server.port(), http_test_server.port());
- // Both hostnames should be 127.0.0.1 (so that we can use the same set of
- // cookies on both, for convenience).
- ASSERT_EQ(https_test_server.host_port_pair().host(),
- http_test_server.host_port_pair().host());
- // Set up special schemes
- auto cad = std::make_unique<TestCookieAccessDelegate>();
- cad->SetIgnoreSameSiteRestrictionsScheme("chrome", true);
- auto cm = std::make_unique<CookieMonster>(nullptr, nullptr,
- /*first_party_sets_enabled=*/false);
- cm->SetCookieAccessDelegate(std::move(cad));
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->SetCookieStore(std::move(cm));
- auto context = context_builder->Build();
- // SameSite cookies are not set for 'chrome' scheme if requested origin is not
- // secure.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(context->CreateRequest(
- http_test_server.GetURL(
- "/set-cookie?StrictSameSiteCookie=1;SameSite=Strict&"
- "LaxSameSiteCookie=1;SameSite=Lax"),
- DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_site_for_cookies(
- SiteForCookies::FromUrl(GURL("chrome://whatever/")));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(0u, GetAllCookies(context.get()).size());
- }
- // But they are set for 'chrome' scheme if the requested origin is secure.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(context->CreateRequest(
- https_test_server.GetURL(
- "/set-cookie?StrictSameSiteCookie=1;SameSite=Strict&"
- "LaxSameSiteCookie=1;SameSite=Lax"),
- DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_site_for_cookies(
- SiteForCookies::FromUrl(GURL("chrome://whatever/")));
- req->Start();
- d.RunUntilComplete();
- CookieList cookies = GetAllCookies(context.get());
- EXPECT_EQ(2u, cookies.size());
- }
- // Verify that they are both sent when the site_for_cookies scheme is
- // 'chrome' and the requested origin is secure.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(context->CreateRequest(
- https_test_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_site_for_cookies(
- SiteForCookies::FromUrl(GURL("chrome://whatever/")));
- req->Start();
- d.RunUntilComplete();
- EXPECT_NE(std::string::npos,
- d.data_received().find("StrictSameSiteCookie=1"));
- EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
- }
- // Verify that they are not sent when the site_for_cookies scheme is
- // 'chrome' and the requested origin is not secure.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(context->CreateRequest(
- http_test_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_site_for_cookies(
- SiteForCookies::FromUrl(GURL("chrome://whatever/")));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(std::string::npos,
- d.data_received().find("StrictSameSiteCookie"));
- EXPECT_EQ(std::string::npos, d.data_received().find("LaxSameSiteCookie"));
- }
- }
- TEST_P(URLRequestSameSiteCookiesTest, SettingSameSiteCookies_Redirect) {
- EmbeddedTestServer http_server;
- RegisterDefaultHandlers(&http_server);
- EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS);
- https_server.SetSSLConfig(EmbeddedTestServer::CERT_TEST_NAMES);
- RegisterDefaultHandlers(&https_server);
- ASSERT_TRUE(http_server.Start());
- ASSERT_TRUE(https_server.Start());
- auto& network_delegate = default_network_delegate();
- const std::string kHost = "foo.a.test";
- const std::string kSameSiteHost = "bar.a.test";
- const std::string kCrossSiteHost = "b.test";
- const url::Origin kOrigin =
- url::Origin::Create(https_server.GetURL(kHost, "/"));
- const url::Origin kHttpOrigin =
- url::Origin::Create(http_server.GetURL(kHost, "/"));
- const url::Origin kSameSiteOrigin =
- url::Origin::Create(https_server.GetURL(kSameSiteHost, "/"));
- const url::Origin kCrossSiteOrigin =
- url::Origin::Create(https_server.GetURL(kCrossSiteHost, "/"));
- const SiteForCookies kSiteForCookies = SiteForCookies::FromOrigin(kOrigin);
- const SiteForCookies kHttpSiteForCookies =
- SiteForCookies::FromOrigin(kHttpOrigin);
- const SiteForCookies kCrossSiteForCookies =
- SiteForCookies::FromOrigin(kCrossSiteOrigin);
- int expected_cookies = 0;
- int expected_set_cookie_count = 0;
- // Verify that SameSite cookies can be set for a same-origin redirected
- // top-level navigation request.
- {
- TestDelegate d;
- GURL set_cookie_url = https_server.GetURL(
- kHost, "/set-cookie?Strict1=1;SameSite=Strict&Lax1=1;SameSite=Lax");
- GURL url =
- https_server.GetURL(kHost, "/server-redirect?" + set_cookie_url.spec());
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(IsolationInfo::Create(
- IsolationInfo::RequestType::kMainFrame, kOrigin, kOrigin,
- kSiteForCookies, {} /* party_context */));
- req->set_first_party_url_policy(
- RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT);
- req->set_site_for_cookies(kSiteForCookies);
- req->set_initiator(kOrigin);
- expected_cookies += 2;
- expected_set_cookie_count += 2;
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(expected_cookies,
- static_cast<int>(GetAllCookies(&default_context()).size()));
- EXPECT_EQ(expected_set_cookie_count, network_delegate.set_cookie_count());
- }
- // Verify that SameSite cookies can be set for a same-site redirected
- // top-level navigation request.
- {
- TestDelegate d;
- GURL set_cookie_url = https_server.GetURL(
- kHost, "/set-cookie?Strict2=1;SameSite=Strict&Lax2=1;SameSite=Lax");
- GURL url = https_server.GetURL(kSameSiteHost,
- "/server-redirect?" + set_cookie_url.spec());
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(IsolationInfo::Create(
- IsolationInfo::RequestType::kMainFrame, kSameSiteOrigin,
- kSameSiteOrigin, kSiteForCookies, {} /* party_context */));
- req->set_first_party_url_policy(
- RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT);
- req->set_site_for_cookies(kSiteForCookies);
- req->set_initiator(kSameSiteOrigin);
- expected_cookies += 2;
- expected_set_cookie_count += 2;
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(expected_cookies,
- static_cast<int>(GetAllCookies(&default_context()).size()));
- EXPECT_EQ(expected_set_cookie_count, network_delegate.set_cookie_count());
- }
- // Verify that SameSite cookies can be set for a cross-site redirected
- // top-level navigation request.
- {
- TestDelegate d;
- GURL set_cookie_url = https_server.GetURL(
- kHost, "/set-cookie?Strict3=1;SameSite=Strict&Lax3=1;SameSite=Lax");
- GURL url = https_server.GetURL(kCrossSiteHost,
- "/server-redirect?" + set_cookie_url.spec());
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(IsolationInfo::Create(
- IsolationInfo::RequestType::kMainFrame, kCrossSiteOrigin,
- kCrossSiteOrigin, kCrossSiteForCookies, {} /* party_context */));
- req->set_first_party_url_policy(
- RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT);
- req->set_site_for_cookies(kCrossSiteForCookies);
- req->set_initiator(kCrossSiteOrigin);
- expected_cookies += 2;
- expected_set_cookie_count += 2;
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(expected_cookies,
- static_cast<int>(GetAllCookies(&default_context()).size()));
- EXPECT_EQ(expected_set_cookie_count, network_delegate.set_cookie_count());
- }
- // Verify that SameSite cookies can be set for a same-origin redirected
- // subresource request.
- {
- TestDelegate d;
- GURL set_cookie_url = https_server.GetURL(
- kHost, "/set-cookie?Strict4=1;SameSite=Strict&Lax4=1;SameSite=Lax");
- GURL url =
- https_server.GetURL(kHost, "/server-redirect?" + set_cookie_url.spec());
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(IsolationInfo::Create(
- IsolationInfo::RequestType::kOther, kOrigin, kOrigin, kSiteForCookies,
- {} /* party_context */));
- req->set_site_for_cookies(kSiteForCookies);
- req->set_initiator(kOrigin);
- expected_cookies += 2;
- expected_set_cookie_count += 2;
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(expected_cookies,
- static_cast<int>(GetAllCookies(&default_context()).size()));
- EXPECT_EQ(expected_set_cookie_count, network_delegate.set_cookie_count());
- }
- // Verify that SameSite cookies can be set for a same-site redirected
- // subresource request.
- {
- TestDelegate d;
- GURL set_cookie_url = https_server.GetURL(
- kHost, "/set-cookie?Strict5=1;SameSite=Strict&Lax5=1;SameSite=Lax");
- GURL url = https_server.GetURL(kSameSiteHost,
- "/server-redirect?" + set_cookie_url.spec());
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(IsolationInfo::Create(
- IsolationInfo::RequestType::kOther, kSameSiteOrigin, kSameSiteOrigin,
- kSiteForCookies, {} /* party_context */));
- req->set_site_for_cookies(kSiteForCookies);
- req->set_initiator(kSameSiteOrigin);
- expected_cookies += 2;
- expected_set_cookie_count += 2;
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(expected_cookies,
- static_cast<int>(GetAllCookies(&default_context()).size()));
- EXPECT_EQ(expected_set_cookie_count, network_delegate.set_cookie_count());
- }
- // Verify that (depending on whether redirect chains are considered) SameSite
- // cookies can/cannot be set for a cross-site redirected subresource request,
- // even if the site-for-cookies and initiator are same-site, ...
- {
- TestDelegate d;
- GURL set_cookie_url = https_server.GetURL(
- kHost, "/set-cookie?Strict6=1;SameSite=Strict&Lax6=1;SameSite=Lax");
- GURL url = https_server.GetURL(kCrossSiteHost,
- "/server-redirect?" + set_cookie_url.spec());
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(IsolationInfo::Create(
- IsolationInfo::RequestType::kOther, kOrigin, kOrigin, kSiteForCookies,
- {} /* party_context */));
- req->set_site_for_cookies(kSiteForCookies);
- req->set_initiator(kOrigin);
- expected_cookies += DoesCookieSameSiteConsiderRedirectChain() ? 0 : 2;
- expected_set_cookie_count += 2;
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(expected_cookies,
- static_cast<int>(GetAllCookies(&default_context()).size()));
- EXPECT_EQ(expected_set_cookie_count, network_delegate.set_cookie_count());
- }
- // ... even if the initial URL is same-site.
- {
- TestDelegate d;
- GURL set_cookie_url = https_server.GetURL(
- kHost, "/set-cookie?Strict7=1;SameSite=Strict&Lax7=1;SameSite=Lax");
- GURL middle_url = https_server.GetURL(
- kCrossSiteHost, "/server-redirect?" + set_cookie_url.spec());
- GURL url =
- https_server.GetURL(kHost, "/server-redirect?" + middle_url.spec());
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(IsolationInfo::Create(
- IsolationInfo::RequestType::kOther, kOrigin, kOrigin, kSiteForCookies,
- {} /* party_context */));
- req->set_site_for_cookies(kSiteForCookies);
- req->set_initiator(kOrigin);
- expected_cookies += DoesCookieSameSiteConsiderRedirectChain() ? 0 : 2;
- expected_set_cookie_count += 2;
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(expected_cookies,
- static_cast<int>(GetAllCookies(&default_context()).size()));
- EXPECT_EQ(expected_set_cookie_count, network_delegate.set_cookie_count());
- }
- // Verify that SameSite cookies may or may not be set for a cross-scheme
- // (same-registrable-domain) redirected subresource request, depending on the
- // status of Schemeful Same-Site and whether redirect chains are considered.
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndDisableFeature(features::kSchemefulSameSite);
- TestDelegate d;
- GURL set_cookie_url = https_server.GetURL(
- kHost, "/set-cookie?Strict8=1;SameSite=Strict&Lax8=1;SameSite=Lax");
- GURL url =
- http_server.GetURL(kHost, "/server-redirect?" + set_cookie_url.spec());
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(IsolationInfo::Create(
- IsolationInfo::RequestType::kOther, kHttpOrigin, kHttpOrigin,
- kHttpSiteForCookies, {} /* party_context */));
- req->set_first_party_url_policy(
- RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT);
- req->set_site_for_cookies(kHttpSiteForCookies);
- req->set_initiator(kOrigin);
- expected_cookies += 2;
- expected_set_cookie_count += 2;
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(expected_cookies,
- static_cast<int>(GetAllCookies(&default_context()).size()));
- EXPECT_EQ(expected_set_cookie_count, network_delegate.set_cookie_count());
- }
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(features::kSchemefulSameSite);
- TestDelegate d;
- GURL set_cookie_url = https_server.GetURL(
- kHost, "/set-cookie?Strict9=1;SameSite=Strict&Lax9=1;SameSite=Lax");
- GURL url =
- http_server.GetURL(kHost, "/server-redirect?" + set_cookie_url.spec());
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(IsolationInfo::Create(
- IsolationInfo::RequestType::kOther, kHttpOrigin, kHttpOrigin,
- kHttpSiteForCookies, {} /* party_context */));
- req->set_first_party_url_policy(
- RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT);
- req->set_site_for_cookies(kHttpSiteForCookies);
- req->set_initiator(kOrigin);
- expected_cookies += DoesCookieSameSiteConsiderRedirectChain() ? 0 : 2;
- expected_set_cookie_count += 2;
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(expected_cookies,
- static_cast<int>(GetAllCookies(&default_context()).size()));
- EXPECT_EQ(expected_set_cookie_count, network_delegate.set_cookie_count());
- }
- }
- INSTANTIATE_TEST_SUITE_P(/* no label */,
- URLRequestSameSiteCookiesTest,
- ::testing::Bool());
- // Tests that __Secure- cookies can't be set on non-secure origins.
- TEST_F(URLRequestTest, SecureCookiePrefixOnNonsecureOrigin) {
- EmbeddedTestServer http_server;
- RegisterDefaultHandlers(&http_server);
- EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS);
- https_server.SetSSLConfig(EmbeddedTestServer::CERT_TEST_NAMES);
- RegisterDefaultHandlers(&https_server);
- ASSERT_TRUE(http_server.Start());
- ASSERT_TRUE(https_server.Start());
- // Try to set a Secure __Secure- cookie on http://a.test (non-secure origin).
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(),
- http_server.GetURL("a.test",
- "/set-cookie?__Secure-nonsecure-origin=1;Secure&"
- "cookienotsecure=1"),
- &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- }
- // Verify that the __Secure- cookie was not set by checking cookies for
- // https://a.test (secure origin).
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(), https_server.GetURL("a.test", "/echoheader?Cookie"),
- &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(d.data_received().find("__Secure-nonsecure-origin=1"),
- std::string::npos);
- EXPECT_NE(d.data_received().find("cookienotsecure=1"), std::string::npos);
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- }
- }
- TEST_F(URLRequestTest, SecureCookiePrefixNonsecure) {
- EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS);
- RegisterDefaultHandlers(&https_server);
- ASSERT_TRUE(https_server.Start());
- // Try to set a non-Secure __Secure- cookie.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(), https_server.GetURL("/set-cookie?__Secure-foo=1"),
- &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(0, default_network_delegate().set_cookie_count());
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- }
- // Verify that the cookie is not set.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(), https_server.GetURL("/echoheader?Cookie"), &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(d.data_received().find("__Secure-foo=1"), std::string::npos);
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- }
- }
- TEST_F(URLRequestTest, SecureCookiePrefixSecure) {
- EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS);
- RegisterDefaultHandlers(&https_server);
- ASSERT_TRUE(https_server.Start());
- // Try to set a Secure __Secure- cookie.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(),
- https_server.GetURL("/set-cookie?__Secure-bar=1;Secure"), &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- }
- // Verify that the cookie is set.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(), https_server.GetURL("/echoheader?Cookie"), &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_NE(d.data_received().find("__Secure-bar=1"), std::string::npos);
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- }
- }
- // Tests that secure cookies can't be set on non-secure origins if strict secure
- // cookies are enabled.
- TEST_F(URLRequestTest, StrictSecureCookiesOnNonsecureOrigin) {
- EmbeddedTestServer http_server;
- RegisterDefaultHandlers(&http_server);
- EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS);
- https_server.SetSSLConfig(EmbeddedTestServer::CERT_TEST_NAMES);
- RegisterDefaultHandlers(&https_server);
- ASSERT_TRUE(http_server.Start());
- ASSERT_TRUE(https_server.Start());
- // Try to set a Secure cookie and a non-Secure cookie from a nonsecure origin.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(),
- http_server.GetURL("a.test",
- "/set-cookie?nonsecure-origin=1;Secure&"
- "cookienotsecure=1"),
- &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- }
- // Verify that the Secure cookie was not set.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- default_context(), https_server.GetURL("a.test", "/echoheader?Cookie"),
- &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(d.data_received().find("nonsecure-origin=1"), std::string::npos);
- EXPECT_NE(d.data_received().find("cookienotsecure=1"), std::string::npos);
- EXPECT_EQ(0, default_network_delegate().blocked_annotate_cookies_count());
- EXPECT_EQ(0, default_network_delegate().blocked_set_cookie_count());
- }
- }
- // FixedDateNetworkDelegate swaps out the server's HTTP Date response header
- // value for the `fixed_date_` member.
- class FixedDateNetworkDelegate : public TestNetworkDelegate {
- public:
- explicit FixedDateNetworkDelegate(base::StringPiece fixed_date)
- : fixed_date_(fixed_date) {}
- FixedDateNetworkDelegate(const FixedDateNetworkDelegate&) = delete;
- FixedDateNetworkDelegate& operator=(const FixedDateNetworkDelegate&) = delete;
- ~FixedDateNetworkDelegate() override = default;
- void set_fixed_date(base::StringPiece fixed_date) {
- fixed_date_ = static_cast<std::string>(fixed_date);
- }
- // NetworkDelegate implementation
- int OnHeadersReceived(
- URLRequest* request,
- CompletionOnceCallback callback,
- const HttpResponseHeaders* original_response_headers,
- scoped_refptr<HttpResponseHeaders>* override_response_headers,
- const IPEndPoint& endpoint,
- absl::optional<GURL>* preserve_fragment_on_redirect_url) override;
- private:
- std::string fixed_date_;
- };
- int FixedDateNetworkDelegate::OnHeadersReceived(
- URLRequest* request,
- CompletionOnceCallback callback,
- const HttpResponseHeaders* original_response_headers,
- scoped_refptr<HttpResponseHeaders>* override_response_headers,
- const IPEndPoint& endpoint,
- absl::optional<GURL>* preserve_fragment_on_redirect_url) {
- *override_response_headers = base::MakeRefCounted<HttpResponseHeaders>(
- original_response_headers->raw_headers());
- (*override_response_headers)->SetHeader("Date", fixed_date_);
- return TestNetworkDelegate::OnHeadersReceived(
- request, std::move(callback), original_response_headers,
- override_response_headers, endpoint, preserve_fragment_on_redirect_url);
- }
- // Test that cookie expiration times are adjusted for server/client clock
- // skew and that we handle incorrect timezone specifier "UTC" in HTTP Date
- // headers by defaulting to GMT. (crbug.com/135131)
- TEST_F(URLRequestTest, AcceptClockSkewCookieWithWrongDateTimezone) {
- HttpTestServer test_server;
- ASSERT_TRUE(test_server.Start());
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<FixedDateNetworkDelegate>("04-Jan-2004 04:09:25 UTC"));
- auto context = context_builder->Build();
- // Set up an expired cookie.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- *context,
- test_server.GetURL(
- "/set-cookie?StillGood=1;expires=Mon,18-Apr-1977,22:50:13,GMT"),
- &d);
- req->Start();
- d.RunUntilComplete();
- }
- // Verify that the cookie is not set.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- *context, test_server.GetURL("/echoheader?Cookie"), &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_TRUE(d.data_received().find("StillGood=1") == std::string::npos);
- }
- // Set up a cookie with clock skew and "UTC" HTTP Date timezone specifier.
- {
- TestDelegate d;
- network_delegate.set_fixed_date("18-Apr-1977 22:49:13 UTC");
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- *context,
- test_server.GetURL(
- "/set-cookie?StillGood=1;expires=Mon,18-Apr-1977,22:50:13,GMT"),
- &d);
- req->Start();
- d.RunUntilComplete();
- }
- // Verify that the cookie is set.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req = CreateFirstPartyRequest(
- *context, test_server.GetURL("/echoheader?Cookie"), &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_TRUE(d.data_received().find("StillGood=1") != std::string::npos);
- }
- }
- // Check that it is impossible to change the referrer in the extra headers of
- // an URLRequest.
- TEST_F(URLRequestTest, DoNotOverrideReferrer) {
- HttpTestServer test_server;
- ASSERT_TRUE(test_server.Start());
- // If extra headers contain referer and the request contains a referer,
- // only the latter shall be respected.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- test_server.GetURL("/echoheader?Referer"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->SetReferrer("http://foo.com/");
- HttpRequestHeaders headers;
- headers.SetHeader(HttpRequestHeaders::kReferer, "http://bar.com/");
- req->SetExtraRequestHeaders(headers);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ("http://foo.com/", d.data_received());
- }
- // If extra headers contain a referer but the request does not, no referer
- // shall be sent in the header.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- test_server.GetURL("/echoheader?Referer"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- HttpRequestHeaders headers;
- headers.SetHeader(HttpRequestHeaders::kReferer, "http://bar.com/");
- req->SetExtraRequestHeaders(headers);
- req->SetLoadFlags(LOAD_VALIDATE_CACHE);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ("None", d.data_received());
- }
- }
- class URLRequestTestHTTP : public URLRequestTest {
- public:
- const url::Origin origin1_;
- const url::Origin origin2_;
- const IsolationInfo isolation_info1_;
- const IsolationInfo isolation_info2_;
- URLRequestTestHTTP()
- : origin1_(url::Origin::Create(GURL("https://foo.test/"))),
- origin2_(url::Origin::Create(GURL("https://bar.test/"))),
- isolation_info1_(IsolationInfo::CreateForInternalRequest(origin1_)),
- isolation_info2_(IsolationInfo::CreateForInternalRequest(origin2_)),
- test_server_(base::FilePath(kTestFilePath)) {
- // Needed for NetworkIsolationKey to make it down to the socket layer, for
- // the PKP violation report test.
- feature_list_.InitAndEnableFeature(
- net::features::kPartitionConnectionsByNetworkIsolationKey);
- }
- protected:
- // ProtocolHandler for the scheme that's unsafe to redirect to.
- class NET_EXPORT UnsafeRedirectProtocolHandler
- : public URLRequestJobFactory::ProtocolHandler {
- public:
- UnsafeRedirectProtocolHandler() = default;
- UnsafeRedirectProtocolHandler(const UnsafeRedirectProtocolHandler&) =
- delete;
- UnsafeRedirectProtocolHandler& operator=(
- const UnsafeRedirectProtocolHandler&) = delete;
- ~UnsafeRedirectProtocolHandler() override = default;
- // URLRequestJobFactory::ProtocolHandler implementation:
- std::unique_ptr<URLRequestJob> CreateJob(
- URLRequest* request) const override {
- NOTREACHED();
- return nullptr;
- }
- bool IsSafeRedirectTarget(const GURL& location) const override {
- return false;
- }
- };
- // URLRequestTest interface:
- void SetUpContextBuilder(URLRequestContextBuilder& builder) override {
- // Add support for an unsafe scheme to the default URLRequestContext.
- builder.SetProtocolHandler(
- "unsafe", std::make_unique<UnsafeRedirectProtocolHandler>());
- }
- // Requests |redirect_url|, which must return a HTTP 3xx redirect.
- // |request_method| is the method to use for the initial request.
- // |redirect_method| is the method that is expected to be used for the second
- // request, after redirection.
- // If |include_data| is true, data is uploaded with the request. The
- // response body is expected to match it exactly, if and only if
- // |request_method| == |redirect_method|.
- void HTTPRedirectMethodTest(const GURL& redirect_url,
- const std::string& request_method,
- const std::string& redirect_method,
- bool include_data) {
- static const char kData[] = "hello world";
- TestDelegate d;
- std::unique_ptr<URLRequest> req =
- CreateFirstPartyRequest(default_context(), redirect_url, &d);
- req->set_method(request_method);
- if (include_data) {
- req->set_upload(CreateSimpleUploadData(kData));
- HttpRequestHeaders headers;
- headers.SetHeader(HttpRequestHeaders::kContentLength,
- base::NumberToString(std::size(kData) - 1));
- headers.SetHeader(HttpRequestHeaders::kContentType, "text/plain");
- req->SetExtraRequestHeaders(headers);
- }
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(redirect_method, req->method());
- EXPECT_EQ(OK, d.request_status());
- if (include_data) {
- if (request_method == redirect_method) {
- EXPECT_TRUE(req->extra_request_headers().HasHeader(
- HttpRequestHeaders::kContentLength));
- EXPECT_TRUE(req->extra_request_headers().HasHeader(
- HttpRequestHeaders::kContentType));
- EXPECT_EQ(kData, d.data_received());
- } else {
- EXPECT_FALSE(req->extra_request_headers().HasHeader(
- HttpRequestHeaders::kContentLength));
- EXPECT_FALSE(req->extra_request_headers().HasHeader(
- HttpRequestHeaders::kContentType));
- EXPECT_NE(kData, d.data_received());
- }
- }
- if (HasFailure())
- LOG(WARNING) << "Request method was: " << request_method;
- }
- // Requests |redirect_url|, which must return a HTTP 3xx redirect. It's also
- // used as the initial origin.
- // |request_method| is the method to use for the initial request.
- // |redirect_method| is the method that is expected to be used for the second
- // request, after redirection.
- // |expected_origin_value| is the expected value for the Origin header after
- // redirection. If empty, expects that there will be no Origin header.
- void HTTPRedirectOriginHeaderTest(const GURL& redirect_url,
- const std::string& request_method,
- const std::string& redirect_method,
- const std::string& expected_origin_value) {
- TestDelegate d;
- std::unique_ptr<URLRequest> req =
- CreateFirstPartyRequest(default_context(), redirect_url, &d);
- req->set_method(request_method);
- req->SetExtraRequestHeaderByName(
- HttpRequestHeaders::kOrigin,
- redirect_url.DeprecatedGetOriginAsURL().spec(), false);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(redirect_method, req->method());
- // Note that there is no check for request success here because, for
- // purposes of testing, the request very well may fail. For example, if the
- // test redirects to an HTTPS server from an HTTP origin, thus it is cross
- // origin, there is not an HTTPS server in this unit test framework, so the
- // request would fail. However, that's fine, as long as the request headers
- // are in order and pass the checks below.
- if (expected_origin_value.empty()) {
- EXPECT_FALSE(
- req->extra_request_headers().HasHeader(HttpRequestHeaders::kOrigin));
- } else {
- std::string origin_header;
- EXPECT_TRUE(req->extra_request_headers().GetHeader(
- HttpRequestHeaders::kOrigin, &origin_header));
- EXPECT_EQ(expected_origin_value, origin_header);
- }
- }
- void HTTPUploadDataOperationTest(const std::string& method) {
- const int kMsgSize = 20000; // multiple of 10
- const int kIterations = 50;
- auto uploadBytes = std::make_unique<char[]>(kMsgSize + 1);
- char* ptr = uploadBytes.get();
- char marker = 'a';
- for (int idx = 0; idx < kMsgSize / 10; idx++) {
- memcpy(ptr, "----------", 10);
- ptr += 10;
- if (idx % 100 == 0) {
- ptr--;
- *ptr++ = marker;
- if (++marker > 'z')
- marker = 'a';
- }
- }
- uploadBytes[kMsgSize] = '\0';
- for (int i = 0; i < kIterations; ++i) {
- TestDelegate d;
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- test_server_.GetURL("/echo"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->set_method(method.c_str());
- r->set_upload(CreateSimpleUploadData(uploadBytes.get()));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- ASSERT_EQ(1, d.response_started_count())
- << "request failed. Error: " << d.request_status();
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_EQ(base::StringPiece(uploadBytes.get(), kMsgSize),
- d.data_received());
- }
- }
- HttpTestServer* http_test_server() { return &test_server_; }
- private:
- base::test::ScopedFeatureList feature_list_;
- HttpTestServer test_server_;
- };
- namespace {
- std::unique_ptr<test_server::HttpResponse> HandleRedirectConnect(
- const test_server::HttpRequest& request) {
- if (request.headers.find("Host") == request.headers.end() ||
- request.headers.at("Host") != "www.redirect.com" ||
- request.method != test_server::METHOD_CONNECT) {
- return nullptr;
- }
- auto http_response = std::make_unique<test_server::BasicHttpResponse>();
- http_response->set_code(HTTP_FOUND);
- http_response->AddCustomHeader("Location",
- "http://www.destination.com/foo.js");
- return std::move(http_response);
- }
- } // namespace
- // In this unit test, we're using the HTTPTestServer as a proxy server and
- // issuing a CONNECT request with the magic host name "www.redirect.com".
- // The EmbeddedTestServer will return a 302 response, which we should not
- // follow.
- TEST_F(URLRequestTestHTTP, ProxyTunnelRedirectTest) {
- http_test_server()->RegisterRequestHandler(
- base::BindRepeating(&HandleRedirectConnect));
- ASSERT_TRUE(http_test_server()->Start());
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_proxy_resolution_service(
- CreateFixedProxyResolutionService(
- http_test_server()->host_port_pair().ToString()));
- auto context = context_builder->Build();
- TestDelegate d;
- {
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- GURL("https://www.redirect.com/"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- // The proxy server should be set before failure.
- EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
- http_test_server()->host_port_pair()),
- r->proxy_server());
- EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, d.request_status());
- EXPECT_EQ(1, d.response_started_count());
- // We should not have followed the redirect.
- EXPECT_EQ(0, d.received_redirect_count());
- }
- }
- // This is the same as the previous test, but checks that the network delegate
- // registers the error.
- TEST_F(URLRequestTestHTTP, NetworkDelegateTunnelConnectionFailed) {
- ASSERT_TRUE(http_test_server()->Start());
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_proxy_resolution_service(
- CreateFixedProxyResolutionService(
- http_test_server()->host_port_pair().ToString()));
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<TestNetworkDelegate>());
- auto context = context_builder->Build();
- TestDelegate d;
- {
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- GURL("https://www.redirect.com/"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- // The proxy server should be set before failure.
- EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
- http_test_server()->host_port_pair()),
- r->proxy_server());
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, d.request_status());
- // We should not have followed the redirect.
- EXPECT_EQ(0, d.received_redirect_count());
- EXPECT_EQ(1, network_delegate.error_count());
- EXPECT_THAT(network_delegate.last_error(),
- IsError(ERR_TUNNEL_CONNECTION_FAILED));
- }
- }
- // Tests that we can block and asynchronously return OK in various stages.
- TEST_F(URLRequestTestHTTP, NetworkDelegateBlockAsynchronously) {
- static const BlockingNetworkDelegate::Stage blocking_stages[] = {
- BlockingNetworkDelegate::ON_BEFORE_URL_REQUEST,
- BlockingNetworkDelegate::ON_BEFORE_SEND_HEADERS,
- BlockingNetworkDelegate::ON_HEADERS_RECEIVED};
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<BlockingNetworkDelegate>(
- BlockingNetworkDelegate::USER_CALLBACK));
- network_delegate.set_block_on(
- BlockingNetworkDelegate::ON_BEFORE_URL_REQUEST |
- BlockingNetworkDelegate::ON_BEFORE_SEND_HEADERS |
- BlockingNetworkDelegate::ON_HEADERS_RECEIVED);
- auto context = context_builder->Build();
- {
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- http_test_server()->GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- for (auto stage : blocking_stages) {
- network_delegate.RunUntilBlocked();
- EXPECT_EQ(stage, network_delegate.stage_blocked_for_callback());
- network_delegate.DoCallback(OK);
- }
- d.RunUntilComplete();
- EXPECT_EQ(200, r->GetResponseCode());
- EXPECT_EQ(OK, d.request_status());
- EXPECT_EQ(1, network_delegate.created_requests());
- EXPECT_EQ(0, network_delegate.destroyed_requests());
- }
- EXPECT_EQ(1, network_delegate.destroyed_requests());
- }
- // Tests that the network delegate can block and cancel a request.
- TEST_F(URLRequestTestHTTP, NetworkDelegateCancelRequest) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_proxy_resolution_service(
- CreateFixedProxyResolutionService(
- http_test_server()->host_port_pair().ToString()));
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<BlockingNetworkDelegate>(
- BlockingNetworkDelegate::AUTO_CALLBACK));
- auto context = context_builder->Build();
- network_delegate.set_block_on(BlockingNetworkDelegate::ON_BEFORE_URL_REQUEST);
- network_delegate.set_retval(ERR_EMPTY_RESPONSE);
- {
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- http_test_server()->GetURL("/"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- d.RunUntilComplete();
- // The proxy server is not set before cancellation.
- EXPECT_FALSE(r->proxy_server().is_valid());
- EXPECT_EQ(ERR_EMPTY_RESPONSE, d.request_status());
- EXPECT_EQ(1, network_delegate.created_requests());
- EXPECT_EQ(0, network_delegate.destroyed_requests());
- }
- EXPECT_EQ(1, network_delegate.destroyed_requests());
- }
- // Helper function for NetworkDelegateCancelRequestAsynchronously and
- // NetworkDelegateCancelRequestSynchronously. Sets up a blocking network
- // delegate operating in |block_mode| and a request for |url|. It blocks the
- // request in |stage| and cancels it with ERR_BLOCKED_BY_CLIENT.
- void NetworkDelegateCancelRequest(BlockingNetworkDelegate::BlockMode block_mode,
- BlockingNetworkDelegate::Stage stage,
- const GURL& url) {
- TestDelegate d;
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<BlockingNetworkDelegate>(block_mode));
- network_delegate.set_retval(ERR_BLOCKED_BY_CLIENT);
- network_delegate.set_block_on(stage);
- auto context = context_builder->Build();
- {
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- d.RunUntilComplete();
- // The proxy server is not set before cancellation.
- if (stage == BlockingNetworkDelegate::ON_BEFORE_URL_REQUEST ||
- stage == BlockingNetworkDelegate::ON_BEFORE_SEND_HEADERS) {
- EXPECT_FALSE(r->proxy_server().is_valid());
- } else if (stage == BlockingNetworkDelegate::ON_HEADERS_RECEIVED) {
- EXPECT_TRUE(r->proxy_server().is_direct());
- } else {
- NOTREACHED();
- }
- EXPECT_EQ(ERR_BLOCKED_BY_CLIENT, d.request_status());
- EXPECT_EQ(1, network_delegate.created_requests());
- EXPECT_EQ(0, network_delegate.destroyed_requests());
- }
- EXPECT_EQ(1, network_delegate.destroyed_requests());
- }
- // The following 3 tests check that the network delegate can cancel a request
- // synchronously in various stages of the request.
- TEST_F(URLRequestTestHTTP, NetworkDelegateCancelRequestSynchronously1) {
- ASSERT_TRUE(http_test_server()->Start());
- NetworkDelegateCancelRequest(BlockingNetworkDelegate::SYNCHRONOUS,
- BlockingNetworkDelegate::ON_BEFORE_URL_REQUEST,
- http_test_server()->GetURL("/"));
- }
- TEST_F(URLRequestTestHTTP, NetworkDelegateCancelRequestSynchronously2) {
- ASSERT_TRUE(http_test_server()->Start());
- NetworkDelegateCancelRequest(BlockingNetworkDelegate::SYNCHRONOUS,
- BlockingNetworkDelegate::ON_BEFORE_SEND_HEADERS,
- http_test_server()->GetURL("/"));
- }
- TEST_F(URLRequestTestHTTP, NetworkDelegateCancelRequestSynchronously3) {
- ASSERT_TRUE(http_test_server()->Start());
- NetworkDelegateCancelRequest(BlockingNetworkDelegate::SYNCHRONOUS,
- BlockingNetworkDelegate::ON_HEADERS_RECEIVED,
- http_test_server()->GetURL("/"));
- }
- // The following 3 tests check that the network delegate can cancel a request
- // asynchronously in various stages of the request.
- TEST_F(URLRequestTestHTTP, NetworkDelegateCancelRequestAsynchronously1) {
- ASSERT_TRUE(http_test_server()->Start());
- NetworkDelegateCancelRequest(BlockingNetworkDelegate::AUTO_CALLBACK,
- BlockingNetworkDelegate::ON_BEFORE_URL_REQUEST,
- http_test_server()->GetURL("/"));
- }
- TEST_F(URLRequestTestHTTP, NetworkDelegateCancelRequestAsynchronously2) {
- ASSERT_TRUE(http_test_server()->Start());
- NetworkDelegateCancelRequest(BlockingNetworkDelegate::AUTO_CALLBACK,
- BlockingNetworkDelegate::ON_BEFORE_SEND_HEADERS,
- http_test_server()->GetURL("/"));
- }
- TEST_F(URLRequestTestHTTP, NetworkDelegateCancelRequestAsynchronously3) {
- ASSERT_TRUE(http_test_server()->Start());
- NetworkDelegateCancelRequest(BlockingNetworkDelegate::AUTO_CALLBACK,
- BlockingNetworkDelegate::ON_HEADERS_RECEIVED,
- http_test_server()->GetURL("/"));
- }
- // Tests that the network delegate can block and redirect a request to a new
- // URL.
- TEST_F(URLRequestTestHTTP, NetworkDelegateRedirectRequest) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_proxy_resolution_service(
- CreateFixedProxyResolutionService(
- http_test_server()->host_port_pair().ToString()));
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<BlockingNetworkDelegate>(
- BlockingNetworkDelegate::AUTO_CALLBACK));
- auto context = context_builder->Build();
- GURL redirect_url("http://does.not.resolve.test/simple.html");
- network_delegate.set_redirect_url(redirect_url);
- {
- GURL original_url("http://does.not.resolve.test/defaultresponse");
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- // Quit after hitting the redirect, so can check the headers.
- r->Start();
- d.RunUntilRedirect();
- // Check headers from URLRequestJob.
- EXPECT_EQ(307, r->GetResponseCode());
- EXPECT_EQ(307, r->response_headers()->response_code());
- std::string location;
- ASSERT_TRUE(
- r->response_headers()->EnumerateHeader(nullptr, "Location", &location));
- EXPECT_EQ(redirect_url, GURL(location));
- // Let the request finish.
- r->FollowDeferredRedirect(absl::nullopt /* removed_headers */,
- absl::nullopt /* modified_headers */);
- d.RunUntilComplete();
- EXPECT_EQ(OK, d.request_status());
- EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
- http_test_server()->host_port_pair()),
- r->proxy_server());
- EXPECT_EQ(OK, d.request_status());
- EXPECT_EQ(redirect_url, r->url());
- EXPECT_EQ(original_url, r->original_url());
- EXPECT_EQ(2U, r->url_chain().size());
- EXPECT_EQ(1, network_delegate.created_requests());
- EXPECT_EQ(0, network_delegate.destroyed_requests());
- }
- EXPECT_EQ(1, network_delegate.destroyed_requests());
- }
- // Tests that the network delegate can block and redirect a request to a new
- // URL by setting a redirect_url and returning in OnBeforeURLRequest directly.
- TEST_F(URLRequestTestHTTP, NetworkDelegateRedirectRequestSynchronously) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_proxy_resolution_service(
- CreateFixedProxyResolutionService(
- http_test_server()->host_port_pair().ToString()));
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<BlockingNetworkDelegate>(
- BlockingNetworkDelegate::SYNCHRONOUS));
- auto context = context_builder->Build();
- GURL redirect_url("http://does.not.resolve.test/simple.html");
- network_delegate.set_redirect_url(redirect_url);
- {
- GURL original_url("http://does.not.resolve.test/defaultresponse");
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- // Quit after hitting the redirect, so can check the headers.
- r->Start();
- d.RunUntilRedirect();
- // Check headers from URLRequestJob.
- EXPECT_EQ(307, r->GetResponseCode());
- EXPECT_EQ(307, r->response_headers()->response_code());
- std::string location;
- ASSERT_TRUE(
- r->response_headers()->EnumerateHeader(nullptr, "Location", &location));
- EXPECT_EQ(redirect_url, GURL(location));
- // Let the request finish.
- r->FollowDeferredRedirect(absl::nullopt /* removed_headers */,
- absl::nullopt /* modified_headers */);
- d.RunUntilComplete();
- EXPECT_EQ(OK, d.request_status());
- EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
- http_test_server()->host_port_pair()),
- r->proxy_server());
- EXPECT_EQ(OK, d.request_status());
- EXPECT_EQ(redirect_url, r->url());
- EXPECT_EQ(original_url, r->original_url());
- EXPECT_EQ(2U, r->url_chain().size());
- EXPECT_EQ(1, network_delegate.created_requests());
- EXPECT_EQ(0, network_delegate.destroyed_requests());
- }
- EXPECT_EQ(1, network_delegate.destroyed_requests());
- }
- // Tests that redirects caused by the network delegate preserve POST data.
- TEST_F(URLRequestTestHTTP, NetworkDelegateRedirectRequestPost) {
- ASSERT_TRUE(http_test_server()->Start());
- const char kData[] = "hello world";
- TestDelegate d;
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<BlockingNetworkDelegate>(
- BlockingNetworkDelegate::AUTO_CALLBACK));
- network_delegate.set_block_on(BlockingNetworkDelegate::ON_BEFORE_URL_REQUEST);
- GURL redirect_url(http_test_server()->GetURL("/echo"));
- network_delegate.set_redirect_url(redirect_url);
- auto context = context_builder->Build();
- {
- GURL original_url(http_test_server()->GetURL("/defaultresponse"));
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->set_method("POST");
- r->set_upload(CreateSimpleUploadData(kData));
- HttpRequestHeaders headers;
- headers.SetHeader(HttpRequestHeaders::kContentLength,
- base::NumberToString(std::size(kData) - 1));
- r->SetExtraRequestHeaders(headers);
- // Quit after hitting the redirect, so can check the headers.
- r->Start();
- d.RunUntilRedirect();
- // Check headers from URLRequestJob.
- EXPECT_EQ(307, r->GetResponseCode());
- EXPECT_EQ(307, r->response_headers()->response_code());
- std::string location;
- ASSERT_TRUE(
- r->response_headers()->EnumerateHeader(nullptr, "Location", &location));
- EXPECT_EQ(redirect_url, GURL(location));
- // Let the request finish.
- r->FollowDeferredRedirect(absl::nullopt /* removed_headers */,
- absl::nullopt /* modified_headers */);
- d.RunUntilComplete();
- EXPECT_EQ(OK, d.request_status());
- EXPECT_EQ(redirect_url, r->url());
- EXPECT_EQ(original_url, r->original_url());
- EXPECT_EQ(2U, r->url_chain().size());
- EXPECT_EQ(1, network_delegate.created_requests());
- EXPECT_EQ(0, network_delegate.destroyed_requests());
- EXPECT_EQ("POST", r->method());
- EXPECT_EQ(kData, d.data_received());
- }
- EXPECT_EQ(1, network_delegate.destroyed_requests());
- }
- // Tests that the network delegate can block and redirect a request to a new
- // URL during OnHeadersReceived.
- TEST_F(URLRequestTestHTTP, NetworkDelegateRedirectRequestOnHeadersReceived) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_proxy_resolution_service(
- CreateFixedProxyResolutionService(
- http_test_server()->host_port_pair().ToString()));
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<BlockingNetworkDelegate>(
- BlockingNetworkDelegate::AUTO_CALLBACK));
- auto context = context_builder->Build();
- network_delegate.set_block_on(BlockingNetworkDelegate::ON_HEADERS_RECEIVED);
- GURL redirect_url("http://does.not.resolve.test/simple.html");
- network_delegate.set_redirect_on_headers_received_url(redirect_url);
- {
- GURL original_url("http://does.not.resolve.test/defaultresponse");
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- d.RunUntilComplete();
- EXPECT_EQ(OK, d.request_status());
- EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
- http_test_server()->host_port_pair()),
- r->proxy_server());
- EXPECT_EQ(OK, d.request_status());
- EXPECT_EQ(redirect_url, r->url());
- EXPECT_EQ(original_url, r->original_url());
- EXPECT_EQ(2U, r->url_chain().size());
- EXPECT_EQ(2, network_delegate.created_requests());
- EXPECT_EQ(0, network_delegate.destroyed_requests());
- }
- EXPECT_EQ(1, network_delegate.destroyed_requests());
- }
- // Tests that the network delegate can synchronously complete OnAuthRequired
- // by taking no action. This indicates that the NetworkDelegate does not want to
- // handle the challenge, and is passing the buck along to the
- // URLRequest::Delegate.
- TEST_F(URLRequestTestHTTP, NetworkDelegateOnAuthRequiredSyncNoAction) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<BlockingNetworkDelegate>(
- BlockingNetworkDelegate::SYNCHRONOUS));
- auto context = context_builder->Build();
- d.set_credentials(AuthCredentials(kUser, kSecret));
- {
- GURL url(http_test_server()->GetURL("/auth-basic"));
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- d.RunUntilComplete();
- EXPECT_EQ(OK, d.request_status());
- EXPECT_EQ(200, r->GetResponseCode());
- EXPECT_TRUE(d.auth_required_called());
- EXPECT_EQ(1, network_delegate.created_requests());
- EXPECT_EQ(0, network_delegate.destroyed_requests());
- }
- EXPECT_EQ(1, network_delegate.destroyed_requests());
- }
- // Tests that NetworkDelegate header overrides from the 401 response do not
- // affect the 200 response. This is a regression test for
- // https://crbug.com/801237.
- TEST_F(URLRequestTestHTTP, NetworkDelegateOverrideHeadersWithAuth) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- d.set_credentials(AuthCredentials(kUser, kSecret));
- default_network_delegate().set_add_header_to_first_response(true);
- {
- GURL url(http_test_server()->GetURL("/auth-basic"));
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- d.RunUntilComplete();
- EXPECT_EQ(OK, d.request_status());
- EXPECT_EQ(200, r->GetResponseCode());
- EXPECT_TRUE(d.auth_required_called());
- EXPECT_FALSE(r->response_headers()->HasHeader("X-Network-Delegate"));
- }
- {
- GURL url(http_test_server()->GetURL("/defaultresponse"));
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- d.RunUntilComplete();
- // Check that set_add_header_to_first_response normally adds a header.
- EXPECT_EQ(OK, d.request_status());
- EXPECT_EQ(200, r->GetResponseCode());
- EXPECT_TRUE(r->response_headers()->HasHeader("X-Network-Delegate"));
- }
- }
- // Tests that we can handle when a network request was canceled while we were
- // waiting for the network delegate.
- // Part 1: Request is cancelled while waiting for OnBeforeURLRequest callback.
- TEST_F(URLRequestTestHTTP, NetworkDelegateCancelWhileWaiting1) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<BlockingNetworkDelegate>(
- BlockingNetworkDelegate::USER_CALLBACK));
- network_delegate.set_block_on(BlockingNetworkDelegate::ON_BEFORE_URL_REQUEST);
- auto context = context_builder->Build();
- {
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- http_test_server()->GetURL("/"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- network_delegate.RunUntilBlocked();
- EXPECT_EQ(BlockingNetworkDelegate::ON_BEFORE_URL_REQUEST,
- network_delegate.stage_blocked_for_callback());
- EXPECT_EQ(0, network_delegate.completed_requests());
- // Cancel before callback.
- r->Cancel();
- // Ensure that network delegate is notified.
- EXPECT_EQ(1, network_delegate.completed_requests());
- EXPECT_EQ(1, network_delegate.canceled_requests());
- EXPECT_EQ(1, network_delegate.created_requests());
- EXPECT_EQ(0, network_delegate.destroyed_requests());
- }
- EXPECT_EQ(1, network_delegate.destroyed_requests());
- }
- // Tests that we can handle when a network request was canceled while we were
- // waiting for the network delegate.
- // Part 2: Request is cancelled while waiting for OnBeforeStartTransaction
- // callback.
- TEST_F(URLRequestTestHTTP, NetworkDelegateCancelWhileWaiting2) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<BlockingNetworkDelegate>(
- BlockingNetworkDelegate::USER_CALLBACK));
- network_delegate.set_block_on(
- BlockingNetworkDelegate::ON_BEFORE_SEND_HEADERS);
- auto context = context_builder->Build();
- {
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- http_test_server()->GetURL("/"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- network_delegate.RunUntilBlocked();
- EXPECT_EQ(BlockingNetworkDelegate::ON_BEFORE_SEND_HEADERS,
- network_delegate.stage_blocked_for_callback());
- EXPECT_EQ(0, network_delegate.completed_requests());
- // Cancel before callback.
- r->Cancel();
- // Ensure that network delegate is notified.
- EXPECT_EQ(1, network_delegate.completed_requests());
- EXPECT_EQ(1, network_delegate.canceled_requests());
- EXPECT_EQ(1, network_delegate.created_requests());
- EXPECT_EQ(0, network_delegate.destroyed_requests());
- }
- EXPECT_EQ(1, network_delegate.destroyed_requests());
- }
- // Tests that we can handle when a network request was canceled while we were
- // waiting for the network delegate.
- // Part 3: Request is cancelled while waiting for OnHeadersReceived callback.
- TEST_F(URLRequestTestHTTP, NetworkDelegateCancelWhileWaiting3) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<BlockingNetworkDelegate>(
- BlockingNetworkDelegate::USER_CALLBACK));
- network_delegate.set_block_on(BlockingNetworkDelegate::ON_HEADERS_RECEIVED);
- auto context = context_builder->Build();
- {
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- http_test_server()->GetURL("/"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- network_delegate.RunUntilBlocked();
- EXPECT_EQ(BlockingNetworkDelegate::ON_HEADERS_RECEIVED,
- network_delegate.stage_blocked_for_callback());
- EXPECT_EQ(0, network_delegate.completed_requests());
- // Cancel before callback.
- r->Cancel();
- // Ensure that network delegate is notified.
- EXPECT_EQ(1, network_delegate.completed_requests());
- EXPECT_EQ(1, network_delegate.canceled_requests());
- EXPECT_EQ(1, network_delegate.created_requests());
- EXPECT_EQ(0, network_delegate.destroyed_requests());
- }
- EXPECT_EQ(1, network_delegate.destroyed_requests());
- }
- namespace {
- std::unique_ptr<test_server::HttpResponse> HandleServerAuthConnect(
- const test_server::HttpRequest& request) {
- if (request.headers.find("Host") == request.headers.end() ||
- request.headers.at("Host") != "www.server-auth.com" ||
- request.method != test_server::METHOD_CONNECT) {
- return nullptr;
- }
- auto http_response = std::make_unique<test_server::BasicHttpResponse>();
- http_response->set_code(HTTP_UNAUTHORIZED);
- http_response->AddCustomHeader("WWW-Authenticate",
- "Basic realm=\"WallyWorld\"");
- return http_response;
- }
- } // namespace
- // In this unit test, we're using the EmbeddedTestServer as a proxy server and
- // issuing a CONNECT request with the magic host name "www.server-auth.com".
- // The EmbeddedTestServer will return a 401 response, which we should balk at.
- TEST_F(URLRequestTestHTTP, UnexpectedServerAuthTest) {
- http_test_server()->RegisterRequestHandler(
- base::BindRepeating(&HandleServerAuthConnect));
- ASSERT_TRUE(http_test_server()->Start());
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_proxy_resolution_service(
- CreateFixedProxyResolutionService(
- http_test_server()->host_port_pair().ToString()));
- auto context = context_builder->Build();
- TestDelegate d;
- {
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- GURL("https://www.server-auth.com/"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- // The proxy server should be set before failure.
- EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
- http_test_server()->host_port_pair()),
- r->proxy_server());
- EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, d.request_status());
- }
- }
- TEST_F(URLRequestTestHTTP, GetTest_NoCache) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- {
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- http_test_server()->GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_NE(0, d.bytes_received());
- EXPECT_EQ(http_test_server()->host_port_pair().host(),
- r->GetResponseRemoteEndpoint().ToStringWithoutPort());
- EXPECT_EQ(http_test_server()->host_port_pair().port(),
- r->GetResponseRemoteEndpoint().port());
- // TODO(eroman): Add back the NetLog tests...
- }
- }
- TEST_F(URLRequestTestHTTP, GetTest) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- {
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- http_test_server()->GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_NE(0, d.bytes_received());
- EXPECT_EQ(http_test_server()->host_port_pair().host(),
- r->GetResponseRemoteEndpoint().ToStringWithoutPort());
- EXPECT_EQ(http_test_server()->host_port_pair().port(),
- r->GetResponseRemoteEndpoint().port());
- }
- }
- TEST_F(URLRequestTestHTTP, GetTestLoadTiming) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- {
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- http_test_server()->GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- LoadTimingInfo load_timing_info;
- r->GetLoadTimingInfo(&load_timing_info);
- TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_NE(0, d.bytes_received());
- EXPECT_EQ(http_test_server()->host_port_pair().host(),
- r->GetResponseRemoteEndpoint().ToStringWithoutPort());
- EXPECT_EQ(http_test_server()->host_port_pair().port(),
- r->GetResponseRemoteEndpoint().port());
- }
- }
- namespace {
- // Sends the correct Content-Length matching the compressed length.
- const char kZippedContentLengthCompressed[] = "C";
- // Sends an incorrect Content-Length matching the uncompressed length.
- const char kZippedContentLengthUncompressed[] = "U";
- // Sends an incorrect Content-Length shorter than the compressed length.
- const char kZippedContentLengthShort[] = "S";
- // Sends an incorrect Content-Length between the compressed and uncompressed
- // lengths.
- const char kZippedContentLengthMedium[] = "M";
- // Sends an incorrect Content-Length larger than both compressed and
- // uncompressed lengths.
- const char kZippedContentLengthLong[] = "L";
- // Sends |compressed_content| which, when decoded with deflate, should have
- // length |uncompressed_length|. The Content-Length header will be sent based on
- // which of the constants above is sent in the query string.
- std::unique_ptr<test_server::HttpResponse> HandleZippedRequest(
- const std::string& compressed_content,
- size_t uncompressed_length,
- const test_server::HttpRequest& request) {
- GURL url = request.GetURL();
- if (url.path_piece() != "/compressedfiles/BullRunSpeech.txt")
- return nullptr;
- size_t length;
- if (url.query_piece() == kZippedContentLengthCompressed) {
- length = compressed_content.size();
- } else if (url.query_piece() == kZippedContentLengthUncompressed) {
- length = uncompressed_length;
- } else if (url.query_piece() == kZippedContentLengthShort) {
- length = compressed_content.size() / 2;
- } else if (url.query_piece() == kZippedContentLengthMedium) {
- length = (compressed_content.size() + uncompressed_length) / 2;
- } else if (url.query_piece() == kZippedContentLengthLong) {
- length = compressed_content.size() + uncompressed_length;
- } else {
- return nullptr;
- }
- std::string headers = "HTTP/1.1 200 OK\r\n";
- headers += "Content-Encoding: deflate\r\n";
- base::StringAppendF(&headers, "Content-Length: %zu\r\n", length);
- return std::make_unique<test_server::RawHttpResponse>(headers,
- compressed_content);
- }
- } // namespace
- TEST_F(URLRequestTestHTTP, GetZippedTest) {
- base::FilePath file_path;
- base::PathService::Get(base::DIR_SOURCE_ROOT, &file_path);
- file_path = file_path.Append(kTestFilePath);
- std::string expected_content, compressed_content;
- ASSERT_TRUE(base::ReadFileToString(
- file_path.Append(FILE_PATH_LITERAL("BullRunSpeech.txt")),
- &expected_content));
- // This file is the output of the Python zlib.compress function on
- // |expected_content|.
- ASSERT_TRUE(base::ReadFileToString(
- file_path.Append(FILE_PATH_LITERAL("BullRunSpeech.txt.deflate")),
- &compressed_content));
- http_test_server()->RegisterRequestHandler(base::BindRepeating(
- &HandleZippedRequest, compressed_content, expected_content.size()));
- ASSERT_TRUE(http_test_server()->Start());
- static const struct {
- const char* parameter;
- bool expect_success;
- } kTests[] = {
- // Sending the compressed Content-Length is correct.
- {kZippedContentLengthCompressed, true},
- // Sending the uncompressed Content-Length is incorrect, but we accept it
- // to workaround some broken servers.
- {kZippedContentLengthUncompressed, true},
- // Sending too long of Content-Length is rejected.
- {kZippedContentLengthLong, false},
- {kZippedContentLengthMedium, false},
- // Sending too short of Content-Length successfully fetches a response
- // body, but it will be truncated.
- {kZippedContentLengthShort, true},
- };
- for (const auto& test : kTests) {
- SCOPED_TRACE(test.parameter);
- TestDelegate d;
- std::string test_file = base::StringPrintf(
- "/compressedfiles/BullRunSpeech.txt?%s", test.parameter);
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_network_delegate(
- std::make_unique<TestNetworkDelegate>());
- auto context = context_builder->Build();
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- http_test_server()->GetURL(test_file), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_FALSE(d.received_data_before_response());
- VLOG(1) << " Received " << d.bytes_received() << " bytes"
- << " error = " << d.request_status();
- if (test.expect_success) {
- EXPECT_EQ(OK, d.request_status())
- << " Parameter = \"" << test_file << "\"";
- if (strcmp(test.parameter, kZippedContentLengthShort) == 0) {
- // When content length is smaller than both compressed length and
- // uncompressed length, HttpStreamParser might not read the full
- // response body.
- EXPECT_EQ(expected_content.substr(0, d.data_received().size()),
- d.data_received());
- } else {
- EXPECT_EQ(expected_content, d.data_received());
- }
- } else {
- EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, d.request_status())
- << " Parameter = \"" << test_file << "\"";
- }
- }
- }
- TEST_F(URLRequestTestHTTP, RedirectLoadTiming) {
- ASSERT_TRUE(http_test_server()->Start());
- GURL destination_url = http_test_server()->GetURL("/");
- GURL original_url =
- http_test_server()->GetURL("/server-redirect?" + destination_url.spec());
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(1, d.received_redirect_count());
- EXPECT_EQ(destination_url, req->url());
- EXPECT_EQ(original_url, req->original_url());
- ASSERT_EQ(2U, req->url_chain().size());
- EXPECT_EQ(original_url, req->url_chain()[0]);
- EXPECT_EQ(destination_url, req->url_chain()[1]);
- LoadTimingInfo load_timing_info_before_redirect;
- EXPECT_TRUE(default_network_delegate().GetLoadTimingInfoBeforeRedirect(
- &load_timing_info_before_redirect));
- TestLoadTimingNotReused(load_timing_info_before_redirect,
- CONNECT_TIMING_HAS_DNS_TIMES);
- LoadTimingInfo load_timing_info;
- req->GetLoadTimingInfo(&load_timing_info);
- TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
- // Check that a new socket was used on redirect, since the server does not
- // supposed keep-alive sockets, and that the times before the redirect are
- // before the ones recorded for the second request.
- EXPECT_NE(load_timing_info_before_redirect.socket_log_id,
- load_timing_info.socket_log_id);
- EXPECT_LE(load_timing_info_before_redirect.receive_headers_end,
- load_timing_info.connect_timing.connect_start);
- }
- TEST_F(URLRequestTestHTTP, MultipleRedirectTest) {
- ASSERT_TRUE(http_test_server()->Start());
- GURL destination_url = http_test_server()->GetURL("/");
- GURL middle_redirect_url =
- http_test_server()->GetURL("/server-redirect?" + destination_url.spec());
- GURL original_url = http_test_server()->GetURL("/server-redirect?" +
- middle_redirect_url.spec());
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(2, d.received_redirect_count());
- EXPECT_EQ(destination_url, req->url());
- EXPECT_EQ(original_url, req->original_url());
- ASSERT_EQ(3U, req->url_chain().size());
- EXPECT_EQ(original_url, req->url_chain()[0]);
- EXPECT_EQ(middle_redirect_url, req->url_chain()[1]);
- EXPECT_EQ(destination_url, req->url_chain()[2]);
- }
- // This is a regression test for https://crbug.com/942073.
- TEST_F(URLRequestTestHTTP, RedirectEscaping) {
- ASSERT_TRUE(http_test_server()->Start());
- // Assemble the destination URL as a string so it is not escaped by GURL.
- GURL destination_base = http_test_server()->GetURL("/defaultresponse");
- // Add a URL fragment of U+2603 unescaped, U+2603 escaped, and then a UTF-8
- // encoding error.
- std::string destination_url =
- destination_base.spec() + "#\xE2\x98\x83_%E2%98%83_\xE0\xE0";
- // Redirect resolution should percent-escape bytes and preserve the UTF-8
- // error at the end.
- std::string destination_escaped =
- destination_base.spec() + "#%E2%98%83_%E2%98%83_%E0%E0";
- GURL original_url = http_test_server()->GetURL(
- "/server-redirect?" +
- base::EscapeQueryParamValue(destination_url, false));
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(1, d.received_redirect_count());
- EXPECT_EQ(destination_escaped, req->url().spec());
- EXPECT_EQ(original_url, req->original_url());
- ASSERT_EQ(2U, req->url_chain().size());
- EXPECT_EQ(original_url, req->url_chain()[0]);
- EXPECT_EQ(destination_escaped, req->url_chain()[1].spec());
- }
- // First and second pieces of information logged by delegates to URLRequests.
- const char kFirstDelegateInfo[] = "Wonderful delegate";
- const char16_t kFirstDelegateInfo16[] = u"Wonderful delegate";
- const char kSecondDelegateInfo[] = "Exciting delegate";
- const char16_t kSecondDelegateInfo16[] = u"Exciting delegate";
- // Logs delegate information to a URLRequest. The first string is logged
- // synchronously on Start(), using DELEGATE_INFO_DEBUG_ONLY. The second is
- // logged asynchronously, using DELEGATE_INFO_DISPLAY_TO_USER. Then
- // another asynchronous call is used to clear the delegate information
- // before calling a callback. The object then deletes itself.
- class AsyncDelegateLogger : public base::RefCounted<AsyncDelegateLogger> {
- public:
- using Callback = base::OnceCallback<void()>;
- AsyncDelegateLogger(const AsyncDelegateLogger&) = delete;
- AsyncDelegateLogger& operator=(const AsyncDelegateLogger&) = delete;
- // Each time delegate information is added to the URLRequest, the resulting
- // load state is checked. The expected load state after each request is
- // passed in as an argument.
- static void Run(URLRequest* url_request,
- LoadState expected_first_load_state,
- LoadState expected_second_load_state,
- LoadState expected_third_load_state,
- Callback callback) {
- // base::MakeRefCounted<AsyncDelegateLogger> is unavailable here, since the
- // constructor of AsyncDelegateLogger is private.
- auto logger = base::WrapRefCounted(new AsyncDelegateLogger(
- url_request, expected_first_load_state, expected_second_load_state,
- expected_third_load_state, std::move(callback)));
- logger->Start();
- }
- // Checks that the log entries, starting with log_position, contain the
- // DELEGATE_INFO NetLog events that an AsyncDelegateLogger should have
- // recorded. Returns the index of entry after the expected number of
- // events this logged, or entries.size() if there aren't enough entries.
- static size_t CheckDelegateInfo(const std::vector<NetLogEntry>& entries,
- size_t log_position) {
- // There should be 4 DELEGATE_INFO events: Two begins and two ends.
- if (log_position + 3 >= entries.size()) {
- ADD_FAILURE() << "Not enough log entries";
- return entries.size();
- }
- std::string delegate_info;
- EXPECT_EQ(NetLogEventType::DELEGATE_INFO, entries[log_position].type);
- EXPECT_EQ(NetLogEventPhase::BEGIN, entries[log_position].phase);
- EXPECT_EQ(
- kFirstDelegateInfo,
- GetStringValueFromParams(entries[log_position], "delegate_blocked_by"));
- ++log_position;
- EXPECT_EQ(NetLogEventType::DELEGATE_INFO, entries[log_position].type);
- EXPECT_EQ(NetLogEventPhase::END, entries[log_position].phase);
- ++log_position;
- EXPECT_EQ(NetLogEventType::DELEGATE_INFO, entries[log_position].type);
- EXPECT_EQ(NetLogEventPhase::BEGIN, entries[log_position].phase);
- EXPECT_EQ(
- kSecondDelegateInfo,
- GetStringValueFromParams(entries[log_position], "delegate_blocked_by"));
- ++log_position;
- EXPECT_EQ(NetLogEventType::DELEGATE_INFO, entries[log_position].type);
- EXPECT_EQ(NetLogEventPhase::END, entries[log_position].phase);
- return log_position + 1;
- }
- private:
- friend class base::RefCounted<AsyncDelegateLogger>;
- AsyncDelegateLogger(URLRequest* url_request,
- LoadState expected_first_load_state,
- LoadState expected_second_load_state,
- LoadState expected_third_load_state,
- Callback callback)
- : url_request_(url_request),
- expected_first_load_state_(expected_first_load_state),
- expected_second_load_state_(expected_second_load_state),
- expected_third_load_state_(expected_third_load_state),
- callback_(std::move(callback)) {}
- ~AsyncDelegateLogger() = default;
- void Start() {
- url_request_->LogBlockedBy(kFirstDelegateInfo);
- LoadStateWithParam load_state = url_request_->GetLoadState();
- EXPECT_EQ(expected_first_load_state_, load_state.state);
- EXPECT_NE(kFirstDelegateInfo16, load_state.param);
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(&AsyncDelegateLogger::LogSecondDelegate, this));
- }
- void LogSecondDelegate() {
- url_request_->LogAndReportBlockedBy(kSecondDelegateInfo);
- LoadStateWithParam load_state = url_request_->GetLoadState();
- EXPECT_EQ(expected_second_load_state_, load_state.state);
- if (expected_second_load_state_ == LOAD_STATE_WAITING_FOR_DELEGATE) {
- EXPECT_EQ(kSecondDelegateInfo16, load_state.param);
- } else {
- EXPECT_NE(kSecondDelegateInfo16, load_state.param);
- }
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&AsyncDelegateLogger::LogComplete, this));
- }
- void LogComplete() {
- url_request_->LogUnblocked();
- LoadStateWithParam load_state = url_request_->GetLoadState();
- EXPECT_EQ(expected_third_load_state_, load_state.state);
- if (expected_second_load_state_ == LOAD_STATE_WAITING_FOR_DELEGATE)
- EXPECT_EQ(std::u16string(), load_state.param);
- std::move(callback_).Run();
- }
- raw_ptr<URLRequest> url_request_;
- const int expected_first_load_state_;
- const int expected_second_load_state_;
- const int expected_third_load_state_;
- Callback callback_;
- };
- // NetworkDelegate that logs delegate information before a request is started,
- // before headers are sent, when headers are read, and when auth information
- // is requested. Uses AsyncDelegateLogger.
- class AsyncLoggingNetworkDelegate : public TestNetworkDelegate {
- public:
- AsyncLoggingNetworkDelegate() = default;
- AsyncLoggingNetworkDelegate(const AsyncLoggingNetworkDelegate&) = delete;
- AsyncLoggingNetworkDelegate& operator=(const AsyncLoggingNetworkDelegate&) =
- delete;
- ~AsyncLoggingNetworkDelegate() override = default;
- // NetworkDelegate implementation.
- int OnBeforeURLRequest(URLRequest* request,
- CompletionOnceCallback callback,
- GURL* new_url) override {
- // TestNetworkDelegate always completes synchronously.
- CHECK_NE(ERR_IO_PENDING, TestNetworkDelegate::OnBeforeURLRequest(
- request, base::NullCallback(), new_url));
- return RunCallbackAsynchronously(request, std::move(callback));
- }
- int OnBeforeStartTransaction(
- URLRequest* request,
- const HttpRequestHeaders& headers,
- OnBeforeStartTransactionCallback callback) override {
- // TestNetworkDelegate always completes synchronously.
- CHECK_NE(ERR_IO_PENDING, TestNetworkDelegate::OnBeforeStartTransaction(
- request, headers, base::NullCallback()));
- return RunCallbackAsynchronously(
- request, base::BindOnce(
- [](OnBeforeStartTransactionCallback callback, int result) {
- std::move(callback).Run(result, absl::nullopt);
- },
- std::move(callback)));
- }
- int OnHeadersReceived(
- URLRequest* request,
- CompletionOnceCallback callback,
- const HttpResponseHeaders* original_response_headers,
- scoped_refptr<HttpResponseHeaders>* override_response_headers,
- const IPEndPoint& endpoint,
- absl::optional<GURL>* preserve_fragment_on_redirect_url) override {
- // TestNetworkDelegate always completes synchronously.
- CHECK_NE(ERR_IO_PENDING,
- TestNetworkDelegate::OnHeadersReceived(
- request, base::NullCallback(), original_response_headers,
- override_response_headers, endpoint,
- preserve_fragment_on_redirect_url));
- return RunCallbackAsynchronously(request, std::move(callback));
- }
- private:
- static int RunCallbackAsynchronously(URLRequest* request,
- CompletionOnceCallback callback) {
- AsyncDelegateLogger::Run(request, LOAD_STATE_WAITING_FOR_DELEGATE,
- LOAD_STATE_WAITING_FOR_DELEGATE,
- LOAD_STATE_WAITING_FOR_DELEGATE,
- base::BindOnce(std::move(callback), OK));
- return ERR_IO_PENDING;
- }
- };
- // URLRequest::Delegate that logs delegate information when the headers
- // are received, when each read completes, and during redirects. Uses
- // AsyncDelegateLogger. Can optionally cancel a request in any phase.
- //
- // Inherits from TestDelegate to reuse the TestDelegate code to handle
- // advancing to the next step in most cases, as well as cancellation.
- class AsyncLoggingUrlRequestDelegate : public TestDelegate {
- public:
- enum CancelStage {
- NO_CANCEL = 0,
- CANCEL_ON_RECEIVED_REDIRECT,
- CANCEL_ON_RESPONSE_STARTED,
- CANCEL_ON_READ_COMPLETED
- };
- explicit AsyncLoggingUrlRequestDelegate(CancelStage cancel_stage)
- : cancel_stage_(cancel_stage) {
- if (cancel_stage == CANCEL_ON_RECEIVED_REDIRECT)
- set_cancel_in_received_redirect(true);
- else if (cancel_stage == CANCEL_ON_RESPONSE_STARTED)
- set_cancel_in_response_started(true);
- else if (cancel_stage == CANCEL_ON_READ_COMPLETED)
- set_cancel_in_received_data(true);
- }
- AsyncLoggingUrlRequestDelegate(const AsyncLoggingUrlRequestDelegate&) =
- delete;
- AsyncLoggingUrlRequestDelegate& operator=(
- const AsyncLoggingUrlRequestDelegate&) = delete;
- ~AsyncLoggingUrlRequestDelegate() override = default;
- // URLRequest::Delegate implementation:
- void OnReceivedRedirect(URLRequest* request,
- const RedirectInfo& redirect_info,
- bool* defer_redirect) override {
- *defer_redirect = true;
- AsyncDelegateLogger::Run(
- request, LOAD_STATE_WAITING_FOR_DELEGATE,
- LOAD_STATE_WAITING_FOR_DELEGATE, LOAD_STATE_WAITING_FOR_DELEGATE,
- base::BindOnce(
- &AsyncLoggingUrlRequestDelegate::OnReceivedRedirectLoggingComplete,
- base::Unretained(this), request, redirect_info));
- }
- void OnResponseStarted(URLRequest* request, int net_error) override {
- AsyncDelegateLogger::Run(
- request, LOAD_STATE_WAITING_FOR_DELEGATE,
- LOAD_STATE_WAITING_FOR_DELEGATE, LOAD_STATE_WAITING_FOR_DELEGATE,
- base::BindOnce(
- &AsyncLoggingUrlRequestDelegate::OnResponseStartedLoggingComplete,
- base::Unretained(this), request, net_error));
- }
- void OnReadCompleted(URLRequest* request, int bytes_read) override {
- AsyncDelegateLogger::Run(
- request, LOAD_STATE_IDLE, LOAD_STATE_IDLE, LOAD_STATE_IDLE,
- base::BindOnce(
- &AsyncLoggingUrlRequestDelegate::AfterReadCompletedLoggingComplete,
- base::Unretained(this), request, bytes_read));
- }
- private:
- void OnReceivedRedirectLoggingComplete(URLRequest* request,
- const RedirectInfo& redirect_info) {
- bool defer_redirect = false;
- TestDelegate::OnReceivedRedirect(request, redirect_info, &defer_redirect);
- // FollowDeferredRedirect should not be called after cancellation.
- if (cancel_stage_ == CANCEL_ON_RECEIVED_REDIRECT)
- return;
- if (!defer_redirect) {
- request->FollowDeferredRedirect(absl::nullopt /* removed_headers */,
- absl::nullopt /* modified_headers */);
- }
- }
- void OnResponseStartedLoggingComplete(URLRequest* request, int net_error) {
- // The parent class continues the request.
- TestDelegate::OnResponseStarted(request, net_error);
- }
- void AfterReadCompletedLoggingComplete(URLRequest* request, int bytes_read) {
- // The parent class continues the request.
- TestDelegate::OnReadCompleted(request, bytes_read);
- }
- const CancelStage cancel_stage_;
- };
- // Tests handling of delegate info before a request starts.
- TEST_F(URLRequestTestHTTP, DelegateInfoBeforeStart) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate request_delegate;
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_net_log(NetLog::Get());
- auto context = context_builder->Build();
- {
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- http_test_server()->GetURL("/defaultresponse"), DEFAULT_PRIORITY,
- &request_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
- LoadStateWithParam load_state = r->GetLoadState();
- EXPECT_EQ(LOAD_STATE_IDLE, load_state.state);
- EXPECT_EQ(std::u16string(), load_state.param);
- AsyncDelegateLogger::Run(
- r.get(), LOAD_STATE_WAITING_FOR_DELEGATE,
- LOAD_STATE_WAITING_FOR_DELEGATE, LOAD_STATE_IDLE,
- base::BindOnce(&URLRequest::Start, base::Unretained(r.get())));
- request_delegate.RunUntilComplete();
- EXPECT_EQ(200, r->GetResponseCode());
- EXPECT_EQ(OK, request_delegate.request_status());
- }
- auto entries = net_log_observer_.GetEntries();
- size_t log_position = ExpectLogContainsSomewhereAfter(
- entries, 0, NetLogEventType::DELEGATE_INFO, NetLogEventPhase::BEGIN);
- log_position = AsyncDelegateLogger::CheckDelegateInfo(entries, log_position);
- // Nothing else should add any delegate info to the request.
- EXPECT_FALSE(LogContainsEntryWithTypeAfter(entries, log_position + 1,
- NetLogEventType::DELEGATE_INFO));
- }
- // Tests handling of delegate info from a network delegate.
- TEST_F(URLRequestTestHTTP, NetworkDelegateInfo) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate request_delegate;
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<AsyncLoggingNetworkDelegate>());
- context_builder->set_net_log(NetLog::Get());
- auto context = context_builder->Build();
- {
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- http_test_server()->GetURL("/simple.html"), DEFAULT_PRIORITY,
- &request_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
- LoadStateWithParam load_state = r->GetLoadState();
- EXPECT_EQ(LOAD_STATE_IDLE, load_state.state);
- EXPECT_EQ(std::u16string(), load_state.param);
- r->Start();
- request_delegate.RunUntilComplete();
- EXPECT_EQ(200, r->GetResponseCode());
- EXPECT_EQ(OK, request_delegate.request_status());
- EXPECT_EQ(1, network_delegate.created_requests());
- EXPECT_EQ(0, network_delegate.destroyed_requests());
- }
- EXPECT_EQ(1, network_delegate.destroyed_requests());
- size_t log_position = 0;
- auto entries = net_log_observer_.GetEntries();
- static const NetLogEventType kExpectedEvents[] = {
- NetLogEventType::NETWORK_DELEGATE_BEFORE_URL_REQUEST,
- NetLogEventType::NETWORK_DELEGATE_BEFORE_START_TRANSACTION,
- NetLogEventType::NETWORK_DELEGATE_HEADERS_RECEIVED,
- };
- for (NetLogEventType event : kExpectedEvents) {
- SCOPED_TRACE(NetLogEventTypeToString(event));
- log_position = ExpectLogContainsSomewhereAfter(
- entries, log_position + 1, event, NetLogEventPhase::BEGIN);
- log_position =
- AsyncDelegateLogger::CheckDelegateInfo(entries, log_position + 1);
- ASSERT_LT(log_position, entries.size());
- EXPECT_EQ(event, entries[log_position].type);
- EXPECT_EQ(NetLogEventPhase::END, entries[log_position].phase);
- }
- EXPECT_FALSE(LogContainsEntryWithTypeAfter(entries, log_position + 1,
- NetLogEventType::DELEGATE_INFO));
- }
- // Tests handling of delegate info from a network delegate in the case of an
- // HTTP redirect.
- TEST_F(URLRequestTestHTTP, NetworkDelegateInfoRedirect) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate request_delegate;
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<AsyncLoggingNetworkDelegate>());
- auto context = context_builder->Build();
- {
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- http_test_server()->GetURL("/server-redirect?simple.html"),
- DEFAULT_PRIORITY, &request_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
- LoadStateWithParam load_state = r->GetLoadState();
- EXPECT_EQ(LOAD_STATE_IDLE, load_state.state);
- EXPECT_EQ(std::u16string(), load_state.param);
- r->Start();
- request_delegate.RunUntilComplete();
- EXPECT_EQ(200, r->GetResponseCode());
- EXPECT_EQ(OK, request_delegate.request_status());
- EXPECT_EQ(2, network_delegate.created_requests());
- EXPECT_EQ(0, network_delegate.destroyed_requests());
- }
- EXPECT_EQ(1, network_delegate.destroyed_requests());
- size_t log_position = 0;
- auto entries = net_log_observer_.GetEntries();
- static const NetLogEventType kExpectedEvents[] = {
- NetLogEventType::NETWORK_DELEGATE_BEFORE_URL_REQUEST,
- NetLogEventType::NETWORK_DELEGATE_BEFORE_START_TRANSACTION,
- NetLogEventType::NETWORK_DELEGATE_HEADERS_RECEIVED,
- };
- for (NetLogEventType event : kExpectedEvents) {
- SCOPED_TRACE(NetLogEventTypeToString(event));
- log_position = ExpectLogContainsSomewhereAfter(
- entries, log_position + 1, event, NetLogEventPhase::BEGIN);
- log_position =
- AsyncDelegateLogger::CheckDelegateInfo(entries, log_position + 1);
- ASSERT_LT(log_position, entries.size());
- EXPECT_EQ(event, entries[log_position].type);
- EXPECT_EQ(NetLogEventPhase::END, entries[log_position].phase);
- }
- // The URLRequest::Delegate then gets informed about the redirect.
- log_position = ExpectLogContainsSomewhereAfter(
- entries, log_position + 1,
- NetLogEventType::URL_REQUEST_DELEGATE_RECEIVED_REDIRECT,
- NetLogEventPhase::BEGIN);
- // The NetworkDelegate logged information in the same three events as before.
- for (NetLogEventType event : kExpectedEvents) {
- SCOPED_TRACE(NetLogEventTypeToString(event));
- log_position = ExpectLogContainsSomewhereAfter(
- entries, log_position + 1, event, NetLogEventPhase::BEGIN);
- log_position =
- AsyncDelegateLogger::CheckDelegateInfo(entries, log_position + 1);
- ASSERT_LT(log_position, entries.size());
- EXPECT_EQ(event, entries[log_position].type);
- EXPECT_EQ(NetLogEventPhase::END, entries[log_position].phase);
- }
- EXPECT_FALSE(LogContainsEntryWithTypeAfter(entries, log_position + 1,
- NetLogEventType::DELEGATE_INFO));
- }
- // Tests handling of delegate info from a URLRequest::Delegate.
- TEST_F(URLRequestTestHTTP, URLRequestDelegateInfo) {
- ASSERT_TRUE(http_test_server()->Start());
- AsyncLoggingUrlRequestDelegate request_delegate(
- AsyncLoggingUrlRequestDelegate::NO_CANCEL);
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_net_log(NetLog::Get());
- auto context = context_builder->Build();
- {
- // A chunked response with delays between chunks is used to make sure that
- // attempts by the URLRequest delegate to log information while reading the
- // body are ignored. Since they are ignored, this test is robust against
- // the possibility of multiple reads being combined in the unlikely event
- // that it occurs.
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- http_test_server()->GetURL("/chunked?waitBetweenChunks=20"),
- DEFAULT_PRIORITY, &request_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
- LoadStateWithParam load_state = r->GetLoadState();
- r->Start();
- request_delegate.RunUntilComplete();
- EXPECT_EQ(200, r->GetResponseCode());
- EXPECT_EQ(OK, request_delegate.request_status());
- }
- auto entries = net_log_observer_.GetEntries();
- size_t log_position = 0;
- // The delegate info should only have been logged on header complete. Other
- // times it should silently be ignored.
- log_position = ExpectLogContainsSomewhereAfter(
- entries, log_position + 1,
- NetLogEventType::URL_REQUEST_DELEGATE_RESPONSE_STARTED,
- NetLogEventPhase::BEGIN);
- log_position =
- AsyncDelegateLogger::CheckDelegateInfo(entries, log_position + 1);
- ASSERT_LT(log_position, entries.size());
- EXPECT_EQ(NetLogEventType::URL_REQUEST_DELEGATE_RESPONSE_STARTED,
- entries[log_position].type);
- EXPECT_EQ(NetLogEventPhase::END, entries[log_position].phase);
- EXPECT_FALSE(LogContainsEntryWithTypeAfter(entries, log_position + 1,
- NetLogEventType::DELEGATE_INFO));
- EXPECT_FALSE(LogContainsEntryWithTypeAfter(
- entries, log_position + 1,
- NetLogEventType::URL_REQUEST_DELEGATE_RESPONSE_STARTED));
- }
- // Tests handling of delegate info from a URLRequest::Delegate in the case of
- // an HTTP redirect.
- TEST_F(URLRequestTestHTTP, URLRequestDelegateInfoOnRedirect) {
- ASSERT_TRUE(http_test_server()->Start());
- AsyncLoggingUrlRequestDelegate request_delegate(
- AsyncLoggingUrlRequestDelegate::NO_CANCEL);
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_net_log(NetLog::Get());
- auto context = context_builder->Build();
- {
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- http_test_server()->GetURL("/server-redirect?simple.html"),
- DEFAULT_PRIORITY, &request_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
- LoadStateWithParam load_state = r->GetLoadState();
- r->Start();
- request_delegate.RunUntilComplete();
- EXPECT_EQ(200, r->GetResponseCode());
- EXPECT_EQ(OK, request_delegate.request_status());
- }
- auto entries = net_log_observer_.GetEntries();
- // Delegate info should only have been logged in OnReceivedRedirect and
- // OnResponseStarted.
- size_t log_position = 0;
- static const NetLogEventType kExpectedEvents[] = {
- NetLogEventType::URL_REQUEST_DELEGATE_RECEIVED_REDIRECT,
- NetLogEventType::URL_REQUEST_DELEGATE_RESPONSE_STARTED,
- };
- for (NetLogEventType event : kExpectedEvents) {
- SCOPED_TRACE(NetLogEventTypeToString(event));
- log_position = ExpectLogContainsSomewhereAfter(entries, log_position, event,
- NetLogEventPhase::BEGIN);
- log_position =
- AsyncDelegateLogger::CheckDelegateInfo(entries, log_position + 1);
- ASSERT_LT(log_position, entries.size());
- EXPECT_EQ(event, entries[log_position].type);
- EXPECT_EQ(NetLogEventPhase::END, entries[log_position].phase);
- }
- EXPECT_FALSE(LogContainsEntryWithTypeAfter(entries, log_position + 1,
- NetLogEventType::DELEGATE_INFO));
- }
- // Tests handling of delegate info from a URLRequest::Delegate in the case of
- // an HTTP redirect, with cancellation at various points.
- TEST_F(URLRequestTestHTTP, URLRequestDelegateOnRedirectCancelled) {
- ASSERT_TRUE(http_test_server()->Start());
- const AsyncLoggingUrlRequestDelegate::CancelStage kCancelStages[] = {
- AsyncLoggingUrlRequestDelegate::CANCEL_ON_RECEIVED_REDIRECT,
- AsyncLoggingUrlRequestDelegate::CANCEL_ON_RESPONSE_STARTED,
- AsyncLoggingUrlRequestDelegate::CANCEL_ON_READ_COMPLETED,
- };
- for (auto cancel_stage : kCancelStages) {
- AsyncLoggingUrlRequestDelegate request_delegate(cancel_stage);
- RecordingNetLogObserver net_log_observer;
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_net_log(NetLog::Get());
- auto context = context_builder->Build();
- {
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- http_test_server()->GetURL("/server-redirect?simple.html"),
- DEFAULT_PRIORITY, &request_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
- LoadStateWithParam load_state = r->GetLoadState();
- r->Start();
- request_delegate.RunUntilComplete();
- EXPECT_EQ(ERR_ABORTED, request_delegate.request_status());
- // Spin the message loop to run AsyncDelegateLogger task(s) posted after
- // the |request_delegate| completion task.
- base::RunLoop().RunUntilIdle();
- }
- auto entries = net_log_observer.GetEntries();
- // Delegate info is always logged in both OnReceivedRedirect and
- // OnResponseStarted. In the CANCEL_ON_RECEIVED_REDIRECT, the
- // OnResponseStarted delegate call is after cancellation, but logging is
- // still currently supported in that call.
- size_t log_position = 0;
- static const NetLogEventType kExpectedEvents[] = {
- NetLogEventType::URL_REQUEST_DELEGATE_RECEIVED_REDIRECT,
- NetLogEventType::URL_REQUEST_DELEGATE_RESPONSE_STARTED,
- };
- for (NetLogEventType event : kExpectedEvents) {
- SCOPED_TRACE(NetLogEventTypeToString(event));
- log_position = ExpectLogContainsSomewhereAfter(
- entries, log_position, event, NetLogEventPhase::BEGIN);
- log_position =
- AsyncDelegateLogger::CheckDelegateInfo(entries, log_position + 1);
- ASSERT_LT(log_position, entries.size());
- EXPECT_EQ(event, entries[log_position].type);
- EXPECT_EQ(NetLogEventPhase::END, entries[log_position].phase);
- }
- EXPECT_FALSE(LogContainsEntryWithTypeAfter(entries, log_position + 1,
- NetLogEventType::DELEGATE_INFO));
- }
- }
- namespace {
- const char kExtraHeader[] = "Allow-Snafu";
- const char kExtraValue[] = "fubar";
- class RedirectWithAdditionalHeadersDelegate : public TestDelegate {
- void OnReceivedRedirect(URLRequest* request,
- const RedirectInfo& redirect_info,
- bool* defer_redirect) override {
- TestDelegate::OnReceivedRedirect(request, redirect_info, defer_redirect);
- request->SetExtraRequestHeaderByName(kExtraHeader, kExtraValue, false);
- }
- };
- } // namespace
- TEST_F(URLRequestTestHTTP, RedirectWithAdditionalHeadersTest) {
- ASSERT_TRUE(http_test_server()->Start());
- GURL destination_url =
- http_test_server()->GetURL("/echoheader?" + std::string(kExtraHeader));
- GURL original_url =
- http_test_server()->GetURL("/server-redirect?" + destination_url.spec());
- RedirectWithAdditionalHeadersDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- std::string value;
- const HttpRequestHeaders& headers = req->extra_request_headers();
- EXPECT_TRUE(headers.GetHeader(kExtraHeader, &value));
- EXPECT_EQ(kExtraValue, value);
- EXPECT_FALSE(req->is_pending());
- EXPECT_FALSE(req->is_redirecting());
- EXPECT_EQ(kExtraValue, d.data_received());
- }
- namespace {
- const char kExtraHeaderToRemove[] = "To-Be-Removed";
- class RedirectWithHeaderRemovalDelegate : public TestDelegate {
- void OnReceivedRedirect(URLRequest* request,
- const RedirectInfo& redirect_info,
- bool* defer_redirect) override {
- TestDelegate::OnReceivedRedirect(request, redirect_info, defer_redirect);
- request->RemoveRequestHeaderByName(kExtraHeaderToRemove);
- }
- };
- } // namespace
- TEST_F(URLRequestTestHTTP, RedirectWithHeaderRemovalTest) {
- ASSERT_TRUE(http_test_server()->Start());
- GURL destination_url = http_test_server()->GetURL(
- "/echoheader?" + std::string(kExtraHeaderToRemove));
- GURL original_url =
- http_test_server()->GetURL("/server-redirect?" + destination_url.spec());
- RedirectWithHeaderRemovalDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->SetExtraRequestHeaderByName(kExtraHeaderToRemove, "dummy", false);
- req->Start();
- d.RunUntilComplete();
- std::string value;
- const HttpRequestHeaders& headers = req->extra_request_headers();
- EXPECT_FALSE(headers.GetHeader(kExtraHeaderToRemove, &value));
- EXPECT_FALSE(req->is_pending());
- EXPECT_FALSE(req->is_redirecting());
- EXPECT_EQ("None", d.data_received());
- }
- TEST_F(URLRequestTestHTTP, CancelAfterStart) {
- TestDelegate d;
- {
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- GURL("http://www.google.com/"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- r->Cancel();
- d.RunUntilComplete();
- // We expect to receive OnResponseStarted even though the request has been
- // cancelled.
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(0, d.bytes_received());
- EXPECT_FALSE(d.received_data_before_response());
- }
- }
- TEST_F(URLRequestTestHTTP, CancelInResponseStarted) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- {
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- http_test_server()->GetURL("/"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- d.set_cancel_in_response_started(true);
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(0, d.bytes_received());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_EQ(ERR_ABORTED, d.request_status());
- }
- }
- TEST_F(URLRequestTestHTTP, CancelOnDataReceived) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- {
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- http_test_server()->GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- d.set_cancel_in_received_data(true);
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_NE(0, d.received_bytes_count());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_EQ(ERR_ABORTED, d.request_status());
- }
- }
- TEST_F(URLRequestTestHTTP, CancelDuringEofRead) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- {
- // This returns an empty response (With headers).
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- http_test_server()->GetURL("/"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- d.set_cancel_in_received_data(true);
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(0, d.received_bytes_count());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_EQ(ERR_ABORTED, d.request_status());
- }
- }
- TEST_F(URLRequestTestHTTP, CancelByDestroyingAfterStart) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- {
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- http_test_server()->GetURL("/"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- // The request will be implicitly canceled when it is destroyed. The
- // test delegate must not post a quit message when this happens because
- // this test doesn't actually have a message loop. The quit message would
- // get put on this thread's message queue and the next test would exit
- // early, causing problems.
- d.set_on_complete(base::DoNothing());
- }
- // expect things to just cleanup properly.
- // we won't actually get a received response here because we've never run the
- // message loop
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_EQ(0, d.bytes_received());
- }
- TEST_F(URLRequestTestHTTP, CancelWhileReadingFromCache) {
- ASSERT_TRUE(http_test_server()->Start());
- // populate cache
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- http_test_server()->GetURL("/cachetime"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- d.RunUntilComplete();
- EXPECT_EQ(OK, d.request_status());
- }
- // cancel read from cache (see bug 990242)
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- http_test_server()->GetURL("/cachetime"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- r->Cancel();
- d.RunUntilComplete();
- EXPECT_EQ(ERR_ABORTED, d.request_status());
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(0, d.bytes_received());
- EXPECT_FALSE(d.received_data_before_response());
- }
- }
- TEST_F(URLRequestTestHTTP, PostTest) {
- ASSERT_TRUE(http_test_server()->Start());
- HTTPUploadDataOperationTest("POST");
- }
- TEST_F(URLRequestTestHTTP, PutTest) {
- ASSERT_TRUE(http_test_server()->Start());
- HTTPUploadDataOperationTest("PUT");
- }
- TEST_F(URLRequestTestHTTP, PostEmptyTest) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- {
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- http_test_server()->GetURL("/echo"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->set_method("POST");
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- ASSERT_EQ(1, d.response_started_count())
- << "request failed. Error: " << d.request_status();
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_TRUE(d.data_received().empty());
- }
- }
- TEST_F(URLRequestTestHTTP, PostFileTest) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- {
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- http_test_server()->GetURL("/echo"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->set_method("POST");
- base::FilePath dir;
- base::PathService::Get(base::DIR_EXE, &dir);
- base::SetCurrentDirectory(dir);
- std::vector<std::unique_ptr<UploadElementReader>> element_readers;
- base::FilePath path;
- base::PathService::Get(base::DIR_SOURCE_ROOT, &path);
- path = path.Append(kTestFilePath);
- path = path.Append(FILE_PATH_LITERAL("with-headers.html"));
- element_readers.push_back(std::make_unique<UploadFileElementReader>(
- base::ThreadTaskRunnerHandle::Get().get(), path, 0,
- std::numeric_limits<uint64_t>::max(), base::Time()));
- r->set_upload(std::make_unique<ElementsUploadDataStream>(
- std::move(element_readers), 0));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- int64_t size64 = 0;
- ASSERT_EQ(true, base::GetFileSize(path, &size64));
- ASSERT_LE(size64, std::numeric_limits<int>::max());
- int size = static_cast<int>(size64);
- auto buf = std::make_unique<char[]>(size);
- ASSERT_EQ(size, base::ReadFile(path, buf.get(), size));
- ASSERT_EQ(1, d.response_started_count())
- << "request failed. Error: " << d.request_status();
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_EQ(size, d.bytes_received());
- EXPECT_EQ(std::string(&buf[0], size), d.data_received());
- }
- }
- TEST_F(URLRequestTestHTTP, PostUnreadableFileTest) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- {
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- http_test_server()->GetURL("/echo"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->set_method("POST");
- std::vector<std::unique_ptr<UploadElementReader>> element_readers;
- element_readers.push_back(std::make_unique<UploadFileElementReader>(
- base::ThreadTaskRunnerHandle::Get().get(),
- base::FilePath(FILE_PATH_LITERAL(
- "c:\\path\\to\\non\\existant\\file.randomness.12345")),
- 0, std::numeric_limits<uint64_t>::max(), base::Time()));
- r->set_upload(std::make_unique<ElementsUploadDataStream>(
- std::move(element_readers), 0));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_TRUE(d.request_failed());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_EQ(0, d.bytes_received());
- EXPECT_EQ(ERR_FILE_NOT_FOUND, d.request_status());
- }
- }
- namespace {
- // Adds a standard set of data to an upload for chunked upload integration
- // tests.
- void AddDataToUpload(ChunkedUploadDataStream::Writer* writer) {
- writer->AppendData("a", 1, false);
- writer->AppendData("bcd", 3, false);
- writer->AppendData("this is a longer chunk than before.", 35, false);
- writer->AppendData("\r\n\r\n", 4, false);
- writer->AppendData("0", 1, false);
- writer->AppendData("2323", 4, true);
- }
- // Checks that the upload data added in AddChunksToUpload() was echoed back from
- // the server.
- void VerifyReceivedDataMatchesChunks(URLRequest* r, TestDelegate* d) {
- // This should match the chunks sent by AddChunksToUpload().
- const std::string expected_data =
- "abcdthis is a longer chunk than before.\r\n\r\n02323";
- ASSERT_EQ(1, d->response_started_count())
- << "request failed. Error: " << d->request_status();
- EXPECT_FALSE(d->received_data_before_response());
- EXPECT_EQ(expected_data.size(), static_cast<size_t>(d->bytes_received()));
- EXPECT_EQ(expected_data, d->data_received());
- }
- } // namespace
- TEST_F(URLRequestTestHTTP, TestPostChunkedDataBeforeStart) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- {
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- http_test_server()->GetURL("/echo"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- auto upload_data_stream = std::make_unique<ChunkedUploadDataStream>(0);
- std::unique_ptr<ChunkedUploadDataStream::Writer> writer =
- upload_data_stream->CreateWriter();
- r->set_upload(std::move(upload_data_stream));
- r->set_method("POST");
- AddDataToUpload(writer.get());
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- VerifyReceivedDataMatchesChunks(r.get(), &d);
- }
- }
- TEST_F(URLRequestTestHTTP, TestPostChunkedDataJustAfterStart) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- {
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- http_test_server()->GetURL("/echo"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- auto upload_data_stream = std::make_unique<ChunkedUploadDataStream>(0);
- std::unique_ptr<ChunkedUploadDataStream::Writer> writer =
- upload_data_stream->CreateWriter();
- r->set_upload(std::move(upload_data_stream));
- r->set_method("POST");
- r->Start();
- EXPECT_TRUE(r->is_pending());
- AddDataToUpload(writer.get());
- d.RunUntilComplete();
- VerifyReceivedDataMatchesChunks(r.get(), &d);
- }
- }
- TEST_F(URLRequestTestHTTP, TestPostChunkedDataAfterStart) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- {
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- http_test_server()->GetURL("/echo"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- auto upload_data_stream = std::make_unique<ChunkedUploadDataStream>(0);
- std::unique_ptr<ChunkedUploadDataStream::Writer> writer =
- upload_data_stream->CreateWriter();
- r->set_upload(std::move(upload_data_stream));
- r->set_method("POST");
- r->Start();
- EXPECT_TRUE(r->is_pending());
- // Pump messages until we start sending headers..
- base::RunLoop().RunUntilIdle();
- // And now wait for completion.
- base::RunLoop run_loop;
- d.set_on_complete(run_loop.QuitClosure());
- AddDataToUpload(writer.get());
- run_loop.Run();
- VerifyReceivedDataMatchesChunks(r.get(), &d);
- }
- }
- TEST_F(URLRequestTestHTTP, ResponseHeadersTest) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/with-headers.html"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- const HttpResponseHeaders* headers = req->response_headers();
- // Simple sanity check that response_info() accesses the same data.
- EXPECT_EQ(headers, req->response_info().headers.get());
- std::string header;
- EXPECT_TRUE(headers->GetNormalizedHeader("cache-control", &header));
- EXPECT_EQ("private", header);
- header.clear();
- EXPECT_TRUE(headers->GetNormalizedHeader("content-type", &header));
- EXPECT_EQ("text/html; charset=ISO-8859-1", header);
- // The response has two "X-Multiple-Entries" headers.
- // This verfies our output has them concatenated together.
- header.clear();
- EXPECT_TRUE(headers->GetNormalizedHeader("x-multiple-entries", &header));
- EXPECT_EQ("a, b", header);
- }
- // TODO(svaldez): iOS tests are flaky with EmbeddedTestServer and transport
- // security state. (see http://crbug.com/550977).
- #if !BUILDFLAG(IS_IOS)
- TEST_F(URLRequestTestHTTP, ProcessSTS) {
- EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- https_test_server.SetSSLConfig(
- net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN);
- https_test_server.ServeFilesFromSourceDirectory(
- base::FilePath(kTestFilePath));
- ASSERT_TRUE(https_test_server.Start());
- std::string test_server_hostname = https_test_server.GetURL("/").host();
- TestDelegate d;
- std::unique_ptr<URLRequest> request(default_context().CreateRequest(
- https_test_server.GetURL("/hsts-headers.html"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- request->Start();
- d.RunUntilComplete();
- TransportSecurityState* security_state =
- default_context().transport_security_state();
- TransportSecurityState::STSState sts_state;
- TransportSecurityState::PKPState pkp_state;
- EXPECT_TRUE(
- security_state->GetDynamicSTSState(test_server_hostname, &sts_state));
- EXPECT_FALSE(
- security_state->GetDynamicPKPState(test_server_hostname, &pkp_state));
- EXPECT_EQ(TransportSecurityState::STSState::MODE_FORCE_HTTPS,
- sts_state.upgrade_mode);
- EXPECT_TRUE(sts_state.include_subdomains);
- EXPECT_FALSE(pkp_state.include_subdomains);
- #if BUILDFLAG(IS_ANDROID)
- // Android's CertVerifyProc does not (yet) handle pins.
- #else
- EXPECT_FALSE(pkp_state.HasPublicKeyPins());
- #endif
- }
- TEST_F(URLRequestTestHTTP, STSNotProcessedOnIP) {
- EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- https_test_server.ServeFilesFromSourceDirectory(
- base::FilePath(kTestFilePath));
- ASSERT_TRUE(https_test_server.Start());
- // Make sure this test fails if the test server is changed to not
- // listen on an IP by default.
- ASSERT_TRUE(https_test_server.GetURL("/").HostIsIPAddress());
- std::string test_server_hostname = https_test_server.GetURL("/").host();
- TestDelegate d;
- std::unique_ptr<URLRequest> request(default_context().CreateRequest(
- https_test_server.GetURL("/hsts-headers.html"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- request->Start();
- d.RunUntilComplete();
- TransportSecurityState* security_state =
- default_context().transport_security_state();
- TransportSecurityState::STSState sts_state;
- EXPECT_FALSE(
- security_state->GetDynamicSTSState(test_server_hostname, &sts_state));
- }
- namespace {
- const char kExpectCTStaticHostname[] = "expect-ct.preloaded.test";
- const char kPKPReportUri[] = "http://report-uri.preloaded.test/pkp";
- const char kPKPHost[] = "with-report-uri-pkp.preloaded.test";
- } // namespace
- // Tests that reports get sent on PKP violations when a report-uri is set.
- TEST_F(URLRequestTestHTTP, ProcessPKPAndSendReport) {
- base::test::ScopedFeatureList scoped_feature_list_;
- scoped_feature_list_.InitAndEnableFeature(
- net::features::kStaticKeyPinningEnforcement);
- GURL report_uri(kPKPReportUri);
- EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- https_test_server.SetSSLConfig(
- net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN);
- https_test_server.ServeFilesFromSourceDirectory(
- base::FilePath(kTestFilePath));
- ASSERT_TRUE(https_test_server.Start());
- std::string test_server_hostname = kPKPHost;
- SetTransportSecurityStateSourceForTesting(&test_default::kHSTSSource);
- // Set up a MockCertVerifier to trigger a violation of the previously
- // set pin.
- scoped_refptr<X509Certificate> cert = https_test_server.GetCertificate();
- ASSERT_TRUE(cert);
- CertVerifyResult verify_result;
- verify_result.verified_cert = cert;
- verify_result.is_issued_by_known_root = true;
- HashValue hash3;
- ASSERT_TRUE(
- hash3.FromString("sha256/3333333333333333333333333333333333333333333="));
- verify_result.public_key_hashes.push_back(hash3);
- auto cert_verifier = std::make_unique<MockCertVerifier>();
- cert_verifier->AddResultForCert(cert.get(), verify_result, OK);
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->SetCertVerifier(std::move(cert_verifier));
- auto context = context_builder->Build();
- MockCertificateReportSender mock_report_sender;
- context->transport_security_state()->EnableStaticPinsForTesting();
- context->transport_security_state()->SetPinningListAlwaysTimelyForTesting(
- true);
- context->transport_security_state()->SetReportSender(&mock_report_sender);
- IsolationInfo isolation_info = IsolationInfo::CreateTransient();
- // Now send a request to trigger the violation.
- TestDelegate d;
- std::unique_ptr<URLRequest> violating_request(context->CreateRequest(
- https_test_server.GetURL(test_server_hostname, "/simple.html"),
- DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- violating_request->set_isolation_info(isolation_info);
- violating_request->Start();
- d.RunUntilComplete();
- // Check that a report was sent.
- EXPECT_EQ(report_uri, mock_report_sender.latest_report_uri());
- ASSERT_FALSE(mock_report_sender.latest_report().empty());
- EXPECT_EQ("application/json; charset=utf-8",
- mock_report_sender.latest_content_type());
- std::unique_ptr<base::Value> value(
- base::JSONReader::ReadDeprecated(mock_report_sender.latest_report()));
- ASSERT_TRUE(value);
- base::Value::Dict* report_dict = value->GetIfDict();
- ASSERT_TRUE(report_dict);
- std::string* report_hostname = report_dict->FindString("hostname");
- ASSERT_TRUE(report_hostname);
- EXPECT_EQ(test_server_hostname, *report_hostname);
- EXPECT_EQ(isolation_info.network_isolation_key(),
- mock_report_sender.latest_network_isolation_key());
- }
- // Tests that reports do not get sent on requests to static pkp hosts that
- // don't have pin violations.
- TEST_F(URLRequestTestHTTP, ProcessPKPWithNoViolation) {
- base::test::ScopedFeatureList scoped_feature_list_;
- scoped_feature_list_.InitAndEnableFeature(
- net::features::kStaticKeyPinningEnforcement);
- EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- https_test_server.SetSSLConfig(
- net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN);
- https_test_server.ServeFilesFromSourceDirectory(
- base::FilePath(kTestFilePath));
- ASSERT_TRUE(https_test_server.Start());
- std::string test_server_hostname = kPKPHost;
- SetTransportSecurityStateSourceForTesting(&test_default::kHSTSSource);
- scoped_refptr<X509Certificate> cert = https_test_server.GetCertificate();
- ASSERT_TRUE(cert);
- CertVerifyResult verify_result;
- verify_result.verified_cert = cert;
- verify_result.is_issued_by_known_root = true;
- HashValue hash;
- // The expected value of GoodPin1 used by |test_default::kHSTSSource|.
- ASSERT_TRUE(
- hash.FromString("sha256/Nn8jk5By4Vkq6BeOVZ7R7AC6XUUBZsWmUbJR1f1Y5FY="));
- verify_result.public_key_hashes.push_back(hash);
- auto mock_cert_verifier = std::make_unique<MockCertVerifier>();
- mock_cert_verifier->AddResultForCert(cert.get(), verify_result, OK);
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->SetCertVerifier(std::move(mock_cert_verifier));
- auto context = context_builder->Build();
- MockCertificateReportSender mock_report_sender;
- context->transport_security_state()->EnableStaticPinsForTesting();
- context->transport_security_state()->SetPinningListAlwaysTimelyForTesting(
- true);
- context->transport_security_state()->SetReportSender(&mock_report_sender);
- // Now send a request that does not trigger the violation.
- TestDelegate d;
- std::unique_ptr<URLRequest> request(context->CreateRequest(
- https_test_server.GetURL(test_server_hostname, "/simple.html"),
- DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- request->set_isolation_info(IsolationInfo::CreateTransient());
- request->Start();
- d.RunUntilComplete();
- // Check that the request succeeded, a report was not sent and the pkp was
- // not bypassed.
- EXPECT_EQ(OK, d.request_status());
- EXPECT_EQ(GURL(), mock_report_sender.latest_report_uri());
- EXPECT_EQ(std::string(), mock_report_sender.latest_report());
- EXPECT_EQ(NetworkIsolationKey(),
- mock_report_sender.latest_network_isolation_key());
- TransportSecurityState::PKPState pkp_state;
- EXPECT_TRUE(context->transport_security_state()->GetStaticPKPState(
- test_server_hostname, &pkp_state));
- EXPECT_TRUE(pkp_state.HasPublicKeyPins());
- EXPECT_FALSE(request->ssl_info().pkp_bypassed);
- }
- TEST_F(URLRequestTestHTTP, PKPBypassRecorded) {
- base::test::ScopedFeatureList scoped_feature_list_;
- scoped_feature_list_.InitAndEnableFeature(
- net::features::kStaticKeyPinningEnforcement);
- EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- https_test_server.SetSSLConfig(
- net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN);
- https_test_server.ServeFilesFromSourceDirectory(
- base::FilePath(kTestFilePath));
- ASSERT_TRUE(https_test_server.Start());
- // Set up a MockCertVerifier to be a local root that violates the pin
- scoped_refptr<X509Certificate> cert = https_test_server.GetCertificate();
- ASSERT_TRUE(cert);
- CertVerifyResult verify_result;
- verify_result.verified_cert = cert;
- verify_result.is_issued_by_known_root = false;
- HashValue hash;
- ASSERT_TRUE(
- hash.FromString("sha256/1111111111111111111111111111111111111111111="));
- verify_result.public_key_hashes.push_back(hash);
- auto cert_verifier = std::make_unique<MockCertVerifier>();
- cert_verifier->AddResultForCert(cert.get(), verify_result, OK);
- std::string test_server_hostname = kPKPHost;
- SetTransportSecurityStateSourceForTesting(&test_default::kHSTSSource);
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->SetCertVerifier(std::move(cert_verifier));
- auto context = context_builder->Build();
- MockCertificateReportSender mock_report_sender;
- context->transport_security_state()->EnableStaticPinsForTesting();
- context->transport_security_state()->SetPinningListAlwaysTimelyForTesting(
- true);
- context->transport_security_state()->SetReportSender(&mock_report_sender);
- TestDelegate d;
- std::unique_ptr<URLRequest> request(context->CreateRequest(
- https_test_server.GetURL(test_server_hostname, "/simple.html"),
- DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- request->set_isolation_info(IsolationInfo::CreateTransient());
- request->Start();
- d.RunUntilComplete();
- // Check that the request succeeded, a report was not sent and the PKP was
- // bypassed.
- EXPECT_EQ(OK, d.request_status());
- EXPECT_EQ(GURL(), mock_report_sender.latest_report_uri());
- EXPECT_EQ(std::string(), mock_report_sender.latest_report());
- EXPECT_EQ(NetworkIsolationKey(),
- mock_report_sender.latest_network_isolation_key());
- TransportSecurityState::PKPState pkp_state;
- EXPECT_TRUE(context->transport_security_state()->GetStaticPKPState(
- test_server_hostname, &pkp_state));
- EXPECT_TRUE(pkp_state.HasPublicKeyPins());
- EXPECT_TRUE(request->ssl_info().pkp_bypassed);
- }
- TEST_F(URLRequestTestHTTP, ProcessSTSOnce) {
- EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- https_test_server.SetSSLConfig(
- net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN);
- https_test_server.ServeFilesFromSourceDirectory(
- base::FilePath(kTestFilePath));
- ASSERT_TRUE(https_test_server.Start());
- std::string test_server_hostname = https_test_server.GetURL("/").host();
- TestDelegate d;
- std::unique_ptr<URLRequest> request(default_context().CreateRequest(
- https_test_server.GetURL("/hsts-multiple-headers.html"), DEFAULT_PRIORITY,
- &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- request->Start();
- d.RunUntilComplete();
- // We should have set parameters from the first header, not the second.
- TransportSecurityState* security_state =
- default_context().transport_security_state();
- TransportSecurityState::STSState sts_state;
- EXPECT_TRUE(
- security_state->GetDynamicSTSState(test_server_hostname, &sts_state));
- EXPECT_EQ(TransportSecurityState::STSState::MODE_FORCE_HTTPS,
- sts_state.upgrade_mode);
- EXPECT_FALSE(sts_state.include_subdomains);
- EXPECT_FALSE(sts_state.include_subdomains);
- }
- // An ExpectCTReporter that records the number of times OnExpectCTFailed() was
- // called.
- class MockExpectCTReporter : public TransportSecurityState::ExpectCTReporter {
- public:
- MockExpectCTReporter() = default;
- ~MockExpectCTReporter() override = default;
- void OnExpectCTFailed(
- const HostPortPair& host_port_pair,
- const GURL& report_uri,
- base::Time expiration,
- const X509Certificate* validated_certificate_chain,
- const X509Certificate* served_certificate_chain,
- const SignedCertificateTimestampAndStatusList&
- signed_certificate_timestamps,
- const NetworkIsolationKey& network_isolation_key) override {
- num_failures_++;
- }
- uint32_t num_failures() { return num_failures_; }
- private:
- uint32_t num_failures_ = 0;
- };
- // A CTPolicyEnforcer that returns a default CTPolicyCompliance value
- // for every certificate.
- class MockCTPolicyEnforcer : public CTPolicyEnforcer {
- public:
- MockCTPolicyEnforcer() = default;
- ~MockCTPolicyEnforcer() override = default;
- ct::CTPolicyCompliance CheckCompliance(
- X509Certificate* cert,
- const ct::SCTList& verified_scts,
- const NetLogWithSource& net_log) override {
- return default_result_;
- }
- void set_default_result(ct::CTPolicyCompliance default_result) {
- default_result_ = default_result;
- }
- private:
- ct::CTPolicyCompliance default_result_ =
- ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS;
- };
- // Tests that Expect CT headers for the preload list are processed correctly.
- TEST_F(URLRequestTestHTTP, PreloadExpectCTHeader) {
- SetTransportSecurityStateSourceForTesting(&test_default::kHSTSSource);
- EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- https_test_server.SetSSLConfig(
- net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN);
- https_test_server.ServeFilesFromSourceDirectory(
- base::FilePath(kTestFilePath));
- ASSERT_TRUE(https_test_server.Start());
- // Set up a MockCertVerifier to accept the certificate that the server sends.
- scoped_refptr<X509Certificate> cert = https_test_server.GetCertificate();
- ASSERT_TRUE(cert);
- CertVerifyResult verify_result;
- verify_result.verified_cert = cert;
- verify_result.is_issued_by_known_root = true;
- auto cert_verifier = std::make_unique<MockCertVerifier>();
- cert_verifier->AddResultForCert(cert.get(), verify_result, OK);
- // Set up a MockCTPolicyEnforcer to trigger an Expect CT violation.
- auto ct_policy_enforcer = std::make_unique<MockCTPolicyEnforcer>();
- ct_policy_enforcer->set_default_result(
- ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS);
- // Use a MockHostResolver, so that the request can be sent to a site on the
- // Expect CT preload list.
- auto host_resolver = std::make_unique<MockHostResolver>();
- host_resolver->rules()->AddRule(kExpectCTStaticHostname,
- https_test_server.GetIPLiteralString());
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_host_resolver(std::move(host_resolver));
- context_builder->SetCertVerifier(std::move(cert_verifier));
- context_builder->set_ct_policy_enforcer(std::move(ct_policy_enforcer));
- context_builder->set_hsts_policy_bypass_list({});
- auto context = context_builder->Build();
- MockExpectCTReporter expect_ct_reporter;
- context->transport_security_state()->enable_static_expect_ct_ = true;
- context->transport_security_state()->SetExpectCTReporter(&expect_ct_reporter);
- context->transport_security_state()->ct_log_list_last_update_time_ =
- base::Time::Now();
- // Now send a request to trigger the violation.
- TestDelegate d;
- GURL url = https_test_server.GetURL("/expect-ct-header-preload.html");
- GURL::Replacements replace_host;
- replace_host.SetHostStr(kExpectCTStaticHostname);
- url = url.ReplaceComponents(replace_host);
- std::unique_ptr<URLRequest> violating_request(context->CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- violating_request->Start();
- d.RunUntilComplete();
- EXPECT_EQ(1u, expect_ct_reporter.num_failures());
- }
- // Tests that Expect CT HTTP headers are processed correctly.
- TEST_F(URLRequestTestHTTP, ExpectCTHeader) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(
- TransportSecurityState::kDynamicExpectCTFeature);
- EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- https_test_server.SetSSLConfig(
- net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN);
- https_test_server.ServeFilesFromSourceDirectory(
- base::FilePath(kTestFilePath));
- ASSERT_TRUE(https_test_server.Start());
- // Set up a MockCertVerifier to accept the certificate that the server sends.
- scoped_refptr<X509Certificate> cert = https_test_server.GetCertificate();
- ASSERT_TRUE(cert);
- CertVerifyResult verify_result;
- verify_result.verified_cert = cert;
- verify_result.is_issued_by_known_root = true;
- auto cert_verifier = std::make_unique<MockCertVerifier>();
- cert_verifier->AddResultForCert(cert.get(), verify_result, OK);
- // Set up a MockCTPolicyEnforcer to simulate CT compliance.
- auto ct_policy_enforcer = std::make_unique<MockCTPolicyEnforcer>();
- ct_policy_enforcer->set_default_result(
- ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS);
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->SetCertVerifier(std::move(cert_verifier));
- context_builder->set_ct_policy_enforcer(std::move(ct_policy_enforcer));
- auto context = context_builder->Build();
- MockExpectCTReporter expect_ct_reporter;
- context->transport_security_state()->SetExpectCTReporter(&expect_ct_reporter);
- // Now send a request to trigger the header processing.
- TestDelegate d;
- GURL url = https_test_server.GetURL("/expect-ct-header.html");
- std::unique_ptr<URLRequest> request(context->CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- request->Start();
- d.RunUntilComplete();
- TransportSecurityState::ExpectCTState state;
- ASSERT_TRUE(context->transport_security_state()->GetDynamicExpectCTState(
- url.host(), NetworkIsolationKey(), &state));
- EXPECT_TRUE(state.enforce);
- EXPECT_EQ(GURL("https://example.test"), state.report_uri);
- }
- // Tests that if multiple Expect CT HTTP headers are sent, they are all
- // processed.
- TEST_F(URLRequestTestHTTP, MultipleExpectCTHeaders) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(
- TransportSecurityState::kDynamicExpectCTFeature);
- EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- https_test_server.SetSSLConfig(
- net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN);
- https_test_server.ServeFilesFromSourceDirectory(
- base::FilePath(kTestFilePath));
- ASSERT_TRUE(https_test_server.Start());
- // Set up a MockCertVerifier to accept the certificate that the server sends.
- scoped_refptr<X509Certificate> cert = https_test_server.GetCertificate();
- ASSERT_TRUE(cert);
- CertVerifyResult verify_result;
- verify_result.verified_cert = cert;
- verify_result.is_issued_by_known_root = true;
- auto cert_verifier = std::make_unique<MockCertVerifier>();
- cert_verifier->AddResultForCert(cert.get(), verify_result, OK);
- // Set up a MockCTPolicyEnforcer to simulate CT compliance.
- DoNothingCTVerifier ct_verifier;
- auto ct_policy_enforcer = std::make_unique<MockCTPolicyEnforcer>();
- ct_policy_enforcer->set_default_result(
- ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS);
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->SetCertVerifier(std::move(cert_verifier));
- context_builder->set_ct_policy_enforcer(std::move(ct_policy_enforcer));
- auto context = context_builder->Build();
- MockExpectCTReporter expect_ct_reporter;
- context->transport_security_state()->SetExpectCTReporter(&expect_ct_reporter);
- // Now send a request to trigger the header processing.
- TestDelegate d;
- GURL url = https_test_server.GetURL("/expect-ct-header-multiple.html");
- std::unique_ptr<URLRequest> request(context->CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- request->Start();
- d.RunUntilComplete();
- TransportSecurityState::ExpectCTState state;
- ASSERT_TRUE(context->transport_security_state()->GetDynamicExpectCTState(
- url.host(), NetworkIsolationKey(), &state));
- EXPECT_TRUE(state.enforce);
- EXPECT_EQ(GURL("https://example.test"), state.report_uri);
- }
- #endif // !BUILDFLAG(IS_IOS)
- #if BUILDFLAG(ENABLE_REPORTING)
- TEST_F(URLRequestTestHTTP, NetworkErrorLogging_DontReportIfNetworkNotAccessed) {
- EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- RegisterDefaultHandlers(&https_test_server);
- ASSERT_TRUE(https_test_server.Start());
- GURL request_url = https_test_server.GetURL("/cachetime");
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_network_error_logging_enabled(true);
- auto& nel_service = *context_builder->SetNetworkErrorLoggingServiceForTesting(
- std::make_unique<TestNetworkErrorLoggingService>());
- auto context = context_builder->Build();
- // Populate the cache.
- TestDelegate d;
- std::unique_ptr<URLRequest> request(context->CreateRequest(
- request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- request->set_isolation_info(isolation_info1_);
- request->Start();
- d.RunUntilComplete();
- ASSERT_EQ(1u, nel_service.errors().size());
- const TestNetworkErrorLoggingService::RequestDetails& error =
- nel_service.errors()[0];
- EXPECT_EQ(request_url, error.uri);
- EXPECT_EQ(200, error.status_code);
- EXPECT_EQ(OK, error.type);
- request = context->CreateRequest(request_url, DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS);
- request->set_isolation_info(isolation_info1_);
- request->Start();
- d.RunUntilComplete();
- EXPECT_FALSE(request->response_info().network_accessed);
- EXPECT_TRUE(request->response_info().was_cached);
- // No additional NEL report was generated.
- EXPECT_EQ(1u, nel_service.errors().size());
- }
- TEST_F(URLRequestTestHTTP, NetworkErrorLogging_BasicSuccess) {
- EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- https_test_server.ServeFilesFromSourceDirectory(
- base::FilePath(kTestFilePath));
- ASSERT_TRUE(https_test_server.Start());
- GURL request_url = https_test_server.GetURL("/simple.html");
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_network_error_logging_enabled(true);
- auto& nel_service = *context_builder->SetNetworkErrorLoggingServiceForTesting(
- std::make_unique<TestNetworkErrorLoggingService>());
- auto context = context_builder->Build();
- TestDelegate d;
- std::unique_ptr<URLRequest> request(context->CreateRequest(
- request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- request->Start();
- d.RunUntilComplete();
- ASSERT_EQ(1u, nel_service.errors().size());
- const TestNetworkErrorLoggingService::RequestDetails& error =
- nel_service.errors()[0];
- EXPECT_EQ(request_url, error.uri);
- EXPECT_EQ(200, error.status_code);
- EXPECT_EQ(OK, error.type);
- }
- TEST_F(URLRequestTestHTTP, NetworkErrorLogging_BasicError) {
- EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- RegisterDefaultHandlers(&https_test_server);
- ASSERT_TRUE(https_test_server.Start());
- GURL request_url = https_test_server.GetURL("/close-socket");
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_network_error_logging_enabled(true);
- auto& nel_service = *context_builder->SetNetworkErrorLoggingServiceForTesting(
- std::make_unique<TestNetworkErrorLoggingService>());
- auto context = context_builder->Build();
- TestDelegate d;
- std::unique_ptr<URLRequest> request(context->CreateRequest(
- request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- request->Start();
- d.RunUntilComplete();
- ASSERT_EQ(1u, nel_service.errors().size());
- const TestNetworkErrorLoggingService::RequestDetails& error =
- nel_service.errors()[0];
- EXPECT_EQ(request_url, error.uri);
- EXPECT_EQ(0, error.status_code);
- EXPECT_EQ(ERR_EMPTY_RESPONSE, error.type);
- }
- TEST_F(URLRequestTestHTTP, NetworkErrorLogging_Redirect) {
- EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- https_test_server.ServeFilesFromSourceDirectory(
- base::FilePath(kTestFilePath));
- ASSERT_TRUE(https_test_server.Start());
- GURL request_url = https_test_server.GetURL("/redirect-test.html");
- GURL redirect_url = https_test_server.GetURL("/with-headers.html");
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_network_error_logging_enabled(true);
- auto& nel_service = *context_builder->SetNetworkErrorLoggingServiceForTesting(
- std::make_unique<TestNetworkErrorLoggingService>());
- auto context = context_builder->Build();
- TestDelegate d;
- std::unique_ptr<URLRequest> request(context->CreateRequest(
- request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- request->Start();
- d.RunUntilComplete();
- ASSERT_EQ(2u, nel_service.errors().size());
- const TestNetworkErrorLoggingService::RequestDetails& error1 =
- nel_service.errors()[0];
- EXPECT_EQ(request_url, error1.uri);
- EXPECT_EQ(302, error1.status_code);
- EXPECT_EQ(OK, error1.type);
- const TestNetworkErrorLoggingService::RequestDetails& error2 =
- nel_service.errors()[1];
- EXPECT_EQ(redirect_url, error2.uri);
- EXPECT_EQ(200, error2.status_code);
- EXPECT_EQ(OK, error2.type);
- }
- TEST_F(URLRequestTestHTTP, NetworkErrorLogging_RedirectWithoutLocationHeader) {
- EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- https_test_server.ServeFilesFromSourceDirectory(
- base::FilePath(kTestFilePath));
- ASSERT_TRUE(https_test_server.Start());
- GURL request_url = https_test_server.GetURL("/308-without-location-header");
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_network_error_logging_enabled(true);
- auto& nel_service = *context_builder->SetNetworkErrorLoggingServiceForTesting(
- std::make_unique<TestNetworkErrorLoggingService>());
- auto context = context_builder->Build();
- TestDelegate d;
- std::unique_ptr<URLRequest> request(context->CreateRequest(
- request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- request->Start();
- d.RunUntilComplete();
- ASSERT_EQ(1u, nel_service.errors().size());
- const TestNetworkErrorLoggingService::RequestDetails& error =
- nel_service.errors()[0];
- EXPECT_EQ(request_url, error.uri);
- EXPECT_EQ(308, error.status_code);
- // The body of the response was successfully read.
- EXPECT_EQ(OK, error.type);
- }
- TEST_F(URLRequestTestHTTP, NetworkErrorLogging_Auth) {
- EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- RegisterDefaultHandlers(&https_test_server);
- ASSERT_TRUE(https_test_server.Start());
- GURL request_url = https_test_server.GetURL("/auth-basic");
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_network_error_logging_enabled(true);
- auto& nel_service = *context_builder->SetNetworkErrorLoggingServiceForTesting(
- std::make_unique<TestNetworkErrorLoggingService>());
- auto context = context_builder->Build();
- TestDelegate d;
- d.set_credentials(AuthCredentials(kUser, kSecret));
- std::unique_ptr<URLRequest> request(context->CreateRequest(
- request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- request->Start();
- d.RunUntilComplete();
- ASSERT_EQ(2u, nel_service.errors().size());
- const TestNetworkErrorLoggingService::RequestDetails& error1 =
- nel_service.errors()[0];
- EXPECT_EQ(request_url, error1.uri);
- EXPECT_EQ(401, error1.status_code);
- EXPECT_EQ(OK, error1.type);
- const TestNetworkErrorLoggingService::RequestDetails& error2 =
- nel_service.errors()[1];
- EXPECT_EQ(request_url, error2.uri);
- EXPECT_EQ(200, error2.status_code);
- EXPECT_EQ(OK, error2.type);
- }
- TEST_F(URLRequestTestHTTP, NetworkErrorLogging_304Response) {
- EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- RegisterDefaultHandlers(&https_test_server);
- ASSERT_TRUE(https_test_server.Start());
- GURL request_url = https_test_server.GetURL("/auth-basic");
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_network_error_logging_enabled(true);
- auto& nel_service = *context_builder->SetNetworkErrorLoggingServiceForTesting(
- std::make_unique<TestNetworkErrorLoggingService>());
- auto context = context_builder->Build();
- // populate the cache
- {
- TestDelegate d;
- d.set_credentials(AuthCredentials(kUser, kSecret));
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->set_isolation_info(isolation_info1_);
- r->Start();
- d.RunUntilComplete();
- }
- ASSERT_EQ(2u, nel_service.errors().size());
- const TestNetworkErrorLoggingService::RequestDetails& error1 =
- nel_service.errors()[0];
- EXPECT_EQ(request_url, error1.uri);
- EXPECT_EQ(401, error1.status_code);
- EXPECT_EQ(OK, error1.type);
- const TestNetworkErrorLoggingService::RequestDetails& error2 =
- nel_service.errors()[1];
- EXPECT_EQ(request_url, error2.uri);
- EXPECT_EQ(200, error2.status_code);
- EXPECT_EQ(OK, error2.type);
- // repeat request with end-to-end validation. since auth-basic results in a
- // cachable page, we expect this test to result in a 304. in which case, the
- // response should be fetched from the cache.
- {
- TestDelegate d;
- d.set_credentials(AuthCredentials(kUser, kSecret));
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->SetLoadFlags(LOAD_VALIDATE_CACHE);
- r->set_isolation_info(isolation_info1_);
- r->Start();
- d.RunUntilComplete();
- // Should be the same cached document.
- EXPECT_TRUE(r->was_cached());
- }
- ASSERT_EQ(3u, nel_service.errors().size());
- const TestNetworkErrorLoggingService::RequestDetails& error3 =
- nel_service.errors()[2];
- EXPECT_EQ(request_url, error3.uri);
- EXPECT_EQ(304, error3.status_code);
- EXPECT_EQ(OK, error3.type);
- }
- TEST_F(URLRequestTestHTTP, NetworkErrorLogging_CancelInResponseStarted) {
- EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- https_test_server.ServeFilesFromSourceDirectory(
- base::FilePath(kTestFilePath));
- ASSERT_TRUE(https_test_server.Start());
- GURL request_url = https_test_server.GetURL("/simple.html");
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_network_error_logging_enabled(true);
- auto& nel_service = *context_builder->SetNetworkErrorLoggingServiceForTesting(
- std::make_unique<TestNetworkErrorLoggingService>());
- auto context = context_builder->Build();
- TestDelegate d;
- d.set_cancel_in_response_started(true);
- std::unique_ptr<URLRequest> request(context->CreateRequest(
- request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- request->Start();
- d.RunUntilComplete();
- ASSERT_EQ(1u, nel_service.errors().size());
- const TestNetworkErrorLoggingService::RequestDetails& error =
- nel_service.errors()[0];
- EXPECT_EQ(request_url, error.uri);
- EXPECT_EQ(200, error.status_code);
- // Headers were received and the body should have been read but was not.
- EXPECT_EQ(ERR_ABORTED, error.type);
- }
- TEST_F(URLRequestTestHTTP, NetworkErrorLogging_CancelOnDataReceived) {
- EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- https_test_server.ServeFilesFromSourceDirectory(
- base::FilePath(kTestFilePath));
- ASSERT_TRUE(https_test_server.Start());
- GURL request_url = https_test_server.GetURL("/simple.html");
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_network_error_logging_enabled(true);
- auto& nel_service = *context_builder->SetNetworkErrorLoggingServiceForTesting(
- std::make_unique<TestNetworkErrorLoggingService>());
- auto context = context_builder->Build();
- TestDelegate d;
- d.set_cancel_in_received_data(true);
- std::unique_ptr<URLRequest> request(context->CreateRequest(
- request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- request->Start();
- d.RunUntilComplete();
- ASSERT_EQ(1u, nel_service.errors().size());
- const TestNetworkErrorLoggingService::RequestDetails& error =
- nel_service.errors()[0];
- EXPECT_EQ(request_url, error.uri);
- EXPECT_EQ(200, error.status_code);
- // Data was received but the body was not completely read.
- EXPECT_EQ(ERR_ABORTED, error.type);
- }
- TEST_F(URLRequestTestHTTP, NetworkErrorLogging_CancelRedirect) {
- EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- https_test_server.ServeFilesFromSourceDirectory(
- base::FilePath(kTestFilePath));
- ASSERT_TRUE(https_test_server.Start());
- GURL request_url = https_test_server.GetURL("/redirect-test.html");
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_network_error_logging_enabled(true);
- auto& nel_service = *context_builder->SetNetworkErrorLoggingServiceForTesting(
- std::make_unique<TestNetworkErrorLoggingService>());
- auto context = context_builder->Build();
- TestDelegate d;
- d.set_cancel_in_received_redirect(true);
- std::unique_ptr<URLRequest> request(context->CreateRequest(
- request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- request->Start();
- d.RunUntilComplete();
- ASSERT_EQ(1u, nel_service.errors().size());
- const TestNetworkErrorLoggingService::RequestDetails& error =
- nel_service.errors()[0];
- EXPECT_EQ(request_url, error.uri);
- EXPECT_EQ(302, error.status_code);
- // A valid HTTP response was received, even though the request was cancelled.
- EXPECT_EQ(OK, error.type);
- }
- #endif // BUILDFLAG(ENABLE_REPORTING)
- TEST_F(URLRequestTestHTTP, ContentTypeNormalizationTest) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/content-type-normalization.html"),
- DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- std::string mime_type;
- req->GetMimeType(&mime_type);
- EXPECT_EQ("text/html", mime_type);
- std::string charset;
- req->GetCharset(&charset);
- EXPECT_EQ("utf-8", charset);
- req->Cancel();
- }
- TEST_F(URLRequestTestHTTP, FileRedirect) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/redirect-to-file.html"), DEFAULT_PRIORITY,
- &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(ERR_UNKNOWN_URL_SCHEME, d.request_status());
- EXPECT_EQ(1, d.received_redirect_count());
- }
- TEST_F(URLRequestTestHTTP, DataRedirect) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/redirect-to-data.html"), DEFAULT_PRIORITY,
- &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(ERR_UNKNOWN_URL_SCHEME, d.request_status());
- EXPECT_EQ(1, d.received_redirect_count());
- }
- TEST_F(URLRequestTestHTTP, RestrictUnsafeRedirect) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL(
- "/server-redirect?unsafe://here-there-be-dragons"),
- DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(ERR_UNSAFE_REDIRECT, d.request_status());
- // The redirect should have been rejected before reporting it to the
- // caller. See https://crbug.com/723796
- EXPECT_EQ(0, d.received_redirect_count());
- }
- // Test that redirects to invalid URLs are rejected. See
- // https://crbug.com/462272.
- TEST_F(URLRequestTestHTTP, RedirectToInvalidURL) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/redirect-to-invalid-url.html"),
- DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(ERR_INVALID_REDIRECT, d.request_status());
- // The redirect should have been rejected before reporting it to the caller.
- EXPECT_EQ(0, d.received_redirect_count());
- }
- // Make sure redirects are cached, despite not reading their bodies.
- TEST_F(URLRequestTestHTTP, CacheRedirect) {
- ASSERT_TRUE(http_test_server()->Start());
- GURL redirect_url =
- http_test_server()->GetURL("/redirect302-to-echo-cacheable");
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- redirect_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(isolation_info1_);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(OK, d.request_status());
- EXPECT_EQ(1, d.received_redirect_count());
- EXPECT_EQ(http_test_server()->GetURL("/echo"), req->url());
- }
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- redirect_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(isolation_info1_);
- req->Start();
- d.RunUntilRedirect();
- EXPECT_EQ(1, d.received_redirect_count());
- EXPECT_EQ(0, d.response_started_count());
- EXPECT_TRUE(req->was_cached());
- req->FollowDeferredRedirect(absl::nullopt /* removed_headers */,
- absl::nullopt /* modified_headers */);
- d.RunUntilComplete();
- EXPECT_EQ(1, d.received_redirect_count());
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(OK, d.request_status());
- EXPECT_EQ(http_test_server()->GetURL("/echo"), req->url());
- }
- }
- // Make sure a request isn't cached when a NetworkDelegate forces a redirect
- // when the headers are read, since the body won't have been read.
- TEST_F(URLRequestTestHTTP, NoCacheOnNetworkDelegateRedirect) {
- ASSERT_TRUE(http_test_server()->Start());
- // URL that is normally cached.
- GURL initial_url = http_test_server()->GetURL("/cachetime");
- {
- // Set up the TestNetworkDelegate tp force a redirect.
- GURL redirect_to_url = http_test_server()->GetURL("/echo");
- default_network_delegate().set_redirect_on_headers_received_url(
- redirect_to_url);
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- initial_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(OK, d.request_status());
- EXPECT_EQ(1, d.received_redirect_count());
- EXPECT_EQ(redirect_to_url, req->url());
- }
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- initial_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(OK, d.request_status());
- EXPECT_FALSE(req->was_cached());
- EXPECT_EQ(0, d.received_redirect_count());
- EXPECT_EQ(initial_url, req->url());
- }
- }
- // Check that |preserve_fragment_on_redirect_url| is respected.
- TEST_F(URLRequestTestHTTP, PreserveFragmentOnRedirectUrl) {
- ASSERT_TRUE(http_test_server()->Start());
- GURL original_url(http_test_server()->GetURL("/original#fragment1"));
- GURL preserve_fragement_url(http_test_server()->GetURL("/echo"));
- default_network_delegate().set_redirect_on_headers_received_url(
- preserve_fragement_url);
- default_network_delegate().set_preserve_fragment_on_redirect_url(
- preserve_fragement_url);
- TestDelegate d;
- {
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- d.RunUntilComplete();
- EXPECT_EQ(2U, r->url_chain().size());
- EXPECT_EQ(OK, d.request_status());
- EXPECT_EQ(original_url, r->original_url());
- EXPECT_EQ(preserve_fragement_url, r->url());
- }
- }
- // Check that |preserve_fragment_on_redirect_url| has no effect when it doesn't
- // match the URL being redirected to.
- TEST_F(URLRequestTestHTTP, PreserveFragmentOnRedirectUrlMismatch) {
- ASSERT_TRUE(http_test_server()->Start());
- GURL original_url(http_test_server()->GetURL("/original#fragment1"));
- GURL preserve_fragement_url(http_test_server()->GetURL("/echo#fragment2"));
- GURL redirect_url(http_test_server()->GetURL("/echo"));
- GURL expected_url(http_test_server()->GetURL("/echo#fragment1"));
- default_network_delegate().set_redirect_on_headers_received_url(redirect_url);
- default_network_delegate().set_preserve_fragment_on_redirect_url(
- preserve_fragement_url);
- TestDelegate d;
- {
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- d.RunUntilComplete();
- EXPECT_EQ(2U, r->url_chain().size());
- EXPECT_EQ(OK, d.request_status());
- EXPECT_EQ(original_url, r->original_url());
- EXPECT_EQ(expected_url, r->url());
- }
- }
- // When a URLRequestRedirectJob is created, the redirection must be followed and
- // the reference fragment of the target URL must not be modified.
- TEST_F(URLRequestTestHTTP, RedirectJobWithReferenceFragment) {
- ASSERT_TRUE(http_test_server()->Start());
- GURL original_url(
- http_test_server()->GetURL("/original#should-not-be-appended"));
- GURL redirect_url(http_test_server()->GetURL("/echo"));
- TestDelegate d;
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- std::unique_ptr<URLRequestRedirectJob> job =
- std::make_unique<URLRequestRedirectJob>(
- r.get(), redirect_url, RedirectUtil::ResponseCode::REDIRECT_302_FOUND,
- "Very Good Reason");
- TestScopedURLInterceptor interceptor(r->url(), std::move(job));
- r->Start();
- d.RunUntilComplete();
- EXPECT_EQ(OK, d.request_status());
- EXPECT_EQ(original_url, r->original_url());
- EXPECT_EQ(redirect_url, r->url());
- }
- TEST_F(URLRequestTestHTTP, UnsupportedReferrerScheme) {
- ASSERT_TRUE(http_test_server()->Start());
- const std::string referrer("foobar://totally.legit.referrer");
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/echoheader?Referer"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->SetReferrer(referrer);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(std::string("None"), d.data_received());
- }
- TEST_F(URLRequestTestHTTP, NoUserPassInReferrer) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/echoheader?Referer"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->SetReferrer("http://user:pass@foo.com/");
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(std::string("http://foo.com/"), d.data_received());
- }
- TEST_F(URLRequestTestHTTP, NoFragmentInReferrer) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/echoheader?Referer"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->SetReferrer("http://foo.com/test#fragment");
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(std::string("http://foo.com/test"), d.data_received());
- }
- TEST_F(URLRequestTestHTTP, EmptyReferrerAfterValidReferrer) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/echoheader?Referer"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->SetReferrer("http://foo.com/test#fragment");
- req->SetReferrer("");
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(std::string("None"), d.data_received());
- }
- TEST_F(URLRequestTestHTTP, CapRefererHeaderLength) {
- ASSERT_TRUE(http_test_server()->Start());
- // Verify that referrers over 4k are stripped to an origin, and referrers at
- // or under 4k are unmodified.
- {
- std::string original_header = "http://example.com/";
- original_header.resize(4097, 'a');
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/echoheader?Referer"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->SetReferrer(original_header);
- req->Start();
- d.RunUntilComplete();
- // The request's referrer will be stripped since (1) there will be a
- // mismatch between the request's referrer and the output of
- // URLRequestJob::ComputeReferrerForPolicy and (2) the delegate, when
- // offered the opportunity to cancel the request for this reason, will
- // decline.
- EXPECT_EQ("None", d.data_received());
- }
- {
- std::string original_header = "http://example.com/";
- original_header.resize(4096, 'a');
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/echoheader?Referer"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->SetReferrer(original_header);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(original_header, d.data_received());
- }
- {
- std::string original_header = "http://example.com/";
- original_header.resize(4095, 'a');
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/echoheader?Referer"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->SetReferrer(original_header);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(original_header, d.data_received());
- }
- }
- TEST_F(URLRequestTestHTTP, CancelRedirect) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- {
- d.set_cancel_in_received_redirect(true);
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/redirect-test.html"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(0, d.bytes_received());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_EQ(ERR_ABORTED, d.request_status());
- }
- }
- TEST_F(URLRequestTestHTTP, DeferredRedirect) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- {
- GURL test_url(http_test_server()->GetURL("/redirect-test.html"));
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- test_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilRedirect();
- EXPECT_EQ(1, d.received_redirect_count());
- req->FollowDeferredRedirect(absl::nullopt /* removed_headers */,
- absl::nullopt /* modified_headers */);
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_EQ(OK, d.request_status());
- base::FilePath path;
- base::PathService::Get(base::DIR_SOURCE_ROOT, &path);
- path = path.Append(kTestFilePath);
- path = path.Append(FILE_PATH_LITERAL("with-headers.html"));
- std::string contents;
- EXPECT_TRUE(base::ReadFileToString(path, &contents));
- EXPECT_EQ(contents, d.data_received());
- }
- }
- TEST_F(URLRequestTestHTTP, DeferredRedirect_ModifiedHeaders) {
- test_server::HttpRequest http_request;
- int num_observed_requests = 0;
- http_test_server()->RegisterRequestMonitor(
- base::BindLambdaForTesting([&](const test_server::HttpRequest& request) {
- http_request = request;
- ++num_observed_requests;
- }));
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- {
- GURL test_url(http_test_server()->GetURL("/redirect-test.html"));
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- test_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- // Set initial headers for the request.
- req->SetExtraRequestHeaderByName("Header1", "Value1", true /* overwrite */);
- req->SetExtraRequestHeaderByName("Header2", "Value2", true /* overwrite */);
- req->Start();
- d.RunUntilRedirect();
- // Initial request should only have initial headers.
- EXPECT_EQ(1, d.received_redirect_count());
- EXPECT_EQ(1, num_observed_requests);
- EXPECT_EQ("Value1", http_request.headers["Header1"]);
- EXPECT_EQ("Value2", http_request.headers["Header2"]);
- EXPECT_EQ(0u, http_request.headers.count("Header3"));
- // Overwrite Header2 and add Header3.
- net::HttpRequestHeaders modified_headers;
- modified_headers.SetHeader("Header2", "");
- modified_headers.SetHeader("Header3", "Value3");
- req->FollowDeferredRedirect(absl::nullopt /* removed_headers */,
- modified_headers);
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_EQ(OK, d.request_status());
- // Redirected request should also have modified headers.
- EXPECT_EQ(2, num_observed_requests);
- EXPECT_EQ("Value1", http_request.headers["Header1"]);
- EXPECT_EQ(1u, http_request.headers.count("Header2"));
- EXPECT_EQ("", http_request.headers["Header2"]);
- EXPECT_EQ("Value3", http_request.headers["Header3"]);
- }
- }
- TEST_F(URLRequestTestHTTP, DeferredRedirect_RemovedHeaders) {
- test_server::HttpRequest http_request;
- int num_observed_requests = 0;
- http_test_server()->RegisterRequestMonitor(
- base::BindLambdaForTesting([&](const test_server::HttpRequest& request) {
- http_request = request;
- ++num_observed_requests;
- }));
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- {
- GURL test_url(http_test_server()->GetURL("/redirect-test.html"));
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- test_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- // Set initial headers for the request.
- req->SetExtraRequestHeaderByName("Header1", "Value1", true /* overwrite */);
- req->SetExtraRequestHeaderByName("Header2", "Value2", true /* overwrite */);
- req->Start();
- d.RunUntilRedirect();
- // Initial request should have initial headers.
- EXPECT_EQ(1, d.received_redirect_count());
- EXPECT_EQ(1, num_observed_requests);
- EXPECT_EQ("Value1", http_request.headers["Header1"]);
- EXPECT_EQ("Value2", http_request.headers["Header2"]);
- // Keep Header1 and remove Header2.
- std::vector<std::string> removed_headers({"Header2"});
- req->FollowDeferredRedirect(removed_headers,
- absl::nullopt /* modified_headers */);
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_EQ(OK, d.request_status());
- // Redirected request should have modified headers.
- EXPECT_EQ(2, num_observed_requests);
- EXPECT_EQ("Value1", http_request.headers["Header1"]);
- EXPECT_EQ(0u, http_request.headers.count("Header2"));
- }
- }
- TEST_F(URLRequestTestHTTP, CancelDeferredRedirect) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- {
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/redirect-test.html"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilRedirect();
- EXPECT_EQ(1, d.received_redirect_count());
- req->Cancel();
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(0, d.bytes_received());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_EQ(ERR_ABORTED, d.request_status());
- }
- }
- TEST_F(URLRequestTestHTTP, VaryHeader) {
- ASSERT_TRUE(http_test_server()->Start());
- // Populate the cache.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/echoheadercache?foo"), DEFAULT_PRIORITY,
- &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- HttpRequestHeaders headers;
- headers.SetHeader("foo", "1");
- req->SetExtraRequestHeaders(headers);
- req->set_isolation_info(isolation_info1_);
- req->Start();
- d.RunUntilComplete();
- LoadTimingInfo load_timing_info;
- req->GetLoadTimingInfo(&load_timing_info);
- TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
- }
- // Expect a cache hit.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/echoheadercache?foo"), DEFAULT_PRIORITY,
- &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- HttpRequestHeaders headers;
- headers.SetHeader("foo", "1");
- req->SetExtraRequestHeaders(headers);
- req->set_isolation_info(isolation_info1_);
- req->Start();
- d.RunUntilComplete();
- EXPECT_TRUE(req->was_cached());
- LoadTimingInfo load_timing_info;
- req->GetLoadTimingInfo(&load_timing_info);
- TestLoadTimingCacheHitNoNetwork(load_timing_info);
- }
- // Expect a cache miss.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/echoheadercache?foo"), DEFAULT_PRIORITY,
- &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- HttpRequestHeaders headers;
- headers.SetHeader("foo", "2");
- req->SetExtraRequestHeaders(headers);
- req->set_isolation_info(isolation_info1_);
- req->Start();
- d.RunUntilComplete();
- EXPECT_FALSE(req->was_cached());
- LoadTimingInfo load_timing_info;
- req->GetLoadTimingInfo(&load_timing_info);
- TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
- }
- }
- TEST_F(URLRequestTestHTTP, BasicAuth) {
- ASSERT_TRUE(http_test_server()->Start());
- // populate the cache
- {
- TestDelegate d;
- d.set_credentials(AuthCredentials(kUser, kSecret));
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- http_test_server()->GetURL("/auth-basic"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->set_isolation_info(isolation_info1_);
- r->Start();
- d.RunUntilComplete();
- EXPECT_TRUE(d.data_received().find("user/secret") != std::string::npos);
- }
- // repeat request with end-to-end validation. since auth-basic results in a
- // cachable page, we expect this test to result in a 304. in which case, the
- // response should be fetched from the cache.
- {
- TestDelegate d;
- d.set_credentials(AuthCredentials(kUser, kSecret));
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- http_test_server()->GetURL("/auth-basic"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->SetLoadFlags(LOAD_VALIDATE_CACHE);
- r->set_isolation_info(isolation_info1_);
- r->Start();
- d.RunUntilComplete();
- EXPECT_TRUE(d.data_received().find("user/secret") != std::string::npos);
- // Should be the same cached document.
- EXPECT_TRUE(r->was_cached());
- }
- }
- // Check that Set-Cookie headers in 401 responses are respected.
- // http://crbug.com/6450
- TEST_F(URLRequestTestHTTP, BasicAuthWithCookies) {
- ASSERT_TRUE(http_test_server()->Start());
- GURL url_requiring_auth =
- http_test_server()->GetURL("/auth-basic?set-cookie-if-challenged");
- // Request a page that will give a 401 containing a Set-Cookie header.
- // Verify that when the transaction is restarted, it includes the new cookie.
- TestDelegate d;
- d.set_credentials(AuthCredentials(kUser, kSecret));
- std::unique_ptr<URLRequest> r =
- CreateFirstPartyRequest(default_context(), url_requiring_auth, &d);
- r->Start();
- d.RunUntilComplete();
- EXPECT_TRUE(d.data_received().find("user/secret") != std::string::npos);
- // Make sure we sent the cookie in the restarted transaction.
- EXPECT_TRUE(d.data_received().find("Cookie: got_challenged=true") !=
- std::string::npos);
- }
- // Same test as above, except this time the restart is initiated earlier
- // (without user intervention since identity is embedded in the URL).
- TEST_F(URLRequestTestHTTP, BasicAuthWithCredentialsWithCookies) {
- ASSERT_TRUE(http_test_server()->Start());
- GURL url_requiring_auth =
- http_test_server()->GetURL("/auth-basic?set-cookie-if-challenged");
- GURL::Replacements replacements;
- replacements.SetUsernameStr("user2");
- replacements.SetPasswordStr("secret");
- GURL url_with_identity = url_requiring_auth.ReplaceComponents(replacements);
- TestDelegate d;
- std::unique_ptr<URLRequest> r =
- CreateFirstPartyRequest(default_context(), url_with_identity, &d);
- r->Start();
- d.RunUntilComplete();
- EXPECT_TRUE(d.data_received().find("user2/secret") != std::string::npos);
- // Make sure we sent the cookie in the restarted transaction.
- EXPECT_TRUE(d.data_received().find("Cookie: got_challenged=true") !=
- std::string::npos);
- }
- TEST_F(URLRequestTestHTTP, BasicAuthWithCookiesCancelAuth) {
- ASSERT_TRUE(http_test_server()->Start());
- GURL url_requiring_auth =
- http_test_server()->GetURL("/auth-basic?set-cookie-if-challenged");
- // Request a page that will give a 401 containing a Set-Cookie header.
- // Verify that cookies are set before credentials are provided, and then
- // cancelling auth does not result in setting the cookies again.
- TestDelegate d;
- EXPECT_TRUE(GetAllCookies(&default_context()).empty());
- std::unique_ptr<URLRequest> r =
- CreateFirstPartyRequest(default_context(), url_requiring_auth, &d);
- r->Start();
- d.RunUntilAuthRequired();
- // Cookie should have been set.
- EXPECT_EQ(1, default_network_delegate().set_cookie_count());
- CookieList cookies = GetAllCookies(&default_context());
- ASSERT_EQ(1u, cookies.size());
- EXPECT_EQ("got_challenged", cookies[0].Name());
- EXPECT_EQ("true", cookies[0].Value());
- // Delete cookie.
- default_context().cookie_store()->DeleteAllAsync(
- CookieStore::DeleteCallback());
- // Cancel auth and continue the request.
- r->CancelAuth();
- d.RunUntilComplete();
- ASSERT_TRUE(r->response_headers());
- EXPECT_EQ(401, r->response_headers()->response_code());
- // Cookie should not have been set again.
- EXPECT_TRUE(GetAllCookies(&default_context()).empty());
- EXPECT_EQ(1, default_network_delegate().set_cookie_count());
- }
- // Tests the IsolationInfo is updated approiately on redirect.
- TEST_F(URLRequestTestHTTP, IsolationInfoUpdatedOnRedirect) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(
- net::features::kSplitCacheByNetworkIsolationKey);
- ASSERT_TRUE(http_test_server()->Start());
- GURL redirect_url =
- http_test_server()->GetURL("redirected.test", "/cachetime");
- GURL original_url = http_test_server()->GetURL(
- "original.test", "/server-redirect?" + redirect_url.spec());
- url::Origin original_origin = url::Origin::Create(original_url);
- url::Origin redirect_origin = url::Origin::Create(redirect_url);
- // Since transient IsolationInfos use opaque origins, need to create a single
- // consistent transient origin one for be used as the original and updated
- // info in the same test case.
- IsolationInfo transient_isolation_info = IsolationInfo::CreateTransient();
- const struct {
- IsolationInfo info_before_redirect;
- IsolationInfo expected_info_after_redirect;
- } kTestCases[] = {
- {IsolationInfo(), IsolationInfo()},
- {IsolationInfo::Create(IsolationInfo::RequestType::kMainFrame,
- original_origin, original_origin,
- SiteForCookies()),
- IsolationInfo::Create(IsolationInfo::RequestType::kMainFrame,
- redirect_origin, redirect_origin,
- SiteForCookies::FromOrigin(redirect_origin))},
- {IsolationInfo::Create(IsolationInfo::RequestType::kSubFrame,
- original_origin, original_origin,
- SiteForCookies::FromOrigin(original_origin)),
- IsolationInfo::Create(IsolationInfo::RequestType::kSubFrame,
- original_origin, redirect_origin,
- SiteForCookies::FromOrigin(original_origin))},
- {IsolationInfo::Create(IsolationInfo::RequestType::kOther,
- original_origin, original_origin,
- SiteForCookies()),
- IsolationInfo::Create(IsolationInfo::RequestType::kOther,
- original_origin, original_origin,
- SiteForCookies())},
- {transient_isolation_info, transient_isolation_info},
- };
- for (const auto& test_case : kTestCases) {
- // Populate the cache, using the expected final IsolationInfo.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- redirect_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->set_isolation_info(test_case.expected_info_after_redirect);
- r->Start();
- d.RunUntilComplete();
- EXPECT_THAT(d.request_status(), IsOk());
- }
- // Send a request using the initial IsolationInfo that should be redirected
- // to the cached url, and should use the cached entry if the NIK was
- // updated, except in the case the IsolationInfo's NIK was empty.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->set_isolation_info(test_case.info_before_redirect);
- r->Start();
- d.RunUntilComplete();
- EXPECT_THAT(d.request_status(), IsOk());
- EXPECT_EQ(redirect_url, r->url());
- EXPECT_EQ(!test_case.expected_info_after_redirect.network_isolation_key()
- .IsTransient(),
- r->was_cached());
- EXPECT_EQ(test_case.expected_info_after_redirect.request_type(),
- r->isolation_info().request_type());
- EXPECT_EQ(test_case.expected_info_after_redirect.top_frame_origin(),
- r->isolation_info().top_frame_origin());
- EXPECT_EQ(test_case.expected_info_after_redirect.frame_origin(),
- r->isolation_info().frame_origin());
- EXPECT_EQ(test_case.expected_info_after_redirect.network_isolation_key(),
- r->isolation_info().network_isolation_key());
- EXPECT_TRUE(test_case.expected_info_after_redirect.site_for_cookies()
- .IsEquivalent(r->isolation_info().site_for_cookies()));
- }
- }
- }
- // Tests that |key_auth_cache_by_network_isolation_key| is respected.
- TEST_F(URLRequestTestHTTP, AuthWithNetworkIsolationKey) {
- ASSERT_TRUE(http_test_server()->Start());
- for (bool key_auth_cache_by_network_isolation_key : {false, true}) {
- auto context_builder = CreateTestURLRequestContextBuilder();
- HttpNetworkSessionParams network_session_params;
- network_session_params
- .key_auth_cache_server_entries_by_network_isolation_key =
- key_auth_cache_by_network_isolation_key;
- context_builder->set_http_network_session_params(network_session_params);
- auto context = context_builder->Build();
- // Populate the auth cache using one NetworkIsolationKey.
- {
- TestDelegate d;
- GURL url(base::StringPrintf(
- "http://%s:%s@%s/auth-basic", base::UTF16ToASCII(kUser).c_str(),
- base::UTF16ToASCII(kSecret).c_str(),
- http_test_server()->host_port_pair().ToString().c_str()));
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->SetLoadFlags(LOAD_BYPASS_CACHE);
- r->set_isolation_info(isolation_info1_);
- r->Start();
- d.RunUntilComplete();
- EXPECT_THAT(d.request_status(), IsOk());
- ASSERT_TRUE(r->response_headers());
- EXPECT_EQ(200, r->response_headers()->response_code());
- EXPECT_TRUE(d.data_received().find("user/secret") != std::string::npos);
- }
- // Make a request with another NetworkIsolationKey. This may or may not use
- // the cached auth credentials, depending on whether or not the
- // HttpAuthCache is configured to respect the NetworkIsolationKey.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- http_test_server()->GetURL("/auth-basic"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->SetLoadFlags(LOAD_BYPASS_CACHE);
- r->set_isolation_info(isolation_info2_);
- r->Start();
- d.RunUntilComplete();
- EXPECT_THAT(d.request_status(), IsOk());
- ASSERT_TRUE(r->response_headers());
- if (key_auth_cache_by_network_isolation_key) {
- EXPECT_EQ(401, r->response_headers()->response_code());
- } else {
- EXPECT_EQ(200, r->response_headers()->response_code());
- }
- EXPECT_EQ(!key_auth_cache_by_network_isolation_key,
- d.data_received().find("user/secret") != std::string::npos);
- }
- }
- }
- TEST_F(URLRequestTest, ReportCookieActivity) {
- HttpTestServer test_server;
- ASSERT_TRUE(test_server.Start());
- RecordingNetLogObserver net_log_observer;
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<FilteringTestNetworkDelegate>());
- network_delegate.SetCookieFilter("not_stored_cookie");
- network_delegate.set_block_annotate_cookies();
- context_builder->set_net_log(net::NetLog::Get());
- auto context = context_builder->Build();
- // Make sure cookies blocked from being stored are caught, and those that are
- // accepted are reported as well.
- GURL set_cookie_test_url = test_server.GetURL(
- "/set-cookie?not_stored_cookie=true&"
- "stored_cookie=tasty"
- "&path_cookie=narrow;path=/set-cookie");
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req =
- CreateFirstPartyRequest(*context, set_cookie_test_url, &d);
- req->Start();
- d.RunUntilComplete();
- ASSERT_EQ(3u, req->maybe_stored_cookies().size());
- EXPECT_EQ("not_stored_cookie",
- req->maybe_stored_cookies()[0].cookie->Name());
- EXPECT_TRUE(req->maybe_stored_cookies()[0]
- .access_result.status.HasExactlyExclusionReasonsForTesting(
- {CookieInclusionStatus::EXCLUDE_USER_PREFERENCES}));
- EXPECT_EQ("stored_cookie", req->maybe_stored_cookies()[1].cookie->Name());
- EXPECT_TRUE(
- req->maybe_stored_cookies()[1].access_result.status.IsInclude());
- EXPECT_EQ("stored_cookie", req->maybe_stored_cookies()[1].cookie->Name());
- EXPECT_TRUE(
- req->maybe_stored_cookies()[2].access_result.status.IsInclude());
- EXPECT_EQ("path_cookie", req->maybe_stored_cookies()[2].cookie->Name());
- auto entries = net_log_observer.GetEntriesWithType(
- NetLogEventType::COOKIE_INCLUSION_STATUS);
- EXPECT_EQ(3u, entries.size());
- EXPECT_EQ("{\"domain\":\"" + set_cookie_test_url.host() +
- "\",\"name\":\"not_stored_cookie\",\"operation\":\"store\","
- "\"path\":\"/\",\"status\":\"EXCLUDE_USER_PREFERENCES, "
- "DO_NOT_WARN\"}",
- SerializeNetLogValueToJson(entries[0].params));
- EXPECT_EQ("{\"domain\":\"" + set_cookie_test_url.host() +
- "\",\"name\":\"stored_cookie\",\"operation\":\"store\","
- "\"path\":\"/\",\"status\":\"INCLUDE, DO_NOT_WARN\"}",
- SerializeNetLogValueToJson(entries[1].params));
- EXPECT_EQ(
- "{\"domain\":\"" + set_cookie_test_url.host() +
- "\",\"name\":\"path_cookie\",\"operation\":\"store\","
- "\"path\":\"/set-cookie\",\"status\":\"INCLUDE, DO_NOT_WARN\"}",
- SerializeNetLogValueToJson(entries[2].params));
- net_log_observer.Clear();
- }
- {
- TestDelegate d;
- // Make sure cookies blocked from being sent are caught.
- GURL test_url = test_server.GetURL("/echoheader?Cookie");
- std::unique_ptr<URLRequest> req =
- CreateFirstPartyRequest(*context, test_url, &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_TRUE(d.data_received().find("stored_cookie=tasty") ==
- std::string::npos);
- ASSERT_EQ(2u, req->maybe_sent_cookies().size());
- EXPECT_EQ("path_cookie", req->maybe_sent_cookies()[0].cookie.Name());
- EXPECT_TRUE(
- req->maybe_sent_cookies()[0]
- .access_result.status.HasExactlyExclusionReasonsForTesting(
- {net::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH,
- net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES}));
- EXPECT_EQ("stored_cookie", req->maybe_sent_cookies()[1].cookie.Name());
- EXPECT_TRUE(
- req->maybe_sent_cookies()[1]
- .access_result.status.HasExactlyExclusionReasonsForTesting(
- {net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES}));
- auto entries = net_log_observer.GetEntriesWithType(
- NetLogEventType::COOKIE_INCLUSION_STATUS);
- EXPECT_EQ(2u, entries.size());
- EXPECT_EQ("{\"domain\":\"" + set_cookie_test_url.host() +
- "\",\"name\":\"path_cookie\",\"operation\":\"send\",\"path\":"
- "\"/set-cookie\",\"status\":\"EXCLUDE_NOT_ON_PATH, "
- "EXCLUDE_USER_PREFERENCES, DO_NOT_WARN\"}",
- SerializeNetLogValueToJson(entries[0].params));
- EXPECT_EQ(
- "{\"domain\":\"" + set_cookie_test_url.host() +
- "\",\"name\":\"stored_cookie\",\"operation\":\"send\",\"path\":\"/"
- "\",\"status\":\"EXCLUDE_USER_PREFERENCES, DO_NOT_WARN\"}",
- SerializeNetLogValueToJson(entries[1].params));
- net_log_observer.Clear();
- }
- {
- TestDelegate d;
- // Ensure that the log does not contain cookie names when not set to collect
- // sensitive data.
- net_log_observer.SetObserverCaptureMode(NetLogCaptureMode::kDefault);
- GURL test_url = test_server.GetURL("/echoheader?Cookie");
- std::unique_ptr<URLRequest> req =
- CreateFirstPartyRequest(*context, test_url, &d);
- req->Start();
- d.RunUntilComplete();
- auto entries = net_log_observer.GetEntriesWithType(
- NetLogEventType::COOKIE_INCLUSION_STATUS);
- EXPECT_EQ(2u, entries.size());
- // Ensure that the potentially-sensitive |name|, |domain|, and |path| fields
- // are omitted, but other fields are logged as expected.
- EXPECT_EQ(
- "{\"operation\":\"send\",\"status\":\"EXCLUDE_NOT_ON_PATH, "
- "EXCLUDE_USER_PREFERENCES, DO_NOT_WARN\"}",
- SerializeNetLogValueToJson(entries[0].params));
- EXPECT_EQ(
- "{\"operation\":\"send\",\"status\":\"EXCLUDE_USER_PREFERENCES, "
- "DO_NOT_WARN\"}",
- SerializeNetLogValueToJson(entries[1].params));
- net_log_observer.Clear();
- net_log_observer.SetObserverCaptureMode(
- NetLogCaptureMode::kIncludeSensitive);
- }
- network_delegate.unset_block_annotate_cookies();
- {
- // Now with sending cookies re-enabled, it should actually be sent.
- TestDelegate d;
- GURL test_url = test_server.GetURL("/echoheader?Cookie");
- std::unique_ptr<URLRequest> req =
- CreateFirstPartyRequest(*context, test_url, &d);
- req->Start();
- d.RunUntilComplete();
- EXPECT_TRUE(d.data_received().find("stored_cookie=tasty") !=
- std::string::npos);
- ASSERT_EQ(2u, req->maybe_sent_cookies().size());
- EXPECT_EQ("path_cookie", req->maybe_sent_cookies()[0].cookie.Name());
- EXPECT_TRUE(req->maybe_sent_cookies()[0]
- .access_result.status.HasExactlyExclusionReasonsForTesting(
- {net::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH}));
- EXPECT_EQ("stored_cookie", req->maybe_sent_cookies()[1].cookie.Name());
- EXPECT_TRUE(req->maybe_sent_cookies()[1].access_result.status.IsInclude());
- auto entries = net_log_observer.GetEntriesWithType(
- NetLogEventType::COOKIE_INCLUSION_STATUS);
- EXPECT_EQ(2u, entries.size());
- EXPECT_EQ(
- "{\"domain\":\"" + set_cookie_test_url.host() +
- "\",\"name\":\"path_cookie\",\"operation\":\"send\",\"path\":\"/"
- "set-cookie\",\"status\":\"EXCLUDE_NOT_ON_PATH, DO_NOT_WARN\"}",
- SerializeNetLogValueToJson(entries[0].params));
- EXPECT_EQ("{\"domain\":\"" + set_cookie_test_url.host() +
- "\",\"name\":\"stored_cookie\",\"operation\":\"send\","
- "\"path\":\"/\",\"status\":\"INCLUDE, DO_NOT_WARN\"}",
- SerializeNetLogValueToJson(entries[1].params));
- net_log_observer.Clear();
- }
- }
- // Test that the SameSite-by-default CookieInclusionStatus warnings do not get
- // set if the cookie would have been rejected for other reasons.
- // Regression test for https://crbug.com/1027318.
- TEST_F(URLRequestTest, NoCookieInclusionStatusWarningIfWouldBeExcludedAnyway) {
- HttpTestServer test_server;
- ASSERT_TRUE(test_server.Start());
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<FilteringTestNetworkDelegate>());
- network_delegate.SetCookieFilter("blockeduserpreference");
- context_builder->SetCookieStore(std::make_unique<CookieMonster>(
- nullptr, nullptr, /*first_party_sets_enabled=*/false));
- auto context = context_builder->Build();
- auto& cm = *static_cast<CookieMonster*>(context->cookie_store());
- // Set cookies
- {
- // Attempt to set some cookies in a cross-site context without a SameSite
- // attribute. They should all be blocked. Only the one that would have been
- // included had it not been for the new SameSite features should have a
- // warning attached.
- TestDelegate d;
- GURL test_url = test_server.GetURL("this.example",
- "/set-cookie?blockeduserpreference=true&"
- "unspecifiedsamesite=1&"
- "invalidsecure=1;Secure");
- GURL cross_site_url = test_server.GetURL("other.example", "/");
- std::unique_ptr<URLRequest> req(context->CreateRequest(
- test_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_site_for_cookies(
- net::SiteForCookies::FromUrl(cross_site_url)); // cross-site context
- req->Start();
- d.RunUntilComplete();
- ASSERT_EQ(3u, req->maybe_stored_cookies().size());
- // Cookie blocked by user preferences is not warned about.
- EXPECT_EQ("blockeduserpreference",
- req->maybe_stored_cookies()[0].cookie->Name());
- // It doesn't pick up the EXCLUDE_UNSPECIFIED_TREATED_AS_LAX because it
- // doesn't even make it to the cookie store (it is filtered out beforehand).
- EXPECT_TRUE(req->maybe_stored_cookies()[0]
- .access_result.status.HasExactlyExclusionReasonsForTesting(
- {CookieInclusionStatus::EXCLUDE_USER_PREFERENCES}));
- EXPECT_FALSE(
- req->maybe_stored_cookies()[0].access_result.status.ShouldWarn());
- // Cookie that would be included had it not been for the new SameSite rules
- // is warned about.
- EXPECT_EQ("unspecifiedsamesite",
- req->maybe_stored_cookies()[1].cookie->Name());
- EXPECT_TRUE(req->maybe_stored_cookies()[1]
- .access_result.status.HasExactlyExclusionReasonsForTesting(
- {CookieInclusionStatus::
- EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX}));
- EXPECT_TRUE(req->maybe_stored_cookies()[1]
- .access_result.status.HasExactlyWarningReasonsForTesting(
- {CookieInclusionStatus::
- WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT}));
- // Cookie that is blocked because of invalid Secure attribute is not warned
- // about.
- EXPECT_EQ("invalidsecure", req->maybe_stored_cookies()[2].cookie->Name());
- EXPECT_TRUE(req->maybe_stored_cookies()[2]
- .access_result.status.HasExactlyExclusionReasonsForTesting(
- {CookieInclusionStatus::EXCLUDE_SECURE_ONLY,
- CookieInclusionStatus::
- EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX}));
- EXPECT_FALSE(
- req->maybe_stored_cookies()[2].access_result.status.ShouldWarn());
- }
- // Get cookies (blocked by user preference)
- network_delegate.set_block_annotate_cookies();
- {
- GURL url = test_server.GetURL("/");
- auto cookie1 = CanonicalCookie::Create(
- url, "cookienosamesite=1", base::Time::Now(), absl::nullopt,
- absl::nullopt /* cookie_partition_key */);
- base::RunLoop run_loop;
- CookieAccessResult access_result;
- cm.SetCanonicalCookieAsync(
- std::move(cookie1), url, CookieOptions::MakeAllInclusive(),
- base::BindLambdaForTesting([&](CookieAccessResult result) {
- access_result = result;
- run_loop.Quit();
- }));
- run_loop.Run();
- EXPECT_TRUE(access_result.status.IsInclude());
- TestDelegate d;
- GURL test_url = test_server.GetURL("/echoheader?Cookie");
- std::unique_ptr<URLRequest> req(context->CreateRequest(
- test_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- GURL cross_site_url = test_server.GetURL("other.example", "/");
- req->set_site_for_cookies(
- net::SiteForCookies::FromUrl(cross_site_url)); // cross-site context
- req->Start();
- d.RunUntilComplete();
- // No cookies were sent with the request because getting cookies is blocked.
- EXPECT_EQ("None", d.data_received());
- ASSERT_EQ(1u, req->maybe_sent_cookies().size());
- EXPECT_EQ("cookienosamesite", req->maybe_sent_cookies()[0].cookie.Name());
- EXPECT_TRUE(req->maybe_sent_cookies()[0]
- .access_result.status.HasExactlyExclusionReasonsForTesting(
- {CookieInclusionStatus::EXCLUDE_USER_PREFERENCES,
- CookieInclusionStatus::
- EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX}));
- // Cookie should not be warned about because it was blocked because of user
- // preferences.
- EXPECT_FALSE(
- req->maybe_sent_cookies()[0].access_result.status.ShouldWarn());
- }
- network_delegate.unset_block_annotate_cookies();
- // Get cookies
- {
- GURL url = test_server.GetURL("/");
- auto cookie2 = CanonicalCookie::Create(
- url, "cookiewithpath=1;path=/foo", base::Time::Now(), absl::nullopt,
- absl::nullopt /* cookie_partition_key */);
- base::RunLoop run_loop;
- // Note: cookie1 from the previous testcase is still in the cookie store.
- CookieAccessResult access_result;
- cm.SetCanonicalCookieAsync(
- std::move(cookie2), url, CookieOptions::MakeAllInclusive(),
- base::BindLambdaForTesting([&](CookieAccessResult result) {
- access_result = result;
- run_loop.Quit();
- }));
- run_loop.Run();
- EXPECT_TRUE(access_result.status.IsInclude());
- TestDelegate d;
- GURL test_url = test_server.GetURL("/echoheader?Cookie");
- std::unique_ptr<URLRequest> req(context->CreateRequest(
- test_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- GURL cross_site_url = test_server.GetURL("other.example", "/");
- req->set_site_for_cookies(
- net::SiteForCookies::FromUrl(cross_site_url)); // cross-site context
- req->Start();
- d.RunUntilComplete();
- // No cookies were sent with the request because they don't specify SameSite
- // and the request is cross-site.
- EXPECT_EQ("None", d.data_received());
- ASSERT_EQ(2u, req->maybe_sent_cookies().size());
- // Cookie excluded for other reasons is not warned about.
- // Note: this cookie is first because the cookies are sorted by path length
- // with longest first. See CookieSorter() in cookie_monster.cc.
- EXPECT_EQ("cookiewithpath", req->maybe_sent_cookies()[0].cookie.Name());
- EXPECT_TRUE(req->maybe_sent_cookies()[0]
- .access_result.status.HasExactlyExclusionReasonsForTesting(
- {CookieInclusionStatus::EXCLUDE_NOT_ON_PATH,
- CookieInclusionStatus::
- EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX}));
- EXPECT_FALSE(
- req->maybe_sent_cookies()[0].access_result.status.ShouldWarn());
- // Cookie that was only blocked because of unspecified SameSite should be
- // warned about.
- EXPECT_EQ("cookienosamesite", req->maybe_sent_cookies()[1].cookie.Name());
- EXPECT_TRUE(req->maybe_sent_cookies()[1]
- .access_result.status.HasExactlyExclusionReasonsForTesting(
- {CookieInclusionStatus::
- EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX}));
- EXPECT_TRUE(req->maybe_sent_cookies()[1]
- .access_result.status.HasExactlyWarningReasonsForTesting(
- {CookieInclusionStatus::
- WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT}));
- }
- }
- TEST_F(URLRequestTestHTTP, AuthChallengeCancelCookieCollect) {
- ASSERT_TRUE(http_test_server()->Start());
- GURL url_requiring_auth =
- http_test_server()->GetURL("/auth-basic?set-cookie-if-challenged");
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto filtering_network_delegate =
- std::make_unique<FilteringTestNetworkDelegate>();
- filtering_network_delegate->SetCookieFilter("got_challenged");
- context_builder->set_network_delegate(std::move(filtering_network_delegate));
- auto context = context_builder->Build();
- TestDelegate delegate;
- std::unique_ptr<URLRequest> request =
- CreateFirstPartyRequest(*context, url_requiring_auth, &delegate);
- request->Start();
- delegate.RunUntilAuthRequired();
- ASSERT_EQ(1u, request->maybe_stored_cookies().size());
- EXPECT_TRUE(request->maybe_stored_cookies()[0]
- .access_result.status.HasExactlyExclusionReasonsForTesting(
- {net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES}));
- EXPECT_EQ("got_challenged=true",
- request->maybe_stored_cookies()[0].cookie_string);
- // This shouldn't DCHECK-fail.
- request->CancelAuth();
- delegate.RunUntilComplete();
- }
- TEST_F(URLRequestTestHTTP, AuthChallengeWithFilteredCookies) {
- ASSERT_TRUE(http_test_server()->Start());
- GURL url_requiring_auth =
- http_test_server()->GetURL("/auth-basic?set-cookie-if-challenged");
- GURL url_requiring_auth_wo_cookies =
- http_test_server()->GetURL("/auth-basic");
- // Check maybe_stored_cookies is populated first round trip, and cleared on
- // the second.
- {
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto& filtering_network_delegate = *context_builder->set_network_delegate(
- std::make_unique<FilteringTestNetworkDelegate>());
- filtering_network_delegate.SetCookieFilter("got_challenged");
- auto context = context_builder->Build();
- TestDelegate delegate;
- std::unique_ptr<URLRequest> request =
- CreateFirstPartyRequest(*context, url_requiring_auth, &delegate);
- request->Start();
- delegate.RunUntilAuthRequired();
- // Make sure it was blocked once.
- EXPECT_EQ(1, filtering_network_delegate.blocked_set_cookie_count());
- // The number of cookies blocked from the most recent round trip.
- ASSERT_EQ(1u, request->maybe_stored_cookies().size());
- EXPECT_TRUE(
- request->maybe_stored_cookies()
- .front()
- .access_result.status.HasExactlyExclusionReasonsForTesting(
- {net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES}));
- // Now check the second round trip
- request->SetAuth(AuthCredentials(kUser, kSecret));
- delegate.RunUntilComplete();
- EXPECT_THAT(delegate.request_status(), IsOk());
- // There are DCHECKs in URLRequestHttpJob that would fail if
- // maybe_sent_cookies and maybe_stored_cookies were not cleared properly.
- // Make sure the cookie was actually filtered and not sent.
- EXPECT_EQ(std::string::npos,
- delegate.data_received().find("Cookie: got_challenged=true"));
- // The number of cookies that most recent round trip tried to set.
- ASSERT_EQ(0u, request->maybe_stored_cookies().size());
- }
- // Check maybe_sent_cookies on first round trip (and cleared for the second).
- {
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto& filtering_network_delegate = *context_builder->set_network_delegate(
- std::make_unique<FilteringTestNetworkDelegate>());
- filtering_network_delegate.set_block_annotate_cookies();
- context_builder->SetCookieStore(std::make_unique<CookieMonster>(
- nullptr, nullptr, /*first_party_sets_enabled=*/false));
- auto context = context_builder->Build();
- auto* cm = static_cast<CookieMonster*>(context->cookie_store());
- auto another_cookie = CanonicalCookie::Create(
- url_requiring_auth_wo_cookies, "another_cookie=true", base::Time::Now(),
- absl::nullopt /* server_time */,
- absl::nullopt /* cookie_partition_key */);
- cm->SetCanonicalCookieAsync(std::move(another_cookie),
- url_requiring_auth_wo_cookies,
- net::CookieOptions::MakeAllInclusive(),
- CookieStore::SetCookiesCallback());
- TestDelegate delegate;
- std::unique_ptr<URLRequest> request = CreateFirstPartyRequest(
- *context, url_requiring_auth_wo_cookies, &delegate);
- request->Start();
- delegate.RunUntilAuthRequired();
- ASSERT_EQ(1u, request->maybe_sent_cookies().size());
- EXPECT_EQ("another_cookie",
- request->maybe_sent_cookies().front().cookie.Name());
- EXPECT_EQ("true", request->maybe_sent_cookies().front().cookie.Value());
- EXPECT_TRUE(
- request->maybe_sent_cookies()
- .front()
- .access_result.status.HasExactlyExclusionReasonsForTesting(
- {net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES}));
- // Check maybe_sent_cookies on second roundtrip.
- request->set_maybe_sent_cookies({});
- cm->DeleteAllAsync(CookieStore::DeleteCallback());
- auto one_more_cookie = CanonicalCookie::Create(
- url_requiring_auth_wo_cookies, "one_more_cookie=true",
- base::Time::Now(), absl::nullopt /* server_time */,
- absl::nullopt /* cookie_partition_key */);
- cm->SetCanonicalCookieAsync(std::move(one_more_cookie),
- url_requiring_auth_wo_cookies,
- net::CookieOptions::MakeAllInclusive(),
- CookieStore::SetCookiesCallback());
- request->SetAuth(AuthCredentials(kUser, kSecret));
- delegate.RunUntilComplete();
- EXPECT_THAT(delegate.request_status(), IsOk());
- // There are DCHECKs in URLRequestHttpJob that would fail if
- // maybe_sent_cookies and maybe_stored_cookies were not cleared properly.
- // Make sure the cookie was actually filtered.
- EXPECT_EQ(std::string::npos,
- delegate.data_received().find("Cookie: one_more_cookie=true"));
- // got_challenged was set after the first request and blocked on the second,
- // so it should only have been blocked this time
- EXPECT_EQ(2, filtering_network_delegate.blocked_annotate_cookies_count());
- // // The number of cookies blocked from the most recent round trip.
- ASSERT_EQ(1u, request->maybe_sent_cookies().size());
- EXPECT_EQ("one_more_cookie",
- request->maybe_sent_cookies().front().cookie.Name());
- EXPECT_TRUE(
- request->maybe_sent_cookies()
- .front()
- .access_result.status.HasExactlyExclusionReasonsForTesting(
- {net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES}));
- }
- }
- // Tests that load timing works as expected with auth and the cache.
- TEST_F(URLRequestTestHTTP, BasicAuthLoadTiming) {
- ASSERT_TRUE(http_test_server()->Start());
- // populate the cache
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- http_test_server()->GetURL("/auth-basic"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->set_isolation_info(isolation_info1_);
- r->Start();
- d.RunUntilAuthRequired();
- LoadTimingInfo load_timing_info_before_auth;
- r->GetLoadTimingInfo(&load_timing_info_before_auth);
- TestLoadTimingNotReused(load_timing_info_before_auth,
- CONNECT_TIMING_HAS_DNS_TIMES);
- r->SetAuth(AuthCredentials(kUser, kSecret));
- d.RunUntilComplete();
- EXPECT_TRUE(d.data_received().find("user/secret") != std::string::npos);
- LoadTimingInfo load_timing_info;
- r->GetLoadTimingInfo(&load_timing_info);
- // The test server does not support keep alive sockets, so the second
- // request with auth should use a new socket.
- TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
- EXPECT_NE(load_timing_info_before_auth.socket_log_id,
- load_timing_info.socket_log_id);
- EXPECT_LE(load_timing_info_before_auth.receive_headers_end,
- load_timing_info.connect_timing.connect_start);
- }
- // Repeat request with end-to-end validation. Since auth-basic results in a
- // cachable page, we expect this test to result in a 304. In which case, the
- // response should be fetched from the cache.
- {
- TestDelegate d;
- d.set_credentials(AuthCredentials(kUser, kSecret));
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- http_test_server()->GetURL("/auth-basic"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->SetLoadFlags(LOAD_VALIDATE_CACHE);
- r->set_isolation_info(isolation_info1_);
- r->Start();
- d.RunUntilComplete();
- EXPECT_TRUE(d.data_received().find("user/secret") != std::string::npos);
- // Should be the same cached document.
- EXPECT_TRUE(r->was_cached());
- // Since there was a request that went over the wire, the load timing
- // information should include connection times.
- LoadTimingInfo load_timing_info;
- r->GetLoadTimingInfo(&load_timing_info);
- TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
- }
- }
- // In this test, we do a POST which the server will 302 redirect.
- // The subsequent transaction should use GET, and should not send the
- // Content-Type header.
- // http://code.google.com/p/chromium/issues/detail?id=843
- TEST_F(URLRequestTestHTTP, Post302RedirectGet) {
- ASSERT_TRUE(http_test_server()->Start());
- const char kData[] = "hello world";
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/redirect-to-echoall"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_method("POST");
- req->set_upload(CreateSimpleUploadData(kData));
- // Set headers (some of which are specific to the POST).
- HttpRequestHeaders headers;
- headers.SetHeader("Content-Type",
- "multipart/form-data;"
- "boundary=----WebKitFormBoundaryAADeAA+NAAWMAAwZ");
- headers.SetHeader("Accept",
- "text/xml,application/xml,application/xhtml+xml,"
- "text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
- headers.SetHeader("Accept-Language", "en-US,en");
- headers.SetHeader("Accept-Charset", "ISO-8859-1,*,utf-8");
- headers.SetHeader("Content-Length", "11");
- headers.SetHeader("Origin", "http://localhost:1337/");
- req->SetExtraRequestHeaders(headers);
- req->Start();
- d.RunUntilComplete();
- std::string mime_type;
- req->GetMimeType(&mime_type);
- EXPECT_EQ("text/html", mime_type);
- const std::string& data = d.data_received();
- // Check that the post-specific headers were stripped:
- EXPECT_FALSE(ContainsString(data, "Content-Length:"));
- EXPECT_FALSE(ContainsString(data, "Content-Type:"));
- EXPECT_FALSE(ContainsString(data, "Origin:"));
- // These extra request headers should not have been stripped.
- EXPECT_TRUE(ContainsString(data, "Accept:"));
- EXPECT_TRUE(ContainsString(data, "Accept-Language:"));
- EXPECT_TRUE(ContainsString(data, "Accept-Charset:"));
- }
- // The following tests check that we handle mutating the request for HTTP
- // redirects as expected.
- // See https://crbug.com/56373, https://crbug.com/102130, and
- // https://crbug.com/465517.
- TEST_F(URLRequestTestHTTP, Redirect301Tests) {
- ASSERT_TRUE(http_test_server()->Start());
- const GURL url = http_test_server()->GetURL("/redirect301-to-echo");
- const GURL https_redirect_url =
- http_test_server()->GetURL("/redirect301-to-https");
- HTTPRedirectMethodTest(url, "POST", "GET", true);
- HTTPRedirectMethodTest(url, "PUT", "PUT", true);
- HTTPRedirectMethodTest(url, "HEAD", "HEAD", false);
- HTTPRedirectOriginHeaderTest(url, "GET", "GET",
- url.DeprecatedGetOriginAsURL().spec());
- HTTPRedirectOriginHeaderTest(https_redirect_url, "GET", "GET", "null");
- HTTPRedirectOriginHeaderTest(url, "POST", "GET", std::string());
- HTTPRedirectOriginHeaderTest(https_redirect_url, "POST", "GET",
- std::string());
- HTTPRedirectOriginHeaderTest(url, "PUT", "PUT",
- url.DeprecatedGetOriginAsURL().spec());
- HTTPRedirectOriginHeaderTest(https_redirect_url, "PUT", "PUT", "null");
- }
- TEST_F(URLRequestTestHTTP, Redirect302Tests) {
- ASSERT_TRUE(http_test_server()->Start());
- const GURL url = http_test_server()->GetURL("/redirect302-to-echo");
- const GURL https_redirect_url =
- http_test_server()->GetURL("/redirect302-to-https");
- HTTPRedirectMethodTest(url, "POST", "GET", true);
- HTTPRedirectMethodTest(url, "PUT", "PUT", true);
- HTTPRedirectMethodTest(url, "HEAD", "HEAD", false);
- HTTPRedirectOriginHeaderTest(url, "GET", "GET",
- url.DeprecatedGetOriginAsURL().spec());
- HTTPRedirectOriginHeaderTest(https_redirect_url, "GET", "GET", "null");
- HTTPRedirectOriginHeaderTest(url, "POST", "GET", std::string());
- HTTPRedirectOriginHeaderTest(https_redirect_url, "POST", "GET",
- std::string());
- HTTPRedirectOriginHeaderTest(url, "PUT", "PUT",
- url.DeprecatedGetOriginAsURL().spec());
- HTTPRedirectOriginHeaderTest(https_redirect_url, "PUT", "PUT", "null");
- }
- TEST_F(URLRequestTestHTTP, Redirect303Tests) {
- ASSERT_TRUE(http_test_server()->Start());
- const GURL url = http_test_server()->GetURL("/redirect303-to-echo");
- const GURL https_redirect_url =
- http_test_server()->GetURL("/redirect303-to-https");
- HTTPRedirectMethodTest(url, "POST", "GET", true);
- HTTPRedirectMethodTest(url, "PUT", "GET", true);
- HTTPRedirectMethodTest(url, "HEAD", "HEAD", false);
- HTTPRedirectOriginHeaderTest(url, "CONNECT", "GET", std::string());
- HTTPRedirectOriginHeaderTest(https_redirect_url, "CONNECT", "GET",
- std::string());
- HTTPRedirectOriginHeaderTest(url, "DELETE", "GET", std::string());
- HTTPRedirectOriginHeaderTest(https_redirect_url, "DELETE", "GET",
- std::string());
- HTTPRedirectOriginHeaderTest(url, "GET", "GET",
- url.DeprecatedGetOriginAsURL().spec());
- HTTPRedirectOriginHeaderTest(https_redirect_url, "GET", "GET", "null");
- HTTPRedirectOriginHeaderTest(url, "HEAD", "HEAD",
- url.DeprecatedGetOriginAsURL().spec());
- HTTPRedirectOriginHeaderTest(https_redirect_url, "HEAD", "HEAD", "null");
- HTTPRedirectOriginHeaderTest(url, "OPTIONS", "GET", std::string());
- HTTPRedirectOriginHeaderTest(https_redirect_url, "OPTIONS", "GET",
- std::string());
- HTTPRedirectOriginHeaderTest(url, "POST", "GET", std::string());
- HTTPRedirectOriginHeaderTest(https_redirect_url, "POST", "GET",
- std::string());
- HTTPRedirectOriginHeaderTest(url, "PUT", "GET", std::string());
- HTTPRedirectOriginHeaderTest(https_redirect_url, "PUT", "GET", std::string());
- }
- TEST_F(URLRequestTestHTTP, Redirect307Tests) {
- ASSERT_TRUE(http_test_server()->Start());
- const GURL url = http_test_server()->GetURL("/redirect307-to-echo");
- const GURL https_redirect_url =
- http_test_server()->GetURL("/redirect307-to-https");
- HTTPRedirectMethodTest(url, "POST", "POST", true);
- HTTPRedirectMethodTest(url, "PUT", "PUT", true);
- HTTPRedirectMethodTest(url, "HEAD", "HEAD", false);
- HTTPRedirectOriginHeaderTest(url, "GET", "GET",
- url.DeprecatedGetOriginAsURL().spec());
- HTTPRedirectOriginHeaderTest(https_redirect_url, "GET", "GET", "null");
- HTTPRedirectOriginHeaderTest(url, "POST", "POST",
- url.DeprecatedGetOriginAsURL().spec());
- HTTPRedirectOriginHeaderTest(https_redirect_url, "POST", "POST", "null");
- HTTPRedirectOriginHeaderTest(url, "PUT", "PUT",
- url.DeprecatedGetOriginAsURL().spec());
- HTTPRedirectOriginHeaderTest(https_redirect_url, "PUT", "PUT", "null");
- }
- TEST_F(URLRequestTestHTTP, Redirect308Tests) {
- ASSERT_TRUE(http_test_server()->Start());
- const GURL url = http_test_server()->GetURL("/redirect308-to-echo");
- const GURL https_redirect_url =
- http_test_server()->GetURL("/redirect308-to-https");
- HTTPRedirectMethodTest(url, "POST", "POST", true);
- HTTPRedirectMethodTest(url, "PUT", "PUT", true);
- HTTPRedirectMethodTest(url, "HEAD", "HEAD", false);
- HTTPRedirectOriginHeaderTest(url, "GET", "GET",
- url.DeprecatedGetOriginAsURL().spec());
- HTTPRedirectOriginHeaderTest(https_redirect_url, "GET", "GET", "null");
- HTTPRedirectOriginHeaderTest(url, "POST", "POST",
- url.DeprecatedGetOriginAsURL().spec());
- HTTPRedirectOriginHeaderTest(https_redirect_url, "POST", "POST", "null");
- HTTPRedirectOriginHeaderTest(url, "PUT", "PUT",
- url.DeprecatedGetOriginAsURL().spec());
- HTTPRedirectOriginHeaderTest(https_redirect_url, "PUT", "PUT", "null");
- }
- // Make sure that 308 responses without bodies are not treated as redirects.
- // Certain legacy apis that pre-date the response code expect this behavior
- // (Like Google Drive).
- TEST_F(URLRequestTestHTTP, NoRedirectOn308WithoutLocationHeader) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- const GURL url = http_test_server()->GetURL("/308-without-location-header");
- std::unique_ptr<URLRequest> request(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- request->Start();
- d.RunUntilComplete();
- EXPECT_EQ(OK, d.request_status());
- EXPECT_EQ(0, d.received_redirect_count());
- EXPECT_EQ(308, request->response_headers()->response_code());
- EXPECT_EQ("This is not a redirect.", d.data_received());
- }
- TEST_F(URLRequestTestHTTP, Redirect302PreserveReferenceFragment) {
- ASSERT_TRUE(http_test_server()->Start());
- GURL original_url(
- http_test_server()->GetURL("/redirect302-to-echo#fragment"));
- GURL expected_url(http_test_server()->GetURL("/echo#fragment"));
- TestDelegate d;
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- d.RunUntilComplete();
- EXPECT_EQ(2U, r->url_chain().size());
- EXPECT_EQ(OK, d.request_status());
- EXPECT_EQ(original_url, r->original_url());
- EXPECT_EQ(expected_url, r->url());
- }
- TEST_F(URLRequestTestHTTP, RedirectWithFilteredCookies) {
- ASSERT_TRUE(http_test_server()->Start());
- // FilteringTestNetworkDelegate filters by name, so the names of the two
- // cookies have to be the same. The values have been set to different strings
- // (the value of the server-redirect cookies is "true" and set-cookie is
- // "other") to differentiate between the two round trips.
- GURL redirect_to(
- http_test_server()->GetURL("/set-cookie?server-redirect=other"));
- GURL original_url(http_test_server()->GetURL("/server-redirect-with-cookie?" +
- redirect_to.spec()));
- GURL original_url_wo_cookie(
- http_test_server()->GetURL("/server-redirect?" + redirect_to.spec()));
- // Check maybe_stored_cookies on first round trip.
- {
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto& filtering_network_delegate = *context_builder->set_network_delegate(
- std::make_unique<FilteringTestNetworkDelegate>());
- filtering_network_delegate.SetCookieFilter(
- "server-redirect"); // Filter the cookie server-redirect sets.
- auto context = context_builder->Build();
- TestDelegate delegate;
- std::unique_ptr<URLRequest> request =
- CreateFirstPartyRequest(*context, original_url, &delegate);
- request->Start();
- delegate.RunUntilRedirect();
- // Make sure it was blocked once.
- EXPECT_EQ(1, filtering_network_delegate.blocked_set_cookie_count());
- // The number of cookies blocked from the most recent round trip.
- ASSERT_EQ(1u, request->maybe_stored_cookies().size());
- EXPECT_EQ("server-redirect",
- request->maybe_stored_cookies().front().cookie->Name());
- EXPECT_EQ("true", request->maybe_stored_cookies().front().cookie->Value());
- EXPECT_TRUE(
- request->maybe_stored_cookies()
- .front()
- .access_result.status.HasExactlyExclusionReasonsForTesting(
- {net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES}));
- // Check maybe_stored_cookies on second round trip (and clearing from the
- // first).
- request->FollowDeferredRedirect(absl::nullopt, absl::nullopt);
- delegate.RunUntilComplete();
- EXPECT_THAT(delegate.request_status(), IsOk());
- // There are DCHECKs in URLRequestHttpJob that would fail if
- // maybe_sent_cookies and maybe_stored_cookies we not cleared properly.
- // Make sure it was blocked twice.
- EXPECT_EQ(2, filtering_network_delegate.blocked_set_cookie_count());
- // The number of cookies blocked from the most recent round trip.
- ASSERT_EQ(1u, request->maybe_stored_cookies().size());
- EXPECT_EQ("server-redirect",
- request->maybe_stored_cookies().front().cookie->Name());
- EXPECT_EQ("other", request->maybe_stored_cookies().front().cookie->Value());
- EXPECT_TRUE(
- request->maybe_stored_cookies()
- .front()
- .access_result.status.HasExactlyExclusionReasonsForTesting(
- {net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES}));
- }
- // Check maybe_sent_cookies on first round trip.
- {
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto& filtering_network_delegate = *context_builder->set_network_delegate(
- std::make_unique<FilteringTestNetworkDelegate>());
- filtering_network_delegate.set_block_annotate_cookies();
- context_builder->SetCookieStore(std::make_unique<CookieMonster>(
- nullptr, nullptr, /*first_party_sets_enabled=*/false));
- auto context = context_builder->Build();
- auto* cm = static_cast<CookieMonster*>(context->cookie_store());
- auto another_cookie = CanonicalCookie::Create(
- original_url, "another_cookie=true", base::Time::Now(),
- absl::nullopt /* server_time */,
- absl::nullopt /* cookie_partition_key */);
- cm->SetCanonicalCookieAsync(std::move(another_cookie), original_url,
- net::CookieOptions::MakeAllInclusive(),
- CookieStore::SetCookiesCallback());
- TestDelegate delegate;
- std::unique_ptr<URLRequest> request =
- CreateFirstPartyRequest(*context, original_url_wo_cookie, &delegate);
- request->Start();
- delegate.RunUntilRedirect();
- ASSERT_EQ(1u, request->maybe_sent_cookies().size());
- EXPECT_EQ("another_cookie",
- request->maybe_sent_cookies().front().cookie.Name());
- EXPECT_TRUE(
- request->maybe_sent_cookies()
- .front()
- .access_result.status.HasExactlyExclusionReasonsForTesting(
- {net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES}));
- // Check maybe_sent_cookies on second round trip
- request->set_maybe_sent_cookies({});
- cm->DeleteAllAsync(CookieStore::DeleteCallback());
- auto one_more_cookie = CanonicalCookie::Create(
- original_url_wo_cookie, "one_more_cookie=true", base::Time::Now(),
- absl::nullopt /* server_time */,
- absl::nullopt /* cookie_partition_key */);
- cm->SetCanonicalCookieAsync(std::move(one_more_cookie),
- original_url_wo_cookie,
- net::CookieOptions::MakeAllInclusive(),
- CookieStore::SetCookiesCallback());
- request->FollowDeferredRedirect(absl::nullopt, absl::nullopt);
- delegate.RunUntilComplete();
- EXPECT_THAT(delegate.request_status(), IsOk());
- // There are DCHECKs in URLRequestHttpJob that would fail if
- // maybe_sent_cookies and maybe_stored_cookies we not cleared properly.
- EXPECT_EQ(2, filtering_network_delegate.blocked_annotate_cookies_count());
- // The number of cookies blocked from the most recent round trip.
- ASSERT_EQ(1u, request->maybe_sent_cookies().size());
- EXPECT_EQ("one_more_cookie",
- request->maybe_sent_cookies().front().cookie.Name());
- EXPECT_EQ("true", request->maybe_sent_cookies().front().cookie.Value());
- EXPECT_TRUE(
- request->maybe_sent_cookies()
- .front()
- .access_result.status.HasExactlyExclusionReasonsForTesting(
- {net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES}));
- }
- }
- TEST_F(URLRequestTestHTTP, RedirectPreserveFirstPartyURL) {
- ASSERT_TRUE(http_test_server()->Start());
- GURL url(http_test_server()->GetURL("/redirect302-to-echo"));
- GURL first_party_url("http://example.com");
- TestDelegate d;
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->set_site_for_cookies(SiteForCookies::FromUrl(first_party_url));
- r->Start();
- d.RunUntilComplete();
- EXPECT_EQ(2U, r->url_chain().size());
- EXPECT_EQ(OK, d.request_status());
- EXPECT_TRUE(SiteForCookies::FromUrl(first_party_url)
- .IsEquivalent(r->site_for_cookies()));
- }
- TEST_F(URLRequestTestHTTP, RedirectUpdateFirstPartyURL) {
- ASSERT_TRUE(http_test_server()->Start());
- GURL url(http_test_server()->GetURL("/redirect302-to-echo"));
- GURL original_first_party_url("http://example.com");
- GURL expected_first_party_url(http_test_server()->GetURL("/echo"));
- TestDelegate d;
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->set_site_for_cookies(SiteForCookies::FromUrl(original_first_party_url));
- r->set_first_party_url_policy(
- RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT);
- r->Start();
- d.RunUntilComplete();
- EXPECT_EQ(2U, r->url_chain().size());
- EXPECT_EQ(OK, d.request_status());
- EXPECT_TRUE(SiteForCookies::FromUrl(expected_first_party_url)
- .IsEquivalent(r->site_for_cookies()));
- }
- TEST_F(URLRequestTestHTTP, InterceptPost302RedirectGet) {
- ASSERT_TRUE(http_test_server()->Start());
- const char kData[] = "hello world";
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_method("POST");
- req->set_upload(CreateSimpleUploadData(kData));
- HttpRequestHeaders headers;
- headers.SetHeader(HttpRequestHeaders::kContentLength,
- base::NumberToString(std::size(kData) - 1));
- req->SetExtraRequestHeaders(headers);
- std::unique_ptr<URLRequestRedirectJob> job =
- std::make_unique<URLRequestRedirectJob>(
- req.get(), http_test_server()->GetURL("/echo"),
- RedirectUtil::ResponseCode::REDIRECT_302_FOUND, "Very Good Reason");
- TestScopedURLInterceptor interceptor(req->url(), std::move(job));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ("GET", req->method());
- }
- TEST_F(URLRequestTestHTTP, InterceptPost307RedirectPost) {
- ASSERT_TRUE(http_test_server()->Start());
- const char kData[] = "hello world";
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_method("POST");
- req->set_upload(CreateSimpleUploadData(kData));
- HttpRequestHeaders headers;
- headers.SetHeader(HttpRequestHeaders::kContentLength,
- base::NumberToString(std::size(kData) - 1));
- req->SetExtraRequestHeaders(headers);
- std::unique_ptr<URLRequestRedirectJob> job =
- std::make_unique<URLRequestRedirectJob>(
- req.get(), http_test_server()->GetURL("/echo"),
- RedirectUtil::ResponseCode::REDIRECT_307_TEMPORARY_REDIRECT,
- "Very Good Reason");
- TestScopedURLInterceptor interceptor(req->url(), std::move(job));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ("POST", req->method());
- EXPECT_EQ(kData, d.data_received());
- }
- // Check that default A-L header is sent.
- TEST_F(URLRequestTestHTTP, DefaultAcceptLanguage) {
- ASSERT_TRUE(http_test_server()->Start());
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_http_user_agent_settings(
- std::make_unique<StaticHttpUserAgentSettings>("en", std::string()));
- auto context = context_builder->Build();
- TestDelegate d;
- std::unique_ptr<URLRequest> req(context->CreateRequest(
- http_test_server()->GetURL("/echoheader?Accept-Language"),
- DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ("en", d.data_received());
- }
- // Check that an empty A-L header is not sent. http://crbug.com/77365.
- TEST_F(URLRequestTestHTTP, EmptyAcceptLanguage) {
- ASSERT_TRUE(http_test_server()->Start());
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_http_user_agent_settings(
- std::make_unique<StaticHttpUserAgentSettings>(std::string(),
- std::string()));
- auto context = context_builder->Build();
- TestDelegate d;
- std::unique_ptr<URLRequest> req(context->CreateRequest(
- http_test_server()->GetURL("/echoheader?Accept-Language"),
- DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ("None", d.data_received());
- }
- // Check that if request overrides the A-L header, the default is not appended.
- // See http://crbug.com/20894
- TEST_F(URLRequestTestHTTP, OverrideAcceptLanguage) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/echoheader?Accept-Language"),
- DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- HttpRequestHeaders headers;
- headers.SetHeader(HttpRequestHeaders::kAcceptLanguage, "ru");
- req->SetExtraRequestHeaders(headers);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(std::string("ru"), d.data_received());
- }
- // Check that default A-E header is sent.
- TEST_F(URLRequestTestHTTP, DefaultAcceptEncoding) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/echoheader?Accept-Encoding"),
- DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- HttpRequestHeaders headers;
- req->SetExtraRequestHeaders(headers);
- req->Start();
- d.RunUntilComplete();
- EXPECT_TRUE(ContainsString(d.data_received(), "gzip"));
- }
- // Check that it's possible to override the default A-E header.
- TEST_F(URLRequestTestHTTP, DefaultAcceptEncodingOverriden) {
- ASSERT_TRUE(http_test_server()->Start());
- struct {
- base::flat_set<net::SourceStream::SourceType> accepted_types;
- const char* expected_accept_encoding;
- } tests[] = {{{net::SourceStream::SourceType::TYPE_DEFLATE}, "deflate"},
- {{}, "None"},
- {{net::SourceStream::SourceType::TYPE_GZIP}, "gzip"},
- {{net::SourceStream::SourceType::TYPE_GZIP,
- net::SourceStream::SourceType::TYPE_DEFLATE},
- "gzip, deflate"}};
- for (auto test : tests) {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/echoheader?Accept-Encoding"),
- DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_accepted_stream_types(test.accepted_types);
- req->Start();
- d.RunUntilComplete();
- EXPECT_STRCASEEQ(d.data_received().c_str(), test.expected_accept_encoding);
- }
- }
- // Check that if request overrides the A-E header, the default is not appended.
- // See http://crbug.com/47381
- TEST_F(URLRequestTestHTTP, OverrideAcceptEncoding) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/echoheader?Accept-Encoding"),
- DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- HttpRequestHeaders headers;
- headers.SetHeader(HttpRequestHeaders::kAcceptEncoding, "identity");
- req->SetExtraRequestHeaders(headers);
- req->Start();
- d.RunUntilComplete();
- EXPECT_FALSE(ContainsString(d.data_received(), "gzip"));
- EXPECT_TRUE(ContainsString(d.data_received(), "identity"));
- }
- // Check that setting the A-C header sends the proper header.
- TEST_F(URLRequestTestHTTP, SetAcceptCharset) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/echoheader?Accept-Charset"),
- DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- HttpRequestHeaders headers;
- headers.SetHeader(HttpRequestHeaders::kAcceptCharset, "koi-8r");
- req->SetExtraRequestHeaders(headers);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(std::string("koi-8r"), d.data_received());
- }
- // Check that default User-Agent header is sent.
- TEST_F(URLRequestTestHTTP, DefaultUserAgent) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/echoheader?User-Agent"), DEFAULT_PRIORITY,
- &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(default_context().http_user_agent_settings()->GetUserAgent(),
- d.data_received());
- }
- // Check that if request overrides the User-Agent header,
- // the default is not appended.
- // TODO(crbug.com/564656) This test is flaky on iOS.
- #if BUILDFLAG(IS_IOS)
- #define MAYBE_OverrideUserAgent FLAKY_OverrideUserAgent
- #else
- #define MAYBE_OverrideUserAgent OverrideUserAgent
- #endif
- TEST_F(URLRequestTestHTTP, MAYBE_OverrideUserAgent) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/echoheader?User-Agent"), DEFAULT_PRIORITY,
- &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- HttpRequestHeaders headers;
- headers.SetHeader(HttpRequestHeaders::kUserAgent, "Lynx (textmode)");
- req->SetExtraRequestHeaders(headers);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(std::string("Lynx (textmode)"), d.data_received());
- }
- // Check that a NULL HttpUserAgentSettings causes the corresponding empty
- // User-Agent header to be sent but does not send the Accept-Language and
- // Accept-Charset headers.
- TEST_F(URLRequestTestHTTP, EmptyHttpUserAgentSettings) {
- ASSERT_TRUE(http_test_server()->Start());
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_http_user_agent_settings(nullptr);
- auto context = context_builder->Build();
- struct {
- const char* request;
- const char* expected_response;
- } tests[] = {{"/echoheader?Accept-Language", "None"},
- {"/echoheader?Accept-Charset", "None"},
- {"/echoheader?User-Agent", ""}};
- for (const auto& test : tests) {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(context->CreateRequest(
- http_test_server()->GetURL(test.request), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(test.expected_response, d.data_received())
- << " Request = \"" << test.request << "\"";
- }
- }
- // Make sure that URLRequest passes on its priority updates to
- // newly-created jobs after the first one.
- TEST_F(URLRequestTestHTTP, SetSubsequentJobPriority) {
- GURL initial_url("http://foo.test/");
- GURL redirect_url("http://bar.test/");
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- initial_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- EXPECT_EQ(DEFAULT_PRIORITY, req->priority());
- std::unique_ptr<URLRequestRedirectJob> redirect_job =
- std::make_unique<URLRequestRedirectJob>(
- req.get(), redirect_url,
- RedirectUtil::ResponseCode::REDIRECT_302_FOUND, "Very Good Reason");
- auto interceptor = std::make_unique<TestScopedURLInterceptor>(
- initial_url, std::move(redirect_job));
- req->SetPriority(LOW);
- req->Start();
- EXPECT_TRUE(req->is_pending());
- d.RunUntilRedirect();
- interceptor.reset();
- RequestPriority job_priority;
- std::unique_ptr<URLRequestJob> job =
- std::make_unique<PriorityMonitoringURLRequestJob>(req.get(),
- &job_priority);
- interceptor =
- std::make_unique<TestScopedURLInterceptor>(redirect_url, std::move(job));
- // Should trigger |job| to be started.
- req->FollowDeferredRedirect(absl::nullopt /* removed_headers */,
- absl::nullopt /* modified_headers */);
- d.RunUntilComplete();
- EXPECT_EQ(LOW, job_priority);
- }
- // Check that creating a network request while entering/exiting suspend mode
- // fails as it should. This is the only case where an HttpTransactionFactory
- // does not return an HttpTransaction.
- TEST_F(URLRequestTestHTTP, NetworkSuspendTest) {
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->SetCreateHttpTransactionFactoryCallback(
- base::BindOnce([](HttpNetworkSession* session) {
- // Create a new HttpNetworkLayer that thinks it's suspended.
- auto network_layer = std::make_unique<HttpNetworkLayer>(session);
- network_layer->OnSuspend();
- std::unique_ptr<HttpTransactionFactory> factory =
- std::make_unique<HttpCache>(std::move(network_layer),
- HttpCache::DefaultBackend::InMemory(0));
- return factory;
- }));
- auto context = context_builder->Build();
- TestDelegate d;
- std::unique_ptr<URLRequest> req(
- context->CreateRequest(GURL("http://127.0.0.1/"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- EXPECT_TRUE(d.request_failed());
- EXPECT_EQ(ERR_NETWORK_IO_SUSPENDED, d.request_status());
- }
- namespace {
- // HttpTransactionFactory that synchronously fails to create transactions.
- class FailingHttpTransactionFactory : public HttpTransactionFactory {
- public:
- explicit FailingHttpTransactionFactory(HttpNetworkSession* network_session)
- : network_session_(network_session) {}
- FailingHttpTransactionFactory(const FailingHttpTransactionFactory&) = delete;
- FailingHttpTransactionFactory& operator=(
- const FailingHttpTransactionFactory&) = delete;
- ~FailingHttpTransactionFactory() override = default;
- // HttpTransactionFactory methods:
- int CreateTransaction(RequestPriority priority,
- std::unique_ptr<HttpTransaction>* trans) override {
- return ERR_FAILED;
- }
- HttpCache* GetCache() override { return nullptr; }
- HttpNetworkSession* GetSession() override { return network_session_; }
- private:
- raw_ptr<HttpNetworkSession> network_session_;
- };
- } // namespace
- // Check that when a request that fails to create an HttpTransaction can be
- // cancelled while the failure notification is pending, and doesn't send two
- // failure notifications.
- //
- // This currently only happens when in suspend mode and there's no cache, but
- // just use a special HttpTransactionFactory, to avoid depending on those
- // behaviors.
- //
- // Flaky crash: https://crbug.com/1348418
- #if BUILDFLAG(IS_CHROMEOS)
- #define MAYBE_NetworkCancelAfterCreateTransactionFailsTest \
- DISABLED_NetworkCancelAfterCreateTransactionFailsTest
- #else
- #define MAYBE_NetworkCancelAfterCreateTransactionFailsTest \
- NetworkCancelAfterCreateTransactionFailsTest
- #endif
- TEST_F(URLRequestTestHTTP, MAYBE_NetworkCancelAfterCreateTransactionFailsTest) {
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->SetCreateHttpTransactionFactoryCallback(
- base::BindOnce([](HttpNetworkSession* session) {
- std::unique_ptr<HttpTransactionFactory> factory =
- std::make_unique<FailingHttpTransactionFactory>(session);
- return factory;
- }));
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<TestNetworkDelegate>());
- auto context = context_builder->Build();
- TestDelegate d;
- std::unique_ptr<URLRequest> req(
- context->CreateRequest(GURL("http://127.0.0.1/"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- // Don't send cookies (Collecting cookies is asynchronous, and need request to
- // try to create an HttpNetworkTransaction synchronously on start).
- req->set_allow_credentials(false);
- req->Start();
- req->Cancel();
- d.RunUntilComplete();
- // Run pending error task, if there is one.
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(d.request_failed());
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(ERR_ABORTED, d.request_status());
- // NetworkDelegate should see the cancellation, but not the error.
- EXPECT_EQ(1, network_delegate.canceled_requests());
- EXPECT_EQ(0, network_delegate.error_count());
- }
- TEST_F(URLRequestTestHTTP, NetworkAccessedSetOnNetworkRequest) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- GURL test_url(http_test_server()->GetURL("/"));
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- test_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- EXPECT_TRUE(req->response_info().network_accessed);
- }
- TEST_F(URLRequestTestHTTP, NetworkAccessedClearOnCachedResponse) {
- ASSERT_TRUE(http_test_server()->Start());
- // Populate the cache.
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/cachetime"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(isolation_info1_);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(OK, d.request_status());
- EXPECT_TRUE(req->response_info().network_accessed);
- EXPECT_FALSE(req->response_info().was_cached);
- req = default_context().CreateRequest(
- http_test_server()->GetURL("/cachetime"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS);
- req->set_isolation_info(isolation_info1_);
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(OK, d.request_status());
- EXPECT_FALSE(req->response_info().network_accessed);
- EXPECT_TRUE(req->response_info().was_cached);
- }
- TEST_F(URLRequestTestHTTP, NetworkAccessedClearOnLoadOnlyFromCache) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- GURL test_url(http_test_server()->GetURL("/"));
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- test_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->SetLoadFlags(LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION);
- req->Start();
- d.RunUntilComplete();
- EXPECT_FALSE(req->response_info().network_accessed);
- }
- // Test that a single job with a THROTTLED priority completes
- // correctly in the absence of contention.
- TEST_F(URLRequestTestHTTP, ThrottledPriority) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- GURL test_url(http_test_server()->GetURL("/"));
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- test_url, THROTTLED, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(OK, d.request_status());
- }
- TEST_F(URLRequestTestHTTP, RawBodyBytesNoContentEncoding) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/simple.html"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(5, req->GetRawBodyBytes());
- }
- TEST_F(URLRequestTestHTTP, RawBodyBytesGzipEncoding) {
- ASSERT_TRUE(http_test_server()->Start());
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/gzip-encoded"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(30, req->GetRawBodyBytes());
- }
- // Check that if NetworkDelegate::OnBeforeStartTransaction returns an error,
- // the delegate isn't called back synchronously.
- TEST_F(URLRequestTestHTTP, TesBeforeStartTransactionFails) {
- ASSERT_TRUE(http_test_server()->Start());
- default_network_delegate().set_before_start_transaction_fails();
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- DCHECK(!d.response_completed());
- d.RunUntilComplete();
- DCHECK(d.response_completed());
- EXPECT_EQ(ERR_FAILED, d.request_status());
- }
- class URLRequestTestReferrerPolicy : public URLRequestTest {
- public:
- URLRequestTestReferrerPolicy() = default;
- void InstantiateSameOriginServers(net::EmbeddedTestServer::Type type) {
- origin_server_ = std::make_unique<EmbeddedTestServer>(type);
- RegisterDefaultHandlers(origin_server_.get());
- ASSERT_TRUE(origin_server_->Start());
- }
- void InstantiateCrossOriginServers(net::EmbeddedTestServer::Type origin_type,
- net::EmbeddedTestServer::Type dest_type) {
- origin_server_ = std::make_unique<EmbeddedTestServer>(origin_type);
- RegisterDefaultHandlers(origin_server_.get());
- ASSERT_TRUE(origin_server_->Start());
- destination_server_ = std::make_unique<EmbeddedTestServer>(dest_type);
- RegisterDefaultHandlers(destination_server_.get());
- ASSERT_TRUE(destination_server_->Start());
- }
- void VerifyReferrerAfterRedirect(ReferrerPolicy policy,
- const GURL& referrer,
- const GURL& expected) {
- // Create and execute the request: we'll only have a |destination_server_|
- // if the origins are meant to be distinct. Otherwise, we'll use the
- // |origin_server_| for both endpoints.
- GURL destination_url =
- destination_server_ ? destination_server_->GetURL("/echoheader?Referer")
- : origin_server_->GetURL("/echoheader?Referer");
- GURL origin_url =
- origin_server_->GetURL("/server-redirect?" + destination_url.spec());
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- origin_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_referrer_policy(policy);
- req->SetReferrer(referrer.spec());
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(1, d.received_redirect_count());
- EXPECT_EQ(destination_url, req->url());
- EXPECT_EQ(OK, d.request_status());
- EXPECT_EQ(200, req->response_headers()->response_code());
- EXPECT_EQ(expected.spec(), req->referrer());
- if (expected.is_empty())
- EXPECT_EQ("None", d.data_received());
- else
- EXPECT_EQ(expected.spec(), d.data_received());
- }
- EmbeddedTestServer* origin_server() const { return origin_server_.get(); }
- private:
- std::unique_ptr<EmbeddedTestServer> origin_server_;
- std::unique_ptr<EmbeddedTestServer> destination_server_;
- };
- TEST_F(URLRequestTestReferrerPolicy, HTTPToSameOriginHTTP) {
- InstantiateSameOriginServers(net::EmbeddedTestServer::TYPE_HTTP);
- GURL referrer = origin_server()->GetURL("/path/to/file.html");
- VerifyReferrerAfterRedirect(
- ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE, referrer,
- referrer);
- VerifyReferrerAfterRedirect(
- ReferrerPolicy::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN, referrer,
- referrer);
- VerifyReferrerAfterRedirect(
- ReferrerPolicy::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, referrer,
- referrer);
- VerifyReferrerAfterRedirect(ReferrerPolicy::NEVER_CLEAR, referrer, referrer);
- // The original referrer set on the request is expected to obey the referrer
- // policy and already be stripped to the origin; thus this test case just
- // checks that this policy doesn't cause the referrer to change when following
- // a redirect.
- VerifyReferrerAfterRedirect(ReferrerPolicy::ORIGIN,
- referrer.DeprecatedGetOriginAsURL(),
- referrer.DeprecatedGetOriginAsURL());
- VerifyReferrerAfterRedirect(ReferrerPolicy::CLEAR_ON_TRANSITION_CROSS_ORIGIN,
- referrer, referrer);
- // The original referrer set on the request is expected to obey the referrer
- // policy and already be stripped to the origin; thus this test case just
- // checks that this policy doesn't cause the referrer to change when following
- // a redirect.
- VerifyReferrerAfterRedirect(
- ReferrerPolicy::ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
- referrer.DeprecatedGetOriginAsURL(), referrer.DeprecatedGetOriginAsURL());
- VerifyReferrerAfterRedirect(ReferrerPolicy::NO_REFERRER, GURL(), GURL());
- }
- TEST_F(URLRequestTestReferrerPolicy, HTTPToCrossOriginHTTP) {
- InstantiateCrossOriginServers(net::EmbeddedTestServer::TYPE_HTTP,
- net::EmbeddedTestServer::TYPE_HTTP);
- GURL referrer = origin_server()->GetURL("/path/to/file.html");
- VerifyReferrerAfterRedirect(
- ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE, referrer,
- referrer);
- VerifyReferrerAfterRedirect(
- ReferrerPolicy::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN, referrer,
- referrer.DeprecatedGetOriginAsURL());
- VerifyReferrerAfterRedirect(
- ReferrerPolicy::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, referrer,
- referrer.DeprecatedGetOriginAsURL());
- VerifyReferrerAfterRedirect(ReferrerPolicy::NEVER_CLEAR, referrer, referrer);
- // The original referrer set on the request is expected to obey the referrer
- // policy and already be stripped to the origin; thus this test case just
- // checks that this policy doesn't cause the referrer to change when following
- // a redirect.
- VerifyReferrerAfterRedirect(ReferrerPolicy::ORIGIN,
- referrer.DeprecatedGetOriginAsURL(),
- referrer.DeprecatedGetOriginAsURL());
- VerifyReferrerAfterRedirect(ReferrerPolicy::CLEAR_ON_TRANSITION_CROSS_ORIGIN,
- referrer, GURL());
- // The original referrer set on the request is expected to obey the referrer
- // policy and already be stripped to the origin; thus this test case just
- // checks that this policy doesn't cause the referrer to change when following
- // a redirect.
- VerifyReferrerAfterRedirect(
- ReferrerPolicy::ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
- referrer.DeprecatedGetOriginAsURL(), referrer.DeprecatedGetOriginAsURL());
- VerifyReferrerAfterRedirect(ReferrerPolicy::NO_REFERRER, GURL(), GURL());
- }
- TEST_F(URLRequestTestReferrerPolicy, HTTPSToSameOriginHTTPS) {
- InstantiateSameOriginServers(net::EmbeddedTestServer::TYPE_HTTPS);
- GURL referrer = origin_server()->GetURL("/path/to/file.html");
- VerifyReferrerAfterRedirect(
- ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE, referrer,
- referrer);
- VerifyReferrerAfterRedirect(
- ReferrerPolicy::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN, referrer,
- referrer);
- VerifyReferrerAfterRedirect(
- ReferrerPolicy::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, referrer,
- referrer);
- VerifyReferrerAfterRedirect(ReferrerPolicy::NEVER_CLEAR, referrer, referrer);
- // The original referrer set on the request is expected to obey the referrer
- // policy and already be stripped to the origin; thus this test case just
- // checks that this policy doesn't cause the referrer to change when following
- // a redirect.
- VerifyReferrerAfterRedirect(ReferrerPolicy::ORIGIN,
- referrer.DeprecatedGetOriginAsURL(),
- referrer.DeprecatedGetOriginAsURL());
- VerifyReferrerAfterRedirect(ReferrerPolicy::CLEAR_ON_TRANSITION_CROSS_ORIGIN,
- referrer, referrer);
- // The original referrer set on the request is expected to obey the referrer
- // policy and already be stripped to the origin; thus this test case just
- // checks that this policy doesn't cause the referrer to change when following
- // a redirect.
- VerifyReferrerAfterRedirect(
- ReferrerPolicy::ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
- referrer.DeprecatedGetOriginAsURL(), referrer.DeprecatedGetOriginAsURL());
- VerifyReferrerAfterRedirect(ReferrerPolicy::NO_REFERRER, GURL(), GURL());
- }
- TEST_F(URLRequestTestReferrerPolicy, HTTPSToCrossOriginHTTPS) {
- InstantiateCrossOriginServers(net::EmbeddedTestServer::TYPE_HTTPS,
- net::EmbeddedTestServer::TYPE_HTTPS);
- GURL referrer = origin_server()->GetURL("/path/to/file.html");
- VerifyReferrerAfterRedirect(
- ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE, referrer,
- referrer);
- VerifyReferrerAfterRedirect(
- ReferrerPolicy::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN, referrer,
- origin_server()->GetURL("/"));
- VerifyReferrerAfterRedirect(
- ReferrerPolicy::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, referrer,
- origin_server()->GetURL("/"));
- VerifyReferrerAfterRedirect(ReferrerPolicy::NEVER_CLEAR, referrer, referrer);
- // The original referrer set on the request is expected to obey the referrer
- // policy and already be stripped to the origin; thus this test case just
- // checks that this policy doesn't cause the referrer to change when following
- // a redirect.
- VerifyReferrerAfterRedirect(ReferrerPolicy::ORIGIN,
- referrer.DeprecatedGetOriginAsURL(),
- referrer.DeprecatedGetOriginAsURL());
- VerifyReferrerAfterRedirect(ReferrerPolicy::CLEAR_ON_TRANSITION_CROSS_ORIGIN,
- referrer, GURL());
- // The original referrer set on the request is expected to obey the referrer
- // policy and already be stripped to the origin; thus this test case just
- // checks that this policy doesn't cause the referrer to change when following
- // a redirect.
- VerifyReferrerAfterRedirect(
- ReferrerPolicy::ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
- referrer.DeprecatedGetOriginAsURL(), referrer.DeprecatedGetOriginAsURL());
- VerifyReferrerAfterRedirect(ReferrerPolicy::NO_REFERRER, GURL(), GURL());
- }
- TEST_F(URLRequestTestReferrerPolicy, HTTPToHTTPS) {
- InstantiateCrossOriginServers(net::EmbeddedTestServer::TYPE_HTTP,
- net::EmbeddedTestServer::TYPE_HTTPS);
- GURL referrer = origin_server()->GetURL("/path/to/file.html");
- VerifyReferrerAfterRedirect(
- ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE, referrer,
- referrer);
- VerifyReferrerAfterRedirect(
- ReferrerPolicy::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN, referrer,
- origin_server()->GetURL("/"));
- VerifyReferrerAfterRedirect(
- ReferrerPolicy::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, referrer,
- origin_server()->GetURL("/"));
- VerifyReferrerAfterRedirect(ReferrerPolicy::NEVER_CLEAR, referrer, referrer);
- // The original referrer set on the request is expected to obey the referrer
- // policy and already be stripped to the origin; thus this test case just
- // checks that this policy doesn't cause the referrer to change when following
- // a redirect.
- VerifyReferrerAfterRedirect(ReferrerPolicy::ORIGIN,
- referrer.DeprecatedGetOriginAsURL(),
- referrer.DeprecatedGetOriginAsURL());
- VerifyReferrerAfterRedirect(ReferrerPolicy::CLEAR_ON_TRANSITION_CROSS_ORIGIN,
- referrer, GURL());
- // The original referrer set on the request is expected to obey the referrer
- // policy and already be stripped to the origin; thus this test case just
- // checks that this policy doesn't cause the referrer to change when following
- // a redirect.
- VerifyReferrerAfterRedirect(
- ReferrerPolicy::ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
- referrer.DeprecatedGetOriginAsURL(), referrer.DeprecatedGetOriginAsURL());
- VerifyReferrerAfterRedirect(ReferrerPolicy::NO_REFERRER, GURL(), GURL());
- }
- TEST_F(URLRequestTestReferrerPolicy, HTTPSToHTTP) {
- InstantiateCrossOriginServers(net::EmbeddedTestServer::TYPE_HTTPS,
- net::EmbeddedTestServer::TYPE_HTTP);
- GURL referrer = origin_server()->GetURL("/path/to/file.html");
- VerifyReferrerAfterRedirect(
- ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE, referrer,
- GURL());
- VerifyReferrerAfterRedirect(
- ReferrerPolicy::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN, referrer,
- GURL());
- VerifyReferrerAfterRedirect(
- ReferrerPolicy::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, referrer,
- origin_server()->GetURL("/"));
- VerifyReferrerAfterRedirect(ReferrerPolicy::NEVER_CLEAR, referrer, referrer);
- // The original referrer set on the request is expected to obey the referrer
- // policy and already be stripped to the origin; thus this test case just
- // checks that this policy doesn't cause the referrer to change when following
- // a redirect.
- VerifyReferrerAfterRedirect(ReferrerPolicy::ORIGIN,
- referrer.DeprecatedGetOriginAsURL(),
- referrer.DeprecatedGetOriginAsURL());
- VerifyReferrerAfterRedirect(ReferrerPolicy::CLEAR_ON_TRANSITION_CROSS_ORIGIN,
- referrer, GURL());
- // The original referrer set on the request is expected to obey the referrer
- // policy and already be stripped to the origin, though it should be
- // subsequently cleared during the downgrading redirect.
- VerifyReferrerAfterRedirect(
- ReferrerPolicy::ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
- referrer.DeprecatedGetOriginAsURL(), GURL());
- VerifyReferrerAfterRedirect(ReferrerPolicy::NO_REFERRER, GURL(), GURL());
- }
- class HTTPSRequestTest : public TestWithTaskEnvironment {
- public:
- HTTPSRequestTest() {
- auto context_builder = CreateTestURLRequestContextBuilder();
- default_context_ = context_builder->Build();
- }
- ~HTTPSRequestTest() override {
- SetTransportSecurityStateSourceForTesting(nullptr);
- }
- URLRequestContext& default_context() { return *default_context_; }
- private:
- std::unique_ptr<URLRequestContext> default_context_;
- };
- TEST_F(HTTPSRequestTest, HTTPSGetTest) {
- EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- RegisterDefaultHandlers(&test_server);
- ASSERT_TRUE(test_server.Start());
- TestDelegate d;
- {
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_NE(0, d.bytes_received());
- CheckSSLInfo(r->ssl_info());
- EXPECT_EQ(test_server.host_port_pair().host(),
- r->GetResponseRemoteEndpoint().ToStringWithoutPort());
- EXPECT_EQ(test_server.host_port_pair().port(),
- r->GetResponseRemoteEndpoint().port());
- }
- }
- TEST_F(HTTPSRequestTest, HTTPSMismatchedTest) {
- EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_MISMATCHED_NAME);
- RegisterDefaultHandlers(&test_server);
- ASSERT_TRUE(test_server.Start());
- bool err_allowed = true;
- for (int i = 0; i < 2; i++, err_allowed = !err_allowed) {
- TestDelegate d;
- {
- d.set_allow_certificate_errors(err_allowed);
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_TRUE(d.have_certificate_errors());
- if (err_allowed) {
- EXPECT_NE(0, d.bytes_received());
- CheckSSLInfo(r->ssl_info());
- } else {
- EXPECT_EQ(0, d.bytes_received());
- }
- }
- }
- }
- TEST_F(HTTPSRequestTest, HTTPSExpiredTest) {
- EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED);
- RegisterDefaultHandlers(&test_server);
- ASSERT_TRUE(test_server.Start());
- // Iterate from false to true, just so that we do the opposite of the
- // previous test in order to increase test coverage.
- bool err_allowed = false;
- for (int i = 0; i < 2; i++, err_allowed = !err_allowed) {
- TestDelegate d;
- {
- d.set_allow_certificate_errors(err_allowed);
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_TRUE(d.have_certificate_errors());
- if (err_allowed) {
- EXPECT_NE(0, d.bytes_received());
- CheckSSLInfo(r->ssl_info());
- } else {
- EXPECT_EQ(0, d.bytes_received());
- }
- }
- }
- }
- // A TestDelegate used to test that an appropriate net error code is provided
- // when an SSL certificate error occurs.
- class SSLNetErrorTestDelegate : public TestDelegate {
- public:
- void OnSSLCertificateError(URLRequest* request,
- int net_error,
- const SSLInfo& ssl_info,
- bool fatal) override {
- net_error_ = net_error;
- on_ssl_certificate_error_called_ = true;
- TestDelegate::OnSSLCertificateError(request, net_error, ssl_info, fatal);
- }
- bool on_ssl_certificate_error_called() {
- return on_ssl_certificate_error_called_;
- }
- int net_error() { return net_error_; }
- private:
- bool on_ssl_certificate_error_called_ = false;
- int net_error_ = net::OK;
- };
- // Tests that the URLRequest::Delegate receives an appropriate net error code
- // when an SSL certificate error occurs.
- TEST_F(HTTPSRequestTest, SSLNetErrorReportedToDelegate) {
- EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED);
- RegisterDefaultHandlers(&test_server);
- ASSERT_TRUE(test_server.Start());
- SSLNetErrorTestDelegate d;
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_TRUE(d.on_ssl_certificate_error_called());
- EXPECT_EQ(net::ERR_CERT_DATE_INVALID, d.net_error());
- }
- // TODO(svaldez): iOS tests are flaky with EmbeddedTestServer and transport
- // security state. (see http://crbug.com/550977).
- #if !BUILDFLAG(IS_IOS)
- // This tests that a load of a domain with preloaded HSTS and HPKP with a
- // certificate error sets the |certificate_errors_are_fatal| flag correctly.
- // This flag will cause the interstitial to be fatal.
- TEST_F(HTTPSRequestTest, HTTPSPreloadedHSTSTest) {
- SetTransportSecurityStateSourceForTesting(&test_default::kHSTSSource);
- EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_MISMATCHED_NAME);
- test_server.ServeFilesFromSourceDirectory("net/data/ssl");
- ASSERT_TRUE(test_server.Start());
- // We require that the URL be hsts-hpkp-preloaded.test. This is a test domain
- // that has a preloaded HSTS+HPKP entry in the TransportSecurityState. This
- // means that we have to use a MockHostResolver in order to direct
- // hsts-hpkp-preloaded.test to the testserver.
- auto host_resolver = std::make_unique<MockHostResolver>();
- host_resolver->rules()->AddRule("hsts-hpkp-preloaded.test",
- test_server.GetIPLiteralString());
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_host_resolver(std::move(host_resolver));
- auto context = context_builder->Build();
- TestDelegate d;
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- GURL(base::StringPrintf("https://hsts-hpkp-preloaded.test:%d",
- test_server.host_port_pair().port())),
- DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_TRUE(d.have_certificate_errors());
- EXPECT_TRUE(d.certificate_errors_are_fatal());
- }
- // This tests that cached HTTPS page loads do not cause any updates to the
- // TransportSecurityState.
- TEST_F(HTTPSRequestTest, HTTPSErrorsNoClobberTSSTest) {
- base::test::ScopedFeatureList scoped_feature_list_;
- scoped_feature_list_.InitAndEnableFeature(
- net::features::kStaticKeyPinningEnforcement);
- SetTransportSecurityStateSourceForTesting(&test_default::kHSTSSource);
- // The actual problem -- CERT_MISMATCHED_NAME in this case -- doesn't
- // matter. It just has to be any error.
- EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_MISMATCHED_NAME);
- test_server.ServeFilesFromSourceDirectory("net/data/ssl");
- ASSERT_TRUE(test_server.Start());
- // We require that the URL be hsts-hpkp-preloaded.test. This is a test domain
- // that has a preloaded HSTS+HPKP entry in the TransportSecurityState. This
- // means that we have to use a MockHostResolver in order to direct
- // hsts-hpkp-preloaded.test to the testserver.
- auto host_resolver = std::make_unique<MockHostResolver>();
- host_resolver->rules()->AddRule("hsts-hpkp-preloaded.test",
- test_server.GetIPLiteralString());
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_host_resolver(std::move(host_resolver));
- auto context = context_builder->Build();
- ASSERT_TRUE(context->transport_security_state());
- TransportSecurityState& transport_security_state =
- *context->transport_security_state();
- transport_security_state.EnableStaticPinsForTesting();
- transport_security_state.SetPinningListAlwaysTimelyForTesting(true);
- TransportSecurityState::STSState static_sts_state;
- TransportSecurityState::PKPState static_pkp_state;
- EXPECT_TRUE(transport_security_state.GetStaticSTSState(
- "hsts-hpkp-preloaded.test", &static_sts_state));
- EXPECT_TRUE(transport_security_state.GetStaticPKPState(
- "hsts-hpkp-preloaded.test", &static_pkp_state));
- TransportSecurityState::STSState dynamic_sts_state;
- TransportSecurityState::PKPState dynamic_pkp_state;
- EXPECT_FALSE(transport_security_state.GetDynamicSTSState(
- "hsts-hpkp-preloaded.test", &dynamic_sts_state));
- EXPECT_FALSE(transport_security_state.GetDynamicPKPState(
- "hsts-hpkp-preloaded.test", &dynamic_pkp_state));
- TestDelegate d;
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- GURL(base::StringPrintf("https://hsts-hpkp-preloaded.test:%d",
- test_server.host_port_pair().port())),
- DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_TRUE(d.have_certificate_errors());
- EXPECT_TRUE(d.certificate_errors_are_fatal());
- // Get a fresh copy of the states, and check that they haven't changed.
- TransportSecurityState::STSState new_static_sts_state;
- TransportSecurityState::PKPState new_static_pkp_state;
- EXPECT_TRUE(transport_security_state.GetStaticSTSState(
- "hsts-hpkp-preloaded.test", &new_static_sts_state));
- EXPECT_TRUE(transport_security_state.GetStaticPKPState(
- "hsts-hpkp-preloaded.test", &new_static_pkp_state));
- TransportSecurityState::STSState new_dynamic_sts_state;
- TransportSecurityState::PKPState new_dynamic_pkp_state;
- EXPECT_FALSE(transport_security_state.GetDynamicSTSState(
- "hsts-hpkp-preloaded.test", &new_dynamic_sts_state));
- EXPECT_FALSE(transport_security_state.GetDynamicPKPState(
- "hsts-hpkp-preloaded.test", &new_dynamic_pkp_state));
- EXPECT_EQ(new_static_sts_state.upgrade_mode, static_sts_state.upgrade_mode);
- EXPECT_EQ(new_static_sts_state.include_subdomains,
- static_sts_state.include_subdomains);
- EXPECT_EQ(new_static_pkp_state.include_subdomains,
- static_pkp_state.include_subdomains);
- EXPECT_EQ(new_static_pkp_state.spki_hashes, static_pkp_state.spki_hashes);
- EXPECT_EQ(new_static_pkp_state.bad_spki_hashes,
- static_pkp_state.bad_spki_hashes);
- }
- // Make sure HSTS preserves a POST request's method and body.
- TEST_F(HTTPSRequestTest, HSTSPreservesPosts) {
- static const char kData[] = "hello world";
- EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- RegisterDefaultHandlers(&test_server);
- ASSERT_TRUE(test_server.Start());
- // Per spec, TransportSecurityState expects a domain name, rather than an IP
- // address, so a MockHostResolver is needed to redirect www.somewhere.com to
- // the EmbeddedTestServer.
- auto host_resolver = std::make_unique<MockHostResolver>();
- host_resolver->rules()->AddRule("www.somewhere.com",
- test_server.GetIPLiteralString());
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_host_resolver(std::move(host_resolver));
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<TestNetworkDelegate>());
- auto context = context_builder->Build();
- ASSERT_TRUE(context->transport_security_state());
- TransportSecurityState& transport_security_state =
- *context->transport_security_state();
- // Force https for www.somewhere.com.
- base::Time expiry = base::Time::Now() + base::Days(1000);
- bool include_subdomains = false;
- transport_security_state.AddHSTS("www.somewhere.com", expiry,
- include_subdomains);
- TestDelegate d;
- // Navigating to https://www.somewhere.com instead of https://127.0.0.1 will
- // cause a certificate error. Ignore the error.
- d.set_allow_certificate_errors(true);
- std::unique_ptr<URLRequest> req(context->CreateRequest(
- GURL(base::StringPrintf("http://www.somewhere.com:%d/echo",
- test_server.host_port_pair().port())),
- DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_method("POST");
- req->set_upload(CreateSimpleUploadData(kData));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ("https", req->url().scheme());
- EXPECT_EQ("POST", req->method());
- EXPECT_EQ(kData, d.data_received());
- LoadTimingInfo load_timing_info;
- network_delegate.GetLoadTimingInfoBeforeRedirect(&load_timing_info);
- // LoadTimingInfo of HSTS redirects is similar to that of network cache hits
- TestLoadTimingCacheHitNoNetwork(load_timing_info);
- }
- // Make sure that the CORS headers are added to cross-origin HSTS redirects.
- TEST_F(HTTPSRequestTest, HSTSCrossOriginAddHeaders) {
- static const char kOriginHeaderValue[] = "http://www.example.com";
- EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- test_server.ServeFilesFromSourceDirectory("net/data/ssl");
- ASSERT_TRUE(test_server.Start());
- auto cert_verifier = std::make_unique<MockCertVerifier>();
- cert_verifier->set_default_result(OK);
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->SetCertVerifier(std::move(cert_verifier));
- auto context = context_builder->Build();
- ASSERT_TRUE(context->transport_security_state());
- TransportSecurityState& transport_security_state =
- *context->transport_security_state();
- base::Time expiry = base::Time::Now() + base::Days(1);
- bool include_subdomains = false;
- transport_security_state.AddHSTS("example.net", expiry, include_subdomains);
- GURL hsts_http_url(base::StringPrintf("http://example.net:%d/somehstssite",
- test_server.host_port_pair().port()));
- GURL::Replacements replacements;
- replacements.SetSchemeStr("https");
- GURL hsts_https_url = hsts_http_url.ReplaceComponents(replacements);
- TestDelegate d;
- std::unique_ptr<URLRequest> req(context->CreateRequest(
- hsts_http_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- // Set Origin header to simulate a cross-origin request.
- HttpRequestHeaders request_headers;
- request_headers.SetHeader("Origin", kOriginHeaderValue);
- req->SetExtraRequestHeaders(request_headers);
- req->Start();
- d.RunUntilRedirect();
- EXPECT_EQ(1, d.received_redirect_count());
- const HttpResponseHeaders* headers = req->response_headers();
- std::string redirect_location;
- EXPECT_TRUE(
- headers->EnumerateHeader(nullptr, "Location", &redirect_location));
- EXPECT_EQ(hsts_https_url.spec(), redirect_location);
- std::string received_cors_header;
- EXPECT_TRUE(headers->EnumerateHeader(nullptr, "Access-Control-Allow-Origin",
- &received_cors_header));
- EXPECT_EQ(kOriginHeaderValue, received_cors_header);
- std::string received_corp_header;
- EXPECT_TRUE(headers->EnumerateHeader(nullptr, "Cross-Origin-Resource-Policy",
- &received_corp_header));
- EXPECT_EQ("Cross-Origin", received_corp_header);
- }
- namespace {
- class SSLClientAuthTestDelegate : public TestDelegate {
- public:
- SSLClientAuthTestDelegate() { set_on_complete(base::DoNothing()); }
- void OnCertificateRequested(URLRequest* request,
- SSLCertRequestInfo* cert_request_info) override {
- on_certificate_requested_count_++;
- std::move(on_certificate_requested_).Run();
- }
- void RunUntilCertificateRequested() {
- base::RunLoop run_loop;
- on_certificate_requested_ = run_loop.QuitClosure();
- run_loop.Run();
- }
- int on_certificate_requested_count() {
- return on_certificate_requested_count_;
- }
- private:
- int on_certificate_requested_count_ = 0;
- base::OnceClosure on_certificate_requested_;
- };
- class TestSSLPrivateKey : public SSLPrivateKey {
- public:
- explicit TestSSLPrivateKey(scoped_refptr<SSLPrivateKey> key)
- : key_(std::move(key)) {}
- void set_fail_signing(bool fail_signing) { fail_signing_ = fail_signing; }
- int sign_count() const { return sign_count_; }
- std::string GetProviderName() override { return key_->GetProviderName(); }
- std::vector<uint16_t> GetAlgorithmPreferences() override {
- return key_->GetAlgorithmPreferences();
- }
- void Sign(uint16_t algorithm,
- base::span<const uint8_t> input,
- SignCallback callback) override {
- sign_count_++;
- if (fail_signing_) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback),
- ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED,
- std::vector<uint8_t>()));
- } else {
- key_->Sign(algorithm, input, std::move(callback));
- }
- }
- private:
- ~TestSSLPrivateKey() override = default;
- scoped_refptr<SSLPrivateKey> key_;
- bool fail_signing_ = false;
- int sign_count_ = 0;
- };
- } // namespace
- // TODO(davidben): Test the rest of the code. Specifically,
- // - Filtering which certificates to select.
- // - Getting a certificate request in an SSL renegotiation sending the
- // HTTP request.
- TEST_F(HTTPSRequestTest, ClientAuthNoCertificate) {
- EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- net::SSLServerConfig ssl_config;
- ssl_config.client_cert_type =
- SSLServerConfig::ClientCertType::OPTIONAL_CLIENT_CERT;
- test_server.SetSSLConfig(EmbeddedTestServer::CERT_OK, ssl_config);
- RegisterDefaultHandlers(&test_server);
- ASSERT_TRUE(test_server.Start());
- SSLClientAuthTestDelegate d;
- {
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilCertificateRequested();
- EXPECT_TRUE(r->is_pending());
- EXPECT_EQ(1, d.on_certificate_requested_count());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_EQ(0, d.bytes_received());
- // Send no certificate.
- // TODO(davidben): Get temporary client cert import (with keys) working on
- // all platforms so we can test sending a cert as well.
- r->ContinueWithCertificate(nullptr, nullptr);
- d.RunUntilComplete();
- EXPECT_EQ(OK, d.request_status());
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_NE(0, d.bytes_received());
- }
- }
- TEST_F(HTTPSRequestTest, ClientAuth) {
- std::unique_ptr<FakeClientCertIdentity> identity =
- FakeClientCertIdentity::CreateFromCertAndKeyFiles(
- GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
- ASSERT_TRUE(identity);
- scoped_refptr<TestSSLPrivateKey> private_key =
- base::MakeRefCounted<TestSSLPrivateKey>(identity->ssl_private_key());
- EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- net::SSLServerConfig ssl_config;
- ssl_config.client_cert_type =
- SSLServerConfig::ClientCertType::REQUIRE_CLIENT_CERT;
- test_server.SetSSLConfig(EmbeddedTestServer::CERT_OK, ssl_config);
- RegisterDefaultHandlers(&test_server);
- ASSERT_TRUE(test_server.Start());
- {
- SSLClientAuthTestDelegate d;
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilCertificateRequested();
- EXPECT_TRUE(r->is_pending());
- EXPECT_EQ(1, d.on_certificate_requested_count());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_EQ(0, d.bytes_received());
- // Send a certificate.
- r->ContinueWithCertificate(identity->certificate(), private_key);
- d.RunUntilComplete();
- EXPECT_EQ(OK, d.request_status());
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_NE(0, d.bytes_received());
- // The private key should have been used.
- EXPECT_EQ(1, private_key->sign_count());
- }
- // Close all connections and clear the session cache to force a new handshake.
- default_context()
- .http_transaction_factory()
- ->GetSession()
- ->CloseAllConnections(ERR_FAILED, "Very good reason");
- default_context()
- .http_transaction_factory()
- ->GetSession()
- ->ClearSSLSessionCache();
- // Connecting again should not call OnCertificateRequested. The identity is
- // taken from the client auth cache.
- {
- SSLClientAuthTestDelegate d;
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(OK, d.request_status());
- EXPECT_EQ(0, d.on_certificate_requested_count());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_NE(0, d.bytes_received());
- // The private key should have been used.
- EXPECT_EQ(2, private_key->sign_count());
- }
- }
- // Test that private keys that fail to sign anything get evicted from the cache.
- TEST_F(HTTPSRequestTest, ClientAuthFailSigning) {
- std::unique_ptr<FakeClientCertIdentity> identity =
- FakeClientCertIdentity::CreateFromCertAndKeyFiles(
- GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
- ASSERT_TRUE(identity);
- scoped_refptr<TestSSLPrivateKey> private_key =
- base::MakeRefCounted<TestSSLPrivateKey>(identity->ssl_private_key());
- private_key->set_fail_signing(true);
- EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- net::SSLServerConfig ssl_config;
- ssl_config.client_cert_type =
- SSLServerConfig::ClientCertType::REQUIRE_CLIENT_CERT;
- test_server.SetSSLConfig(EmbeddedTestServer::CERT_OK, ssl_config);
- RegisterDefaultHandlers(&test_server);
- ASSERT_TRUE(test_server.Start());
- {
- SSLClientAuthTestDelegate d;
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilCertificateRequested();
- EXPECT_TRUE(r->is_pending());
- EXPECT_EQ(1, d.on_certificate_requested_count());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_EQ(0, d.bytes_received());
- // Send a certificate.
- r->ContinueWithCertificate(identity->certificate(), private_key);
- d.RunUntilComplete();
- // The private key cannot sign anything, so we report an error.
- EXPECT_EQ(ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED, d.request_status());
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_EQ(0, d.bytes_received());
- // The private key should have been used.
- EXPECT_EQ(1, private_key->sign_count());
- }
- // Close all connections and clear the session cache to force a new handshake.
- default_context()
- .http_transaction_factory()
- ->GetSession()
- ->CloseAllConnections(ERR_FAILED, "Very good reason");
- default_context()
- .http_transaction_factory()
- ->GetSession()
- ->ClearSSLSessionCache();
- // The bad identity should have been evicted from the cache, so connecting
- // again should call OnCertificateRequested again.
- {
- SSLClientAuthTestDelegate d;
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilCertificateRequested();
- EXPECT_TRUE(r->is_pending());
- EXPECT_EQ(1, d.on_certificate_requested_count());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_EQ(0, d.bytes_received());
- // There should have been no additional uses of the private key.
- EXPECT_EQ(1, private_key->sign_count());
- }
- }
- // Test that cached private keys that fail to sign anything trigger a
- // retry. This is so we handle unplugged smartcards
- // gracefully. https://crbug.com/813022.
- TEST_F(HTTPSRequestTest, ClientAuthFailSigningRetry) {
- std::unique_ptr<FakeClientCertIdentity> identity =
- FakeClientCertIdentity::CreateFromCertAndKeyFiles(
- GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
- ASSERT_TRUE(identity);
- scoped_refptr<TestSSLPrivateKey> private_key =
- base::MakeRefCounted<TestSSLPrivateKey>(identity->ssl_private_key());
- EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- net::SSLServerConfig ssl_config;
- ssl_config.client_cert_type =
- SSLServerConfig::ClientCertType::REQUIRE_CLIENT_CERT;
- test_server.SetSSLConfig(EmbeddedTestServer::CERT_OK, ssl_config);
- RegisterDefaultHandlers(&test_server);
- ASSERT_TRUE(test_server.Start());
- // Connect with a client certificate to put it in the client auth cache.
- {
- SSLClientAuthTestDelegate d;
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilCertificateRequested();
- EXPECT_TRUE(r->is_pending());
- EXPECT_EQ(1, d.on_certificate_requested_count());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_EQ(0, d.bytes_received());
- r->ContinueWithCertificate(identity->certificate(), private_key);
- d.RunUntilComplete();
- EXPECT_EQ(OK, d.request_status());
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_NE(0, d.bytes_received());
- // The private key should have been used.
- EXPECT_EQ(1, private_key->sign_count());
- }
- // Close all connections and clear the session cache to force a new handshake.
- default_context()
- .http_transaction_factory()
- ->GetSession()
- ->CloseAllConnections(ERR_FAILED, "Very good reason");
- default_context()
- .http_transaction_factory()
- ->GetSession()
- ->ClearSSLSessionCache();
- // Cause the private key to fail. Connecting again should attempt to use it,
- // notice the failure, and then request a new identity via
- // OnCertificateRequested.
- private_key->set_fail_signing(true);
- {
- SSLClientAuthTestDelegate d;
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilCertificateRequested();
- EXPECT_TRUE(r->is_pending());
- // There was an additional signing call on the private key (the one which
- // failed).
- EXPECT_EQ(2, private_key->sign_count());
- // That caused another OnCertificateRequested call.
- EXPECT_EQ(1, d.on_certificate_requested_count());
- EXPECT_FALSE(d.received_data_before_response());
- EXPECT_EQ(0, d.bytes_received());
- }
- }
- TEST_F(HTTPSRequestTest, ResumeTest) {
- // Test that we attempt resume sessions when making two connections to the
- // same host.
- EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
- RegisterDefaultHandlers(&test_server);
- ASSERT_TRUE(test_server.Start());
- const auto url = test_server.GetURL("/");
- default_context()
- .http_transaction_factory()
- ->GetSession()
- ->ClearSSLSessionCache();
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, r->ssl_info().handshake_type);
- }
- reinterpret_cast<HttpCache*>(default_context().http_transaction_factory())
- ->CloseAllConnections(ERR_FAILED, "Very good reason");
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(SSLInfo::HANDSHAKE_RESUME, r->ssl_info().handshake_type);
- }
- }
- // Test that sessions aren't resumed across URLRequestContexts.
- TEST_F(HTTPSRequestTest, SSLSessionCacheShardTest) {
- // Start a server.
- EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
- RegisterDefaultHandlers(&test_server);
- ASSERT_TRUE(test_server.Start());
- const auto url = test_server.GetURL("/");
- // Connect to the server once. This will add an entry to the session cache.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, r->ssl_info().handshake_type);
- }
- // Clear the socket pools and connect again. This should resume the previous
- // session.
- default_context()
- .http_transaction_factory()
- ->GetSession()
- ->CloseAllConnections(ERR_FAILED, /*net_log_reason_utf8=*/"");
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(SSLInfo::HANDSHAKE_RESUME, r->ssl_info().handshake_type);
- }
- // Now fetch on a new URLRequestContext. This should not resume the session.
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto other_context = context_builder->Build();
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> r(other_context->CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, r->ssl_info().handshake_type);
- }
- }
- // Test that sessions started with privacy mode enabled cannot be resumed when
- // it is disabled, and vice versa.
- TEST_F(HTTPSRequestTest, NoSessionResumptionBetweenPrivacyModes) {
- // Start a server.
- EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
- RegisterDefaultHandlers(&test_server);
- ASSERT_TRUE(test_server.Start());
- const auto url = test_server.GetURL("/");
- auto ConnectAndCheckHandshake = [this, url](bool allow_credentials,
- auto expected_handshake) {
- // Construct request and indirectly set the privacy mode.
- TestDelegate d;
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->set_allow_credentials(allow_credentials);
- // Start the request and check the SSL handshake type.
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(expected_handshake, r->ssl_info().handshake_type);
- };
- // Exhaustively check all pairs of privacy mode values. Note that we are using
- // allow_credentials to indirectly enable/disable privacy mode.
- const bool kAllowCredentialsValues[] = {false, true};
- for (const auto allow_creds_1 : kAllowCredentialsValues) {
- for (const auto allow_creds_2 : kAllowCredentialsValues) {
- SCOPED_TRACE(base::StringPrintf("allow_creds_1=%d, allow_creds_2=%d",
- allow_creds_1, allow_creds_2));
- // The session cache starts off empty, so we expect a full handshake.
- ConnectAndCheckHandshake(allow_creds_1, SSLInfo::HANDSHAKE_FULL);
- // The second handshake depends on whether we are using the same session
- // cache as the first request.
- ConnectAndCheckHandshake(allow_creds_2, allow_creds_1 == allow_creds_2
- ? SSLInfo::HANDSHAKE_RESUME
- : SSLInfo::HANDSHAKE_FULL);
- // Flush both session caches.
- auto* network_session =
- default_context().http_transaction_factory()->GetSession();
- network_session->ClearSSLSessionCache();
- }
- }
- }
- class HTTPSFallbackTest : public TestWithTaskEnvironment {
- public:
- HTTPSFallbackTest() {
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_ssl_config_service(
- std::make_unique<TestSSLConfigService>(SSLContextConfig()));
- context_ = context_builder->Build();
- }
- ~HTTPSFallbackTest() override = default;
- protected:
- void DoFallbackTest(const SSLServerConfig& ssl_config) {
- DCHECK(!request_);
- delegate_.set_allow_certificate_errors(true);
- EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
- test_server.SetSSLConfig(EmbeddedTestServer::CERT_OK, ssl_config);
- ASSERT_TRUE(test_server.Start());
- request_ =
- context_->CreateRequest(test_server.GetURL("/"), DEFAULT_PRIORITY,
- &delegate_, TRAFFIC_ANNOTATION_FOR_TESTS);
- request_->Start();
- delegate_.RunUntilComplete();
- }
- void ExpectConnection(int version) {
- EXPECT_EQ(1, delegate_.response_started_count());
- EXPECT_NE(0, delegate_.bytes_received());
- EXPECT_EQ(version, SSLConnectionStatusToVersion(
- request_->ssl_info().connection_status));
- }
- void ExpectFailure(int error) {
- EXPECT_EQ(1, delegate_.response_started_count());
- EXPECT_EQ(error, delegate_.request_status());
- }
- private:
- TestDelegate delegate_;
- std::unique_ptr<URLRequestContext> context_;
- std::unique_ptr<URLRequest> request_;
- };
- // Tests the TLS 1.0 fallback doesn't happen.
- TEST_F(HTTPSFallbackTest, TLSv1NoFallback) {
- net::SSLServerConfig ssl_config;
- ssl_config.client_hello_callback_for_testing =
- base::BindRepeating([](const SSL_CLIENT_HELLO* client_hello) {
- // Reject ClientHellos with version >= TLS 1.1.
- return client_hello->version <= TLS1_VERSION;
- });
- ASSERT_NO_FATAL_FAILURE(DoFallbackTest(ssl_config));
- ExpectFailure(ERR_SSL_VERSION_OR_CIPHER_MISMATCH);
- }
- // Tests the TLS 1.1 fallback doesn't happen.
- TEST_F(HTTPSFallbackTest, TLSv1_1NoFallback) {
- net::SSLServerConfig ssl_config;
- ssl_config.client_hello_callback_for_testing =
- base::BindRepeating([](const SSL_CLIENT_HELLO* client_hello) {
- // Reject ClientHellos with version >= TLS 1.2.
- return client_hello->version <= TLS1_1_VERSION;
- });
- ASSERT_NO_FATAL_FAILURE(DoFallbackTest(ssl_config));
- ExpectFailure(ERR_SSL_VERSION_OR_CIPHER_MISMATCH);
- }
- // Tests the TLS 1.2 fallback doesn't happen.
- TEST_F(HTTPSFallbackTest, TLSv1_2NoFallback) {
- net::SSLServerConfig ssl_config;
- ssl_config.client_hello_callback_for_testing =
- base::BindRepeating([](const SSL_CLIENT_HELLO* client_hello) {
- // Reject ClientHellos with a supported_versions extension. TLS 1.3 is
- // signaled via an extension rather than the legacy version field.
- const uint8_t* data;
- size_t len;
- return !SSL_early_callback_ctx_extension_get(
- client_hello, TLSEXT_TYPE_supported_versions, &data, &len);
- });
- ASSERT_NO_FATAL_FAILURE(DoFallbackTest(ssl_config));
- ExpectFailure(ERR_SSL_VERSION_OR_CIPHER_MISMATCH);
- }
- class HTTPSSessionTest : public TestWithTaskEnvironment {
- public:
- HTTPSSessionTest() {
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->SetCertVerifier(std::make_unique<MockCertVerifier>());
- default_context_ = context_builder->Build();
- default_cert_verifier().set_default_result(OK);
- }
- ~HTTPSSessionTest() override = default;
- URLRequestContext& default_context() { return *default_context_; }
- MockCertVerifier& default_cert_verifier() {
- // This cast is safe because we provided a MockCertVerifier in the ctor.
- return *static_cast<MockCertVerifier*>(default_context_->cert_verifier());
- }
- private:
- std::unique_ptr<URLRequestContext> default_context_;
- };
- // Tests that session resumption is not attempted if an invalid certificate
- // is presented.
- TEST_F(HTTPSSessionTest, DontResumeSessionsForInvalidCertificates) {
- EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
- RegisterDefaultHandlers(&test_server);
- ASSERT_TRUE(test_server.Start());
- const auto url = test_server.GetURL("/");
- default_context()
- .http_transaction_factory()
- ->GetSession()
- ->ClearSSLSessionCache();
- // Simulate the certificate being expired and attempt a connection.
- default_cert_verifier().set_default_result(ERR_CERT_DATE_INVALID);
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- }
- reinterpret_cast<HttpCache*>(default_context().http_transaction_factory())
- ->CloseAllConnections(ERR_FAILED, "Very good reason");
- // Now change the certificate to be acceptable (so that the response is
- // loaded), and ensure that no session id is presented to the peer.
- default_cert_verifier().set_default_result(OK);
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, r->ssl_info().handshake_type);
- }
- }
- // Interceptor to check that secure DNS has been disabled. Secure DNS should be
- // disabled for any network fetch triggered during certificate verification as
- // it could cause a deadlock.
- class SecureDnsInterceptor : public net::URLRequestInterceptor {
- public:
- SecureDnsInterceptor() = default;
- ~SecureDnsInterceptor() override = default;
- private:
- // URLRequestInterceptor implementation:
- std::unique_ptr<net::URLRequestJob> MaybeInterceptRequest(
- net::URLRequest* request) const override {
- EXPECT_EQ(SecureDnsPolicy::kDisable, request->secure_dns_policy());
- return nullptr;
- }
- };
- class HTTPSCertNetFetchingTest : public HTTPSRequestTest {
- public:
- HTTPSCertNetFetchingTest() = default;
- void SetUp() override {
- auto context_builder = CreateTestURLRequestContextBuilder();
- cert_net_fetcher_ = base::MakeRefCounted<CertNetFetcherURLRequest>();
- context_builder->SetCertVerifier(
- CertVerifier::CreateDefault(cert_net_fetcher_));
- context_ = context_builder->Build();
- net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
- "http", "127.0.0.1", std::make_unique<SecureDnsInterceptor>());
- cert_net_fetcher_->SetURLRequestContext(context_.get());
- context_->cert_verifier()->SetConfig(GetCertVerifierConfig());
- }
- void TearDown() override {
- cert_net_fetcher_->Shutdown();
- net::URLRequestFilter::GetInstance()->ClearHandlers();
- }
- void DoConnectionWithDelegate(
- const EmbeddedTestServer::ServerCertificateConfig& cert_config,
- TestDelegate* delegate,
- SSLInfo* out_ssl_info) {
- // Always overwrite |out_ssl_info|.
- out_ssl_info->Reset();
- EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
- test_server.SetSSLConfig(cert_config);
- RegisterDefaultHandlers(&test_server);
- ASSERT_TRUE(test_server.Start());
- delegate->set_allow_certificate_errors(true);
- std::unique_ptr<URLRequest> r(
- context_->CreateRequest(test_server.GetURL("/"), DEFAULT_PRIORITY,
- delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- delegate->RunUntilComplete();
- EXPECT_EQ(1, delegate->response_started_count());
- *out_ssl_info = r->ssl_info();
- }
- void DoConnection(
- const EmbeddedTestServer::ServerCertificateConfig& cert_config,
- CertStatus* out_cert_status) {
- // Always overwrite |out_cert_status|.
- *out_cert_status = 0;
- TestDelegate d;
- SSLInfo ssl_info;
- ASSERT_NO_FATAL_FAILURE(
- DoConnectionWithDelegate(cert_config, &d, &ssl_info));
- *out_cert_status = ssl_info.cert_status;
- }
- protected:
- // GetCertVerifierConfig() configures the URLRequestContext that will be used
- // for making connections to the testserver. This can be overridden in test
- // subclasses for different behaviour.
- virtual CertVerifier::Config GetCertVerifierConfig() {
- CertVerifier::Config config;
- return config;
- }
- scoped_refptr<CertNetFetcherURLRequest> cert_net_fetcher_;
- std::unique_ptr<CertVerifier> cert_verifier_;
- std::unique_ptr<URLRequestContext> context_;
- };
- // The test EV policy OID used for generated certs.
- static const char kEVTestCertPolicy[] = "1.3.6.1.4.1.11129.2.4.1";
- class HTTPSEVTest : public HTTPSCertNetFetchingTest {
- public:
- void SetUp() override {
- HTTPSCertNetFetchingTest::SetUp();
- scoped_refptr<X509Certificate> root_cert =
- ImportCertFromFile(GetTestCertsDirectory(), "root_ca_cert.pem");
- ASSERT_TRUE(root_cert);
- ev_test_policy_ = std::make_unique<ScopedTestEVPolicy>(
- EVRootCAMetadata::GetInstance(),
- X509Certificate::CalculateFingerprint256(root_cert->cert_buffer()),
- kEVTestCertPolicy);
- }
- void TearDown() override { HTTPSCertNetFetchingTest::TearDown(); }
- private:
- std::unique_ptr<ScopedTestEVPolicy> ev_test_policy_;
- };
- class HTTPSOCSPTest : public HTTPSCertNetFetchingTest {
- public:
- CertVerifier::Config GetCertVerifierConfig() override {
- CertVerifier::Config config;
- config.enable_rev_checking = true;
- return config;
- }
- };
- static bool UsingBuiltinCertVerifier() {
- #if BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
- return true;
- #else
- #if BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
- if (base::FeatureList::IsEnabled(features::kCertVerifierBuiltinFeature))
- return true;
- #endif
- #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
- if (base::FeatureList::IsEnabled(features::kChromeRootStoreUsed))
- return true;
- #endif
- return false;
- #endif
- }
- // SystemSupportsHardFailRevocationChecking returns true iff the current
- // operating system supports revocation checking and can distinguish between
- // situations where a given certificate lacks any revocation information (eg:
- // no CRLDistributionPoints and no OCSP Responder AuthorityInfoAccess) and when
- // revocation information cannot be obtained (eg: the CRL was unreachable).
- // If it does not, then tests which rely on 'hard fail' behaviour should be
- // skipped.
- static bool SystemSupportsHardFailRevocationChecking() {
- if (UsingBuiltinCertVerifier())
- return true;
- #if BUILDFLAG(IS_WIN)
- return true;
- #else
- return false;
- #endif
- }
- // SystemUsesChromiumEVMetadata returns true iff the current operating system
- // uses Chromium's EV metadata (i.e. EVRootCAMetadata). If it does not, then
- // several tests are effected because our testing EV certificate won't be
- // recognised as EV.
- static bool SystemUsesChromiumEVMetadata() {
- if (UsingBuiltinCertVerifier())
- return true;
- #if defined(PLATFORM_USES_CHROMIUM_EV_METADATA)
- return true;
- #else
- return false;
- #endif
- }
- static bool SystemSupportsOCSP() {
- #if BUILDFLAG(IS_ANDROID)
- // Unsupported, see http://crbug.com/117478.
- return false;
- #else
- return true;
- #endif
- }
- static bool SystemSupportsOCSPStapling() {
- if (UsingBuiltinCertVerifier())
- return true;
- #if BUILDFLAG(IS_ANDROID)
- return false;
- #else
- return true;
- #endif
- }
- static bool SystemSupportsCRLSets() {
- if (UsingBuiltinCertVerifier())
- return true;
- #if BUILDFLAG(IS_ANDROID)
- return false;
- #else
- return true;
- #endif
- }
- TEST_F(HTTPSEVTest, EVCheckNoOCSP) {
- if (!SystemUsesChromiumEVMetadata()) {
- LOG(WARNING) << "Skipping test because system doesn't support EV";
- return;
- }
- EmbeddedTestServer::ServerCertificateConfig cert_config;
- cert_config.policy_oids = {kEVTestCertPolicy};
- CertStatus cert_status;
- DoConnection(cert_config, &cert_status);
- EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
- EXPECT_EQ(SystemUsesChromiumEVMetadata(),
- static_cast<bool>(cert_status & CERT_STATUS_IS_EV));
- EXPECT_FALSE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
- }
- TEST_F(HTTPSOCSPTest, Valid) {
- if (!SystemSupportsOCSP()) {
- LOG(WARNING) << "Skipping test because system doesn't support OCSP";
- return;
- }
- EmbeddedTestServer::ServerCertificateConfig cert_config;
- cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
- CertStatus cert_status;
- DoConnection(cert_config, &cert_status);
- EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
- EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
- }
- TEST_F(HTTPSOCSPTest, Revoked) {
- if (!SystemSupportsOCSP()) {
- LOG(WARNING) << "Skipping test because system doesn't support OCSP";
- return;
- }
- EmbeddedTestServer::ServerCertificateConfig cert_config;
- cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::REVOKED,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
- CertStatus cert_status;
- DoConnection(cert_config, &cert_status);
- EXPECT_EQ(CERT_STATUS_REVOKED, cert_status & CERT_STATUS_ALL_ERRORS);
- EXPECT_FALSE(cert_status & CERT_STATUS_IS_EV);
- EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
- }
- TEST_F(HTTPSOCSPTest, Invalid) {
- if (!SystemSupportsOCSP()) {
- LOG(WARNING) << "Skipping test because system doesn't support OCSP";
- return;
- }
- EmbeddedTestServer::ServerCertificateConfig cert_config;
- cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
- EmbeddedTestServer::OCSPConfig::ResponseType::kInvalidResponse);
- CertStatus cert_status;
- DoConnection(cert_config, &cert_status);
- // Without a positive OCSP response, we shouldn't show the EV status, but also
- // should not show any revocation checking errors.
- EXPECT_FALSE(cert_status & CERT_STATUS_IS_EV);
- EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
- EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
- }
- TEST_F(HTTPSOCSPTest, IntermediateValid) {
- if (!SystemSupportsOCSP()) {
- LOG(WARNING) << "Skipping test because system doesn't support OCSP";
- return;
- }
- EmbeddedTestServer::ServerCertificateConfig cert_config;
- cert_config.intermediate = EmbeddedTestServer::IntermediateType::kInHandshake;
- cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
- cert_config.intermediate_ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
- CertStatus cert_status;
- DoConnection(cert_config, &cert_status);
- EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
- EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
- }
- TEST_F(HTTPSOCSPTest, IntermediateResponseOldButStillValid) {
- if (!SystemSupportsOCSP()) {
- LOG(WARNING) << "Skipping test because system doesn't support OCSP";
- return;
- }
- EmbeddedTestServer::ServerCertificateConfig cert_config;
- cert_config.intermediate = EmbeddedTestServer::IntermediateType::kInHandshake;
- cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
- // Use an OCSP response for the intermediate that would be too old for a leaf
- // cert, but is still valid for an intermediate.
- cert_config.intermediate_ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::REVOKED,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kLong}});
- CertStatus cert_status;
- DoConnection(cert_config, &cert_status);
- if (UsingBuiltinCertVerifier()) {
- EXPECT_EQ(CERT_STATUS_REVOKED, cert_status & CERT_STATUS_ALL_ERRORS);
- } else {
- #if BUILDFLAG(IS_WIN)
- // TODO(mattm): Seems to be flaky on Windows. Either returns
- // CERT_STATUS_UNABLE_TO_CHECK_REVOCATION (which gets masked off due to
- // soft-fail), or CERT_STATUS_REVOKED.
- EXPECT_THAT(cert_status & CERT_STATUS_ALL_ERRORS,
- AnyOf(0u, CERT_STATUS_REVOKED));
- #else
- EXPECT_EQ(CERT_STATUS_REVOKED, cert_status & CERT_STATUS_ALL_ERRORS);
- #endif
- }
- EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
- }
- TEST_F(HTTPSOCSPTest, IntermediateResponseTooOld) {
- if (!SystemSupportsOCSP()) {
- LOG(WARNING) << "Skipping test because system doesn't support OCSP";
- return;
- }
- EmbeddedTestServer::ServerCertificateConfig cert_config;
- cert_config.intermediate = EmbeddedTestServer::IntermediateType::kInHandshake;
- cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
- cert_config.intermediate_ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::REVOKED,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kLonger}});
- CertStatus cert_status;
- DoConnection(cert_config, &cert_status);
- if (UsingBuiltinCertVerifier()) {
- EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
- } else {
- #if BUILDFLAG(IS_WIN)
- // TODO(mattm): Seems to be flaky on Windows. Either returns
- // CERT_STATUS_UNABLE_TO_CHECK_REVOCATION (which gets masked off due to
- // soft-fail), or CERT_STATUS_REVOKED.
- EXPECT_THAT(cert_status & CERT_STATUS_ALL_ERRORS,
- AnyOf(0u, CERT_STATUS_REVOKED));
- #else
- EXPECT_EQ(CERT_STATUS_REVOKED, cert_status & CERT_STATUS_ALL_ERRORS);
- #endif
- }
- EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
- }
- TEST_F(HTTPSOCSPTest, IntermediateRevoked) {
- if (!SystemSupportsOCSP()) {
- LOG(WARNING) << "Skipping test because system doesn't support OCSP";
- return;
- }
- EmbeddedTestServer::ServerCertificateConfig cert_config;
- cert_config.intermediate = EmbeddedTestServer::IntermediateType::kInHandshake;
- cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
- cert_config.intermediate_ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::REVOKED,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
- CertStatus cert_status;
- DoConnection(cert_config, &cert_status);
- if (UsingBuiltinCertVerifier()) {
- EXPECT_EQ(CERT_STATUS_REVOKED, cert_status & CERT_STATUS_ALL_ERRORS);
- } else {
- #if BUILDFLAG(IS_WIN)
- // TODO(mattm): Seems to be flaky on Windows. Either returns
- // CERT_STATUS_UNABLE_TO_CHECK_REVOCATION (which gets masked off due to
- // soft-fail), or CERT_STATUS_REVOKED.
- EXPECT_THAT(cert_status & CERT_STATUS_ALL_ERRORS,
- AnyOf(0u, CERT_STATUS_REVOKED));
- #else
- EXPECT_EQ(CERT_STATUS_REVOKED, cert_status & CERT_STATUS_ALL_ERRORS);
- #endif
- }
- EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
- }
- TEST_F(HTTPSOCSPTest, ValidStapled) {
- if (!SystemSupportsOCSPStapling()) {
- LOG(WARNING)
- << "Skipping test because system doesn't support OCSP stapling";
- return;
- }
- EmbeddedTestServer::ServerCertificateConfig cert_config;
- // AIA OCSP url is included, but does not return a successful ocsp response.
- cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
- EmbeddedTestServer::OCSPConfig::ResponseType::kTryLater);
- cert_config.stapled_ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
- CertStatus cert_status;
- DoConnection(cert_config, &cert_status);
- EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
- EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
- }
- TEST_F(HTTPSOCSPTest, RevokedStapled) {
- if (!SystemSupportsOCSPStapling()) {
- LOG(WARNING)
- << "Skipping test because system doesn't support OCSP stapling";
- return;
- }
- EmbeddedTestServer::ServerCertificateConfig cert_config;
- // AIA OCSP url is included, but does not return a successful ocsp response.
- cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
- EmbeddedTestServer::OCSPConfig::ResponseType::kTryLater);
- cert_config.stapled_ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::REVOKED,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
- CertStatus cert_status;
- DoConnection(cert_config, &cert_status);
- EXPECT_EQ(CERT_STATUS_REVOKED, cert_status & CERT_STATUS_ALL_ERRORS);
- EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
- }
- TEST_F(HTTPSOCSPTest, OldStapledAndInvalidAIA) {
- if (!SystemSupportsOCSPStapling()) {
- LOG(WARNING)
- << "Skipping test because system doesn't support OCSP stapling";
- return;
- }
- EmbeddedTestServer::ServerCertificateConfig cert_config;
- // Stapled response indicates good, but is too old.
- cert_config.stapled_ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kOld}});
- // AIA OCSP url is included, but does not return a successful ocsp response.
- cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
- EmbeddedTestServer::OCSPConfig::ResponseType::kTryLater);
- CertStatus cert_status;
- DoConnection(cert_config, &cert_status);
- EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
- EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
- }
- TEST_F(HTTPSOCSPTest, OldStapledButValidAIA) {
- if (!SystemSupportsOCSPStapling()) {
- LOG(WARNING)
- << "Skipping test because system doesn't support OCSP stapling";
- return;
- }
- EmbeddedTestServer::ServerCertificateConfig cert_config;
- // Stapled response indicates good, but response is too old.
- cert_config.stapled_ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kOld}});
- // AIA OCSP url is included, and returns a successful ocsp response.
- cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
- CertStatus cert_status;
- DoConnection(cert_config, &cert_status);
- EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
- EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
- }
- static const struct OCSPVerifyTestData {
- EmbeddedTestServer::OCSPConfig ocsp_config;
- OCSPVerifyResult::ResponseStatus expected_response_status;
- // |expected_cert_status| is only used if |expected_response_status| is
- // PROVIDED.
- OCSPRevocationStatus expected_cert_status;
- } kOCSPVerifyData[] = {
- // 0
- {EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}},
- EmbeddedTestServer::OCSPConfig::Produced::kValid),
- OCSPVerifyResult::PROVIDED, OCSPRevocationStatus::GOOD},
- // 1
- {EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kOld}},
- EmbeddedTestServer::OCSPConfig::Produced::kValid),
- OCSPVerifyResult::INVALID_DATE, OCSPRevocationStatus::UNKNOWN},
- // 2
- {EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kEarly}},
- EmbeddedTestServer::OCSPConfig::Produced::kValid),
- OCSPVerifyResult::INVALID_DATE, OCSPRevocationStatus::UNKNOWN},
- // 3
- {EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kLong}},
- EmbeddedTestServer::OCSPConfig::Produced::kValid),
- OCSPVerifyResult::INVALID_DATE, OCSPRevocationStatus::UNKNOWN},
- // 4
- {EmbeddedTestServer::OCSPConfig(
- EmbeddedTestServer::OCSPConfig::ResponseType::kTryLater),
- OCSPVerifyResult::ERROR_RESPONSE, OCSPRevocationStatus::UNKNOWN},
- // 5
- {EmbeddedTestServer::OCSPConfig(
- EmbeddedTestServer::OCSPConfig::ResponseType::kInvalidResponse),
- OCSPVerifyResult::PARSE_RESPONSE_ERROR, OCSPRevocationStatus::UNKNOWN},
- // 6
- {EmbeddedTestServer::OCSPConfig(
- EmbeddedTestServer::OCSPConfig::ResponseType::kInvalidResponseData),
- OCSPVerifyResult::PARSE_RESPONSE_DATA_ERROR,
- OCSPRevocationStatus::UNKNOWN},
- // 7
- {EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::REVOKED,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kEarly}},
- EmbeddedTestServer::OCSPConfig::Produced::kValid),
- OCSPVerifyResult::INVALID_DATE, OCSPRevocationStatus::UNKNOWN},
- // 8
- {EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::UNKNOWN,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}},
- EmbeddedTestServer::OCSPConfig::Produced::kValid),
- OCSPVerifyResult::PROVIDED, OCSPRevocationStatus::UNKNOWN},
- // 9
- {EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::UNKNOWN,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kOld}},
- EmbeddedTestServer::OCSPConfig::Produced::kValid),
- OCSPVerifyResult::INVALID_DATE, OCSPRevocationStatus::UNKNOWN},
- // 10
- {EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::UNKNOWN,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kEarly}},
- EmbeddedTestServer::OCSPConfig::Produced::kValid),
- OCSPVerifyResult::INVALID_DATE, OCSPRevocationStatus::UNKNOWN},
- // 11
- {EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}},
- EmbeddedTestServer::OCSPConfig::Produced::kBeforeCert),
- OCSPVerifyResult::BAD_PRODUCED_AT, OCSPRevocationStatus::UNKNOWN},
- // 12
- {EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}},
- EmbeddedTestServer::OCSPConfig::Produced::kAfterCert),
- OCSPVerifyResult::BAD_PRODUCED_AT, OCSPRevocationStatus::UNKNOWN},
- // 13
- {EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kOld},
- {OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}},
- EmbeddedTestServer::OCSPConfig::Produced::kValid),
- OCSPVerifyResult::PROVIDED, OCSPRevocationStatus::GOOD},
- // 14
- {EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kEarly},
- {OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}},
- EmbeddedTestServer::OCSPConfig::Produced::kValid),
- OCSPVerifyResult::PROVIDED, OCSPRevocationStatus::GOOD},
- // 15
- {EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kLong},
- {OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}},
- EmbeddedTestServer::OCSPConfig::Produced::kValid),
- OCSPVerifyResult::PROVIDED, OCSPRevocationStatus::GOOD},
- // 16
- {EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kEarly},
- {OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kOld},
- {OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kLong}},
- EmbeddedTestServer::OCSPConfig::Produced::kValid),
- OCSPVerifyResult::INVALID_DATE, OCSPRevocationStatus::UNKNOWN},
- // 17
- {EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::UNKNOWN,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid},
- {OCSPRevocationStatus::REVOKED,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid},
- {OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}},
- EmbeddedTestServer::OCSPConfig::Produced::kValid),
- OCSPVerifyResult::PROVIDED, OCSPRevocationStatus::REVOKED},
- // 18
- {EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::UNKNOWN,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid},
- {OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}},
- EmbeddedTestServer::OCSPConfig::Produced::kValid),
- OCSPVerifyResult::PROVIDED, OCSPRevocationStatus::UNKNOWN},
- // 19
- {EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::UNKNOWN,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid},
- {OCSPRevocationStatus::REVOKED,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kLong},
- {OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}},
- EmbeddedTestServer::OCSPConfig::Produced::kValid),
- OCSPVerifyResult::PROVIDED, OCSPRevocationStatus::UNKNOWN},
- // 20
- {EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Serial::kMismatch}},
- EmbeddedTestServer::OCSPConfig::Produced::kValid),
- OCSPVerifyResult::NO_MATCHING_RESPONSE, OCSPRevocationStatus::UNKNOWN},
- // 21
- {EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kEarly,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Serial::kMismatch}},
- EmbeddedTestServer::OCSPConfig::Produced::kValid),
- OCSPVerifyResult::NO_MATCHING_RESPONSE, OCSPRevocationStatus::UNKNOWN},
- // 22
- {EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::REVOKED,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}},
- EmbeddedTestServer::OCSPConfig::Produced::kValid),
- OCSPVerifyResult::PROVIDED, OCSPRevocationStatus::REVOKED},
- // 23
- {EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::REVOKED,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kOld}},
- EmbeddedTestServer::OCSPConfig::Produced::kValid),
- OCSPVerifyResult::INVALID_DATE, OCSPRevocationStatus::UNKNOWN},
- // 24
- {EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::REVOKED,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kLong}},
- EmbeddedTestServer::OCSPConfig::Produced::kValid),
- OCSPVerifyResult::INVALID_DATE, OCSPRevocationStatus::UNKNOWN},
- };
- class HTTPSOCSPVerifyTest
- : public HTTPSOCSPTest,
- public testing::WithParamInterface<OCSPVerifyTestData> {};
- TEST_P(HTTPSOCSPVerifyTest, VerifyResult) {
- OCSPVerifyTestData test = GetParam();
- EmbeddedTestServer::ServerCertificateConfig cert_config;
- cert_config.stapled_ocsp_config = test.ocsp_config;
- SSLInfo ssl_info;
- OCSPErrorTestDelegate delegate;
- ASSERT_NO_FATAL_FAILURE(
- DoConnectionWithDelegate(cert_config, &delegate, &ssl_info));
- // The SSLInfo must be extracted from |delegate| on error, due to how
- // URLRequest caches certificate errors.
- if (delegate.have_certificate_errors()) {
- ASSERT_TRUE(delegate.on_ssl_certificate_error_called());
- ssl_info = delegate.ssl_info();
- }
- EXPECT_EQ(test.expected_response_status,
- ssl_info.ocsp_result.response_status);
- if (test.expected_response_status == OCSPVerifyResult::PROVIDED) {
- EXPECT_EQ(test.expected_cert_status,
- ssl_info.ocsp_result.revocation_status);
- }
- }
- INSTANTIATE_TEST_SUITE_P(OCSPVerify,
- HTTPSOCSPVerifyTest,
- testing::ValuesIn(kOCSPVerifyData));
- class HTTPSAIATest : public HTTPSCertNetFetchingTest {};
- TEST_F(HTTPSAIATest, AIAFetching) {
- EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
- EmbeddedTestServer::ServerCertificateConfig cert_config;
- cert_config.intermediate = EmbeddedTestServer::IntermediateType::kByAIA;
- test_server.SetSSLConfig(cert_config);
- RegisterDefaultHandlers(&test_server);
- ASSERT_TRUE(test_server.Start());
- TestDelegate d;
- d.set_allow_certificate_errors(true);
- std::unique_ptr<URLRequest> r(context_->CreateRequest(
- test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- CertStatus cert_status = r->ssl_info().cert_status;
- EXPECT_EQ(OK, d.request_status());
- EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
- ASSERT_TRUE(r->ssl_info().cert);
- EXPECT_EQ(2u, r->ssl_info().cert->intermediate_buffers().size());
- ASSERT_TRUE(r->ssl_info().unverified_cert);
- EXPECT_EQ(0u, r->ssl_info().unverified_cert->intermediate_buffers().size());
- }
- class HTTPSHardFailTest : public HTTPSOCSPTest {
- protected:
- CertVerifier::Config GetCertVerifierConfig() override {
- CertVerifier::Config config;
- config.require_rev_checking_local_anchors = true;
- return config;
- }
- };
- TEST_F(HTTPSHardFailTest, Valid) {
- if (!SystemSupportsOCSP()) {
- LOG(WARNING) << "Skipping test because system doesn't support OCSP";
- return;
- }
- if (!SystemSupportsHardFailRevocationChecking()) {
- LOG(WARNING) << "Skipping test because system doesn't support hard fail "
- << "revocation checking";
- return;
- }
- EmbeddedTestServer::ServerCertificateConfig cert_config;
- cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
- CertStatus cert_status;
- DoConnection(cert_config, &cert_status);
- EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
- EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
- }
- TEST_F(HTTPSHardFailTest, Revoked) {
- if (!SystemSupportsOCSP()) {
- LOG(WARNING) << "Skipping test because system doesn't support OCSP";
- return;
- }
- if (!SystemSupportsHardFailRevocationChecking()) {
- LOG(WARNING) << "Skipping test because system doesn't support hard fail "
- << "revocation checking";
- return;
- }
- EmbeddedTestServer::ServerCertificateConfig cert_config;
- cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::REVOKED,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
- CertStatus cert_status;
- DoConnection(cert_config, &cert_status);
- EXPECT_EQ(CERT_STATUS_REVOKED, cert_status & CERT_STATUS_ALL_ERRORS);
- EXPECT_FALSE(cert_status & CERT_STATUS_IS_EV);
- EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
- }
- TEST_F(HTTPSHardFailTest, FailsOnOCSPInvalid) {
- if (!SystemSupportsOCSP()) {
- LOG(WARNING) << "Skipping test because system doesn't support OCSP";
- return;
- }
- if (!SystemSupportsHardFailRevocationChecking()) {
- LOG(WARNING) << "Skipping test because system doesn't support hard fail "
- << "revocation checking";
- return;
- }
- EmbeddedTestServer::ServerCertificateConfig cert_config;
- cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
- EmbeddedTestServer::OCSPConfig::ResponseType::kInvalidResponse);
- CertStatus cert_status;
- DoConnection(cert_config, &cert_status);
- EXPECT_EQ(CERT_STATUS_UNABLE_TO_CHECK_REVOCATION,
- cert_status & CERT_STATUS_ALL_ERRORS);
- EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
- }
- TEST_F(HTTPSHardFailTest, IntermediateResponseOldButStillValid) {
- if (!SystemSupportsOCSP()) {
- LOG(WARNING) << "Skipping test because system doesn't support OCSP";
- return;
- }
- if (!SystemSupportsHardFailRevocationChecking()) {
- LOG(WARNING) << "Skipping test because system doesn't support hard fail "
- << "revocation checking";
- return;
- }
- EmbeddedTestServer::ServerCertificateConfig cert_config;
- cert_config.intermediate = EmbeddedTestServer::IntermediateType::kInHandshake;
- cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
- // Use an OCSP response for the intermediate that would be too old for a leaf
- // cert, but is still valid for an intermediate.
- cert_config.intermediate_ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kLong}});
- CertStatus cert_status;
- DoConnection(cert_config, &cert_status);
- EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
- EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
- }
- TEST_F(HTTPSHardFailTest, IntermediateResponseTooOld) {
- if (!SystemSupportsOCSP()) {
- LOG(WARNING) << "Skipping test because system doesn't support OCSP";
- return;
- }
- if (!SystemSupportsHardFailRevocationChecking()) {
- LOG(WARNING) << "Skipping test because system doesn't support hard fail "
- << "revocation checking";
- return;
- }
- EmbeddedTestServer::ServerCertificateConfig cert_config;
- cert_config.intermediate = EmbeddedTestServer::IntermediateType::kInHandshake;
- cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
- // Use an OCSP response for the intermediate that is too old.
- cert_config.intermediate_ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kLonger}});
- CertStatus cert_status;
- DoConnection(cert_config, &cert_status);
- if (UsingBuiltinCertVerifier()) {
- EXPECT_EQ(CERT_STATUS_UNABLE_TO_CHECK_REVOCATION,
- cert_status & CERT_STATUS_ALL_ERRORS);
- } else {
- // Platform verifier are more lenient.
- EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
- }
- EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
- }
- TEST_F(HTTPSHardFailTest, ValidStapled) {
- if (!SystemSupportsOCSPStapling()) {
- LOG(WARNING)
- << "Skipping test because system doesn't support OCSP stapling";
- return;
- }
- if (!SystemSupportsHardFailRevocationChecking()) {
- LOG(WARNING) << "Skipping test because system doesn't support hard fail "
- << "revocation checking";
- return;
- }
- EmbeddedTestServer::ServerCertificateConfig cert_config;
- // AIA OCSP url is included, but does not return a successful ocsp response.
- cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
- EmbeddedTestServer::OCSPConfig::ResponseType::kTryLater);
- cert_config.stapled_ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
- CertStatus cert_status;
- DoConnection(cert_config, &cert_status);
- EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
- EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
- }
- TEST_F(HTTPSHardFailTest, RevokedStapled) {
- if (!SystemSupportsOCSPStapling()) {
- LOG(WARNING)
- << "Skipping test because system doesn't support OCSP stapling";
- return;
- }
- if (!SystemSupportsHardFailRevocationChecking()) {
- LOG(WARNING) << "Skipping test because system doesn't support hard fail "
- << "revocation checking";
- return;
- }
- EmbeddedTestServer::ServerCertificateConfig cert_config;
- // AIA OCSP url is included, but does not return a successful ocsp response.
- cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
- EmbeddedTestServer::OCSPConfig::ResponseType::kTryLater);
- cert_config.stapled_ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::REVOKED,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
- CertStatus cert_status;
- DoConnection(cert_config, &cert_status);
- EXPECT_EQ(CERT_STATUS_REVOKED, cert_status & CERT_STATUS_ALL_ERRORS);
- EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
- }
- TEST_F(HTTPSHardFailTest, OldStapledAndInvalidAIA) {
- if (!SystemSupportsOCSPStapling()) {
- LOG(WARNING)
- << "Skipping test because system doesn't support OCSP stapling";
- return;
- }
- if (!SystemSupportsHardFailRevocationChecking()) {
- LOG(WARNING) << "Skipping test because system doesn't support hard fail "
- << "revocation checking";
- return;
- }
- EmbeddedTestServer::ServerCertificateConfig cert_config;
- // Stapled response indicates good, but is too old.
- cert_config.stapled_ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kOld}});
- // AIA OCSP url is included, but does not return a successful ocsp response.
- cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
- EmbeddedTestServer::OCSPConfig::ResponseType::kTryLater);
- CertStatus cert_status;
- DoConnection(cert_config, &cert_status);
- EXPECT_EQ(CERT_STATUS_UNABLE_TO_CHECK_REVOCATION,
- cert_status & CERT_STATUS_ALL_ERRORS);
- EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
- }
- TEST_F(HTTPSHardFailTest, OldStapledButValidAIA) {
- if (!SystemSupportsOCSPStapling()) {
- LOG(WARNING)
- << "Skipping test because system doesn't support OCSP stapling";
- return;
- }
- if (!SystemSupportsHardFailRevocationChecking()) {
- LOG(WARNING) << "Skipping test because system doesn't support hard fail "
- << "revocation checking";
- return;
- }
- EmbeddedTestServer::ServerCertificateConfig cert_config;
- // Stapled response indicates good, but response is too old.
- cert_config.stapled_ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kOld}});
- // AIA OCSP url is included, and returns a successful ocsp response.
- cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
- CertStatus cert_status;
- DoConnection(cert_config, &cert_status);
- EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
- EXPECT_TRUE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
- }
- class HTTPSCRLSetTest : public HTTPSCertNetFetchingTest {};
- TEST_F(HTTPSCRLSetTest, ExpiredCRLSet) {
- EmbeddedTestServer::ServerCertificateConfig cert_config;
- cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
- EmbeddedTestServer::OCSPConfig::ResponseType::kInvalidResponse);
- CertVerifier::Config cert_verifier_config = GetCertVerifierConfig();
- cert_verifier_config.crl_set = CRLSet::ExpiredCRLSetForTesting();
- context_->cert_verifier()->SetConfig(cert_verifier_config);
- CertStatus cert_status;
- DoConnection(cert_config, &cert_status);
- // If we're not trying EV verification then, even if the CRLSet has expired,
- // we don't fall back to online revocation checks.
- EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
- EXPECT_FALSE(cert_status & CERT_STATUS_IS_EV);
- EXPECT_FALSE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
- }
- TEST_F(HTTPSCRLSetTest, ExpiredCRLSetAndRevoked) {
- // Test that when online revocation checking is disabled, and the leaf
- // certificate is not EV, that no revocation checking actually happens.
- if (!SystemSupportsOCSP()) {
- LOG(WARNING) << "Skipping test because system doesn't support OCSP";
- return;
- }
- EmbeddedTestServer::ServerCertificateConfig cert_config;
- cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::REVOKED,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
- CertVerifier::Config cert_verifier_config = GetCertVerifierConfig();
- cert_verifier_config.crl_set = CRLSet::ExpiredCRLSetForTesting();
- context_->cert_verifier()->SetConfig(cert_verifier_config);
- CertStatus cert_status;
- DoConnection(cert_config, &cert_status);
- EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
- EXPECT_FALSE(cert_status & CERT_STATUS_IS_EV);
- EXPECT_FALSE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
- }
- TEST_F(HTTPSCRLSetTest, CRLSetRevoked) {
- if (!SystemSupportsCRLSets()) {
- LOG(WARNING) << "Skipping test because system doesn't support CRLSets";
- return;
- }
- EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
- EmbeddedTestServer::ServerCertificateConfig cert_config;
- cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
- test_server.SetSSLConfig(cert_config);
- RegisterDefaultHandlers(&test_server);
- ASSERT_TRUE(test_server.Start());
- CertVerifier::Config cert_verifier_config = GetCertVerifierConfig();
- SHA256HashValue root_cert_spki_hash;
- ASSERT_TRUE(GetTestRootCertSPKIHash(&root_cert_spki_hash));
- cert_verifier_config.crl_set =
- CRLSet::ForTesting(false, &root_cert_spki_hash,
- test_server.GetCertificate()->serial_number(), "", {});
- context_->cert_verifier()->SetConfig(cert_verifier_config);
- TestDelegate d;
- d.set_allow_certificate_errors(true);
- std::unique_ptr<URLRequest> r(context_->CreateRequest(
- test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- CertStatus cert_status = r->ssl_info().cert_status;
- // If the certificate is recorded as revoked in the CRLSet, that should be
- // reflected without online revocation checking.
- EXPECT_EQ(CERT_STATUS_REVOKED, cert_status & CERT_STATUS_ALL_ERRORS);
- EXPECT_FALSE(cert_status & CERT_STATUS_IS_EV);
- EXPECT_FALSE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
- }
- TEST_F(HTTPSCRLSetTest, CRLSetRevokedBySubject) {
- if (!SystemSupportsCRLSets()) {
- LOG(WARNING) << "Skipping test because system doesn't support CRLSets";
- return;
- }
- EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
- EmbeddedTestServer::ServerCertificateConfig cert_config;
- cert_config.ocsp_config = EmbeddedTestServer::OCSPConfig(
- {{OCSPRevocationStatus::GOOD,
- EmbeddedTestServer::OCSPConfig::SingleResponse::Date::kValid}});
- test_server.SetSSLConfig(cert_config);
- RegisterDefaultHandlers(&test_server);
- ASSERT_TRUE(test_server.Start());
- std::string common_name = test_server.GetCertificate()->subject().common_name;
- {
- CertVerifier::Config cert_verifier_config = GetCertVerifierConfig();
- cert_verifier_config.crl_set =
- CRLSet::ForTesting(false, nullptr, "", common_name, {});
- ASSERT_TRUE(cert_verifier_config.crl_set);
- context_->cert_verifier()->SetConfig(cert_verifier_config);
- TestDelegate d;
- d.set_allow_certificate_errors(true);
- std::unique_ptr<URLRequest> r(context_->CreateRequest(
- test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- CertStatus cert_status = r->ssl_info().cert_status;
- // If the certificate is recorded as revoked in the CRLSet, that should be
- // reflected without online revocation checking.
- EXPECT_EQ(CERT_STATUS_REVOKED, cert_status & CERT_STATUS_ALL_ERRORS);
- EXPECT_FALSE(cert_status & CERT_STATUS_IS_EV);
- EXPECT_FALSE(cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
- }
- HashValue spki_hash_value;
- ASSERT_TRUE(x509_util::CalculateSha256SpkiHash(
- test_server.GetCertificate()->cert_buffer(), &spki_hash_value));
- std::string spki_hash(spki_hash_value.data(),
- spki_hash_value.data() + spki_hash_value.size());
- {
- CertVerifier::Config cert_verifier_config = GetCertVerifierConfig();
- cert_verifier_config.crl_set =
- CRLSet::ForTesting(false, nullptr, "", common_name, {spki_hash});
- context_->cert_verifier()->SetConfig(cert_verifier_config);
- TestDelegate d;
- d.set_allow_certificate_errors(true);
- std::unique_ptr<URLRequest> r(context_->CreateRequest(
- test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- CertStatus cert_status = r->ssl_info().cert_status;
- // When the correct SPKI hash is specified in
- // |acceptable_spki_hashes_for_cn|, the connection should succeed even
- // though the subject is listed in the CRLSet.
- EXPECT_EQ(0u, cert_status & CERT_STATUS_ALL_ERRORS);
- }
- }
- using HTTPSLocalCRLSetTest = TestWithTaskEnvironment;
- // Use a real CertVerifier to attempt to connect to the TestServer, and ensure
- // that when a CRLSet is provided that marks a given SPKI (the TestServer's
- // root SPKI) as known for interception, that it's adequately flagged.
- TEST_F(HTTPSLocalCRLSetTest, KnownInterceptionBlocked) {
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->SetCertVerifier(
- CertVerifier::CreateDefault(/*cert_net_fetcher=*/nullptr));
- auto context = context_builder->Build();
- // Verify the connection succeeds without being flagged.
- EmbeddedTestServer https_server(EmbeddedTestServer::TYPE_HTTPS);
- RegisterDefaultHandlers(&https_server);
- https_server.SetSSLConfig(EmbeddedTestServer::CERT_OK_BY_INTERMEDIATE);
- ASSERT_TRUE(https_server.Start());
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(
- context->CreateRequest(https_server.GetURL("/"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_FALSE(d.request_failed());
- EXPECT_FALSE(d.have_certificate_errors());
- EXPECT_FALSE(req->ssl_info().cert_status &
- CERT_STATUS_KNOWN_INTERCEPTION_BLOCKED);
- }
- // Configure a CRL that will mark |root_ca_cert| as a blocked interception
- // root.
- std::string crl_set_bytes;
- scoped_refptr<CRLSet> crl_set;
- ASSERT_TRUE(
- base::ReadFileToString(GetTestCertsDirectory().AppendASCII(
- "crlset_blocked_interception_by_root.raw"),
- &crl_set_bytes));
- ASSERT_TRUE(CRLSet::Parse(crl_set_bytes, &crl_set));
- CertVerifier::Config config_with_crlset;
- config_with_crlset.crl_set = crl_set;
- context->cert_verifier()->SetConfig(config_with_crlset);
- // Verify the connection fails as being a known interception root.
- {
- TestDelegate d;
- d.set_allow_certificate_errors(true);
- std::unique_ptr<URLRequest> req(
- context->CreateRequest(https_server.GetURL("/"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_FALSE(d.request_failed());
- if (SystemSupportsCRLSets()) {
- EXPECT_TRUE(d.have_certificate_errors());
- EXPECT_FALSE(d.certificate_errors_are_fatal());
- EXPECT_EQ(ERR_CERT_KNOWN_INTERCEPTION_BLOCKED, d.certificate_net_error());
- EXPECT_TRUE(req->ssl_info().cert_status &
- CERT_STATUS_KNOWN_INTERCEPTION_BLOCKED);
- } else {
- EXPECT_FALSE(d.have_certificate_errors());
- EXPECT_TRUE(req->ssl_info().cert_status &
- CERT_STATUS_KNOWN_INTERCEPTION_DETECTED);
- }
- }
- }
- TEST_F(HTTPSLocalCRLSetTest, InterceptionBlockedAllowOverrideOnHSTS) {
- constexpr char kHSTSHost[] = "include-subdomains-hsts-preloaded.test";
- constexpr char kHSTSSubdomainWithKnownInterception[] =
- "www.include-subdomains-hsts-preloaded.test";
- EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
- https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK_BY_INTERMEDIATE);
- https_server.ServeFilesFromSourceDirectory(base::FilePath(kTestFilePath));
- ASSERT_TRUE(https_server.Start());
- // Configure the CertVerifier to simulate:
- // - For the test server host, that the certificate is issued by an
- // unknown authority; this SHOULD NOT be a fatal error when signaled
- // to the delegate.
- // - For |kHSTSHost|, that the certificate is issued by an unknown
- // authority; this SHOULD be a fatal error.
- // Combined, these two states represent the baseline: non-fatal for non-HSTS
- // hosts, fatal for HSTS host.
- // - For |kHSTSSubdomainWithKnownInterception|, that the certificate is
- // issued by a known interception cert. This SHOULD be an error, but
- // SHOULD NOT be a fatal error
- auto cert_verifier = std::make_unique<MockCertVerifier>();
- scoped_refptr<X509Certificate> cert = https_server.GetCertificate();
- ASSERT_TRUE(cert);
- HashValue filler_hash;
- ASSERT_TRUE(filler_hash.FromString(
- "sha256/3333333333333333333333333333333333333333333="));
- CertVerifyResult fake_result;
- fake_result.verified_cert = cert;
- fake_result.is_issued_by_known_root = false;
- // Configure for the test server's default host.
- CertVerifyResult test_result = fake_result;
- test_result.public_key_hashes.push_back(filler_hash);
- test_result.cert_status |= CERT_STATUS_AUTHORITY_INVALID;
- cert_verifier->AddResultForCertAndHost(
- cert.get(), https_server.host_port_pair().host(), test_result,
- ERR_CERT_AUTHORITY_INVALID);
- // Configure for kHSTSHost.
- CertVerifyResult sts_base_result = fake_result;
- sts_base_result.public_key_hashes.push_back(filler_hash);
- sts_base_result.cert_status |= CERT_STATUS_AUTHORITY_INVALID;
- cert_verifier->AddResultForCertAndHost(cert.get(), kHSTSHost, sts_base_result,
- ERR_CERT_AUTHORITY_INVALID);
- // Configure for kHSTSSubdomainWithKnownInterception
- CertVerifyResult sts_sub_result = fake_result;
- SHA256HashValue root_hash;
- ASSERT_TRUE(GetTestRootCertSPKIHash(&root_hash));
- sts_sub_result.public_key_hashes.push_back(HashValue(root_hash));
- sts_sub_result.cert_status |=
- CERT_STATUS_REVOKED | CERT_STATUS_KNOWN_INTERCEPTION_BLOCKED;
- cert_verifier->AddResultForCertAndHost(
- cert.get(), kHSTSSubdomainWithKnownInterception, sts_sub_result,
- ERR_CERT_KNOWN_INTERCEPTION_BLOCKED);
- // Configure the initial context.
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->SetCertVerifier(std::move(cert_verifier));
- auto context = context_builder->Build();
- // Enable preloaded HSTS for |kHSTSHost|.
- ASSERT_TRUE(context->transport_security_state());
- TransportSecurityState& security_state = *context->transport_security_state();
- security_state.EnableStaticPinsForTesting();
- security_state.SetPinningListAlwaysTimelyForTesting(true);
- SetTransportSecurityStateSourceForTesting(&test_default::kHSTSSource);
- // Connect to the test server and see the certificate error flagged, but
- // not fatal.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(
- context->CreateRequest(https_server.GetURL("/"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_TRUE(d.request_failed());
- EXPECT_TRUE(d.have_certificate_errors());
- EXPECT_FALSE(d.certificate_errors_are_fatal());
- EXPECT_FALSE(req->ssl_info().cert_status &
- CERT_STATUS_KNOWN_INTERCEPTION_BLOCKED);
- }
- // Connect to kHSTSHost and see the certificate errors are flagged, and are
- // fatal.
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(context->CreateRequest(
- https_server.GetURL(kHSTSHost, "/"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_TRUE(d.request_failed());
- EXPECT_TRUE(d.have_certificate_errors());
- EXPECT_TRUE(d.certificate_errors_are_fatal());
- EXPECT_FALSE(req->ssl_info().cert_status &
- CERT_STATUS_KNOWN_INTERCEPTION_BLOCKED);
- }
- // Verify the connection fails as being a known interception root.
- {
- TestDelegate d;
- d.set_allow_certificate_errors(true);
- std::unique_ptr<URLRequest> req(context->CreateRequest(
- https_server.GetURL(kHSTSSubdomainWithKnownInterception, "/"),
- DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_FALSE(d.request_failed());
- EXPECT_TRUE(d.have_certificate_errors());
- EXPECT_FALSE(d.certificate_errors_are_fatal());
- EXPECT_EQ(ERR_CERT_KNOWN_INTERCEPTION_BLOCKED, d.certificate_net_error());
- EXPECT_TRUE(req->ssl_info().cert_status &
- CERT_STATUS_KNOWN_INTERCEPTION_BLOCKED);
- }
- }
- #endif // !BUILDFLAG(IS_IOS)
- TEST_F(URLRequestTest, NetworkAccessedSetOnHostResolutionFailure) {
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto host_resolver = std::make_unique<MockHostResolver>();
- host_resolver->rules()->AddSimulatedTimeoutFailure("*");
- context_builder->set_host_resolver(std::move(host_resolver));
- auto context = context_builder->Build();
- TestDelegate d;
- std::unique_ptr<URLRequest> req(context->CreateRequest(
- GURL("http://test_intercept/foo"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- EXPECT_FALSE(req->response_info().network_accessed);
- req->Start();
- d.RunUntilComplete();
- EXPECT_TRUE(req->response_info().network_accessed);
- EXPECT_THAT(req->response_info().resolve_error_info.error,
- IsError(ERR_DNS_TIMED_OUT));
- }
- // Test that URLRequest is canceled correctly.
- // See http://crbug.com/508900
- TEST_F(URLRequestTest, URLRequestRedirectJobCancelRequest) {
- TestDelegate d;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- GURL("http://not-a-real-domain/"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- std::unique_ptr<URLRequestRedirectJob> job =
- std::make_unique<URLRequestRedirectJob>(
- req.get(), GURL("http://this-should-never-be-navigated-to/"),
- RedirectUtil::ResponseCode::REDIRECT_307_TEMPORARY_REDIRECT,
- "Jumbo shrimp");
- TestScopedURLInterceptor interceptor(req->url(), std::move(job));
- req->Start();
- req->Cancel();
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(ERR_ABORTED, d.request_status());
- EXPECT_EQ(0, d.received_redirect_count());
- }
- #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS)
- #define MAYBE_HeadersCallbacks DISABLED_HeadersCallbacks
- #else
- #define MAYBE_HeadersCallbacks HeadersCallbacks
- #endif
- TEST_F(URLRequestTestHTTP, MAYBE_HeadersCallbacks) {
- ASSERT_TRUE(http_test_server()->Start());
- GURL url(http_test_server()->GetURL("/cachetime"));
- TestDelegate delegate;
- HttpRequestHeaders extra_headers;
- extra_headers.SetHeader("X-Foo", "bar");
- {
- HttpRawRequestHeaders raw_req_headers;
- scoped_refptr<const HttpResponseHeaders> raw_resp_headers;
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->SetExtraRequestHeaders(extra_headers);
- r->SetRequestHeadersCallback(base::BindRepeating(
- &HttpRawRequestHeaders::Assign, base::Unretained(&raw_req_headers)));
- r->SetResponseHeadersCallback(base::BindRepeating(
- [](scoped_refptr<const HttpResponseHeaders>* left,
- scoped_refptr<const HttpResponseHeaders> right) { *left = right; },
- base::Unretained(&raw_resp_headers)));
- r->set_isolation_info(isolation_info1_);
- r->Start();
- while (!delegate.response_started_count())
- base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(raw_req_headers.headers().empty());
- std::string value;
- EXPECT_TRUE(raw_req_headers.FindHeaderForTest("X-Foo", &value));
- EXPECT_EQ("bar", value);
- EXPECT_TRUE(raw_req_headers.FindHeaderForTest("Accept-Encoding", &value));
- EXPECT_EQ("gzip, deflate", value);
- EXPECT_TRUE(raw_req_headers.FindHeaderForTest("Connection", &value));
- EXPECT_TRUE(raw_req_headers.FindHeaderForTest("Host", &value));
- EXPECT_EQ("GET /cachetime HTTP/1.1\r\n", raw_req_headers.request_line());
- EXPECT_EQ(raw_resp_headers.get(), r->response_headers());
- }
- {
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->SetExtraRequestHeaders(extra_headers);
- r->SetRequestHeadersCallback(base::BindRepeating([](HttpRawRequestHeaders) {
- FAIL() << "Callback should not be called unless request is sent";
- }));
- r->SetResponseHeadersCallback(
- base::BindRepeating([](scoped_refptr<const HttpResponseHeaders>) {
- FAIL() << "Callback should not be called unless request is sent";
- }));
- r->set_isolation_info(isolation_info1_);
- r->Start();
- delegate.RunUntilComplete();
- EXPECT_TRUE(r->was_cached());
- }
- }
- TEST_F(URLRequestTestHTTP, HeadersCallbacksWithRedirect) {
- ASSERT_TRUE(http_test_server()->Start());
- HttpRawRequestHeaders raw_req_headers;
- scoped_refptr<const HttpResponseHeaders> raw_resp_headers;
- TestDelegate delegate;
- HttpRequestHeaders extra_headers;
- extra_headers.SetHeader("X-Foo", "bar");
- GURL url(http_test_server()->GetURL("/redirect-test.html"));
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->SetExtraRequestHeaders(extra_headers);
- r->SetRequestHeadersCallback(base::BindRepeating(
- &HttpRawRequestHeaders::Assign, base::Unretained(&raw_req_headers)));
- r->SetResponseHeadersCallback(base::BindRepeating(
- [](scoped_refptr<const HttpResponseHeaders>* left,
- scoped_refptr<const HttpResponseHeaders> right) { *left = right; },
- base::Unretained(&raw_resp_headers)));
- r->Start();
- delegate.RunUntilRedirect();
- ASSERT_EQ(1, delegate.received_redirect_count());
- std::string value;
- EXPECT_TRUE(raw_req_headers.FindHeaderForTest("X-Foo", &value));
- EXPECT_EQ("bar", value);
- EXPECT_TRUE(raw_req_headers.FindHeaderForTest("Accept-Encoding", &value));
- EXPECT_EQ("gzip, deflate", value);
- EXPECT_EQ(1, delegate.received_redirect_count());
- EXPECT_EQ("GET /redirect-test.html HTTP/1.1\r\n",
- raw_req_headers.request_line());
- EXPECT_TRUE(raw_resp_headers->HasHeader("Location"));
- EXPECT_EQ(302, raw_resp_headers->response_code());
- EXPECT_EQ("Redirect", raw_resp_headers->GetStatusText());
- raw_req_headers = HttpRawRequestHeaders();
- raw_resp_headers = nullptr;
- r->FollowDeferredRedirect(absl::nullopt /* removed_headers */,
- absl::nullopt /* modified_headers */);
- delegate.RunUntilComplete();
- EXPECT_TRUE(raw_req_headers.FindHeaderForTest("X-Foo", &value));
- EXPECT_EQ("bar", value);
- EXPECT_TRUE(raw_req_headers.FindHeaderForTest("Accept-Encoding", &value));
- EXPECT_EQ("gzip, deflate", value);
- EXPECT_EQ("GET /with-headers.html HTTP/1.1\r\n",
- raw_req_headers.request_line());
- EXPECT_EQ(r->response_headers(), raw_resp_headers.get());
- }
- TEST_F(URLRequestTest, HeadersCallbacksConnectFailed) {
- TestDelegate request_delegate;
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- GURL("http://127.0.0.1:9/"), DEFAULT_PRIORITY, &request_delegate,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->SetRequestHeadersCallback(
- base::BindRepeating([](net::HttpRawRequestHeaders) {
- FAIL() << "Callback should not be called unless request is sent";
- }));
- r->SetResponseHeadersCallback(
- base::BindRepeating([](scoped_refptr<const net::HttpResponseHeaders>) {
- FAIL() << "Callback should not be called unless request is sent";
- }));
- r->Start();
- request_delegate.RunUntilComplete();
- EXPECT_FALSE(r->is_pending());
- }
- TEST_F(URLRequestTestHTTP, HeadersCallbacksAuthRetry) {
- ASSERT_TRUE(http_test_server()->Start());
- GURL url(http_test_server()->GetURL("/auth-basic"));
- TestDelegate delegate;
- delegate.set_credentials(AuthCredentials(kUser, kSecret));
- HttpRequestHeaders extra_headers;
- extra_headers.SetHeader("X-Foo", "bar");
- using ReqHeadersVector = std::vector<std::unique_ptr<HttpRawRequestHeaders>>;
- ReqHeadersVector raw_req_headers;
- using RespHeadersVector =
- std::vector<scoped_refptr<const HttpResponseHeaders>>;
- RespHeadersVector raw_resp_headers;
- auto req_headers_callback = base::BindRepeating(
- [](ReqHeadersVector* vec, HttpRawRequestHeaders headers) {
- vec->emplace_back(
- std::make_unique<HttpRawRequestHeaders>(std::move(headers)));
- },
- &raw_req_headers);
- auto resp_headers_callback = base::BindRepeating(
- [](RespHeadersVector* vec,
- scoped_refptr<const HttpResponseHeaders> headers) {
- vec->push_back(headers);
- },
- &raw_resp_headers);
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->SetExtraRequestHeaders(extra_headers);
- r->SetRequestHeadersCallback(req_headers_callback);
- r->SetResponseHeadersCallback(resp_headers_callback);
- r->set_isolation_info(isolation_info1_);
- r->Start();
- delegate.RunUntilComplete();
- EXPECT_FALSE(r->is_pending());
- ASSERT_EQ(raw_req_headers.size(), 2u);
- ASSERT_EQ(raw_resp_headers.size(), 2u);
- std::string value;
- EXPECT_FALSE(raw_req_headers[0]->FindHeaderForTest("Authorization", &value));
- EXPECT_TRUE(raw_req_headers[0]->FindHeaderForTest("X-Foo", &value));
- EXPECT_EQ("bar", value);
- EXPECT_TRUE(raw_req_headers[1]->FindHeaderForTest("Authorization", &value));
- EXPECT_TRUE(raw_req_headers[1]->FindHeaderForTest("X-Foo", &value));
- EXPECT_EQ("bar", value);
- EXPECT_EQ(raw_resp_headers[1], r->response_headers());
- EXPECT_NE(raw_resp_headers[0], raw_resp_headers[1]);
- EXPECT_EQ(401, raw_resp_headers[0]->response_code());
- EXPECT_EQ("Unauthorized", raw_resp_headers[0]->GetStatusText());
- std::unique_ptr<URLRequest> r2(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
- r2->SetExtraRequestHeaders(extra_headers);
- r2->SetRequestHeadersCallback(req_headers_callback);
- r2->SetResponseHeadersCallback(resp_headers_callback);
- r2->SetLoadFlags(LOAD_VALIDATE_CACHE);
- r2->set_isolation_info(isolation_info1_);
- r2->Start();
- delegate.RunUntilComplete();
- EXPECT_FALSE(r2->is_pending());
- ASSERT_EQ(raw_req_headers.size(), 3u);
- ASSERT_EQ(raw_resp_headers.size(), 3u);
- EXPECT_TRUE(raw_req_headers[2]->FindHeaderForTest("If-None-Match", &value));
- EXPECT_NE(raw_resp_headers[2].get(), r2->response_headers());
- EXPECT_EQ(304, raw_resp_headers[2]->response_code());
- EXPECT_EQ("Not Modified", raw_resp_headers[2]->GetStatusText());
- }
- TEST_F(URLRequestTest, UpgradeIfInsecureFlagSet) {
- TestDelegate d;
- const GURL kOriginalUrl("https://original.test");
- const GURL kRedirectUrl("http://redirect.test");
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<BlockingNetworkDelegate>(
- BlockingNetworkDelegate::SYNCHRONOUS));
- network_delegate.set_redirect_url(kRedirectUrl);
- auto context = context_builder->Build();
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- kOriginalUrl, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->set_upgrade_if_insecure(true);
- r->Start();
- d.RunUntilRedirect();
- GURL::Replacements replacements;
- // Check that the redirect URL was upgraded to HTTPS since upgrade_if_insecure
- // was set.
- replacements.SetSchemeStr("https");
- EXPECT_EQ(kRedirectUrl.ReplaceComponents(replacements),
- d.redirect_info().new_url);
- EXPECT_TRUE(d.redirect_info().insecure_scheme_was_upgraded);
- }
- TEST_F(URLRequestTest, UpgradeIfInsecureFlagSetExplicitPort80) {
- TestDelegate d;
- const GURL kOriginalUrl("https://original.test");
- const GURL kRedirectUrl("http://redirect.test:80");
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<BlockingNetworkDelegate>(
- BlockingNetworkDelegate::SYNCHRONOUS));
- network_delegate.set_redirect_url(kRedirectUrl);
- auto context = context_builder->Build();
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- kOriginalUrl, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->set_upgrade_if_insecure(true);
- r->Start();
- d.RunUntilRedirect();
- GURL::Replacements replacements;
- // The URL host should have not been changed.
- EXPECT_EQ(d.redirect_info().new_url.host(), kRedirectUrl.host());
- // The scheme should now be https, and the effective port should now be 443.
- EXPECT_TRUE(d.redirect_info().new_url.SchemeIs("https"));
- EXPECT_EQ(d.redirect_info().new_url.EffectiveIntPort(), 443);
- EXPECT_TRUE(d.redirect_info().insecure_scheme_was_upgraded);
- }
- TEST_F(URLRequestTest, UpgradeIfInsecureFlagSetNonStandardPort) {
- TestDelegate d;
- const GURL kOriginalUrl("https://original.test");
- const GURL kRedirectUrl("http://redirect.test:1234");
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<BlockingNetworkDelegate>(
- BlockingNetworkDelegate::SYNCHRONOUS));
- network_delegate.set_redirect_url(kRedirectUrl);
- auto context = context_builder->Build();
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- kOriginalUrl, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->set_upgrade_if_insecure(true);
- r->Start();
- d.RunUntilRedirect();
- GURL::Replacements replacements;
- // Check that the redirect URL was upgraded to HTTPS since upgrade_if_insecure
- // was set, nonstandard port should not have been modified.
- replacements.SetSchemeStr("https");
- EXPECT_EQ(kRedirectUrl.ReplaceComponents(replacements),
- d.redirect_info().new_url);
- EXPECT_TRUE(d.redirect_info().insecure_scheme_was_upgraded);
- }
- TEST_F(URLRequestTest, UpgradeIfInsecureFlagNotSet) {
- TestDelegate d;
- const GURL kOriginalUrl("https://original.test");
- const GURL kRedirectUrl("http://redirect.test");
- auto context_builder = CreateTestURLRequestContextBuilder();
- auto& network_delegate = *context_builder->set_network_delegate(
- std::make_unique<BlockingNetworkDelegate>(
- BlockingNetworkDelegate::SYNCHRONOUS));
- network_delegate.set_redirect_url(kRedirectUrl);
- auto context = context_builder->Build();
- std::unique_ptr<URLRequest> r(context->CreateRequest(
- kOriginalUrl, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->set_upgrade_if_insecure(false);
- r->Start();
- d.RunUntilRedirect();
- // The redirect URL should not be changed if the upgrade_if_insecure flag is
- // not set.
- EXPECT_EQ(kRedirectUrl, d.redirect_info().new_url);
- EXPECT_FALSE(d.redirect_info().insecure_scheme_was_upgraded);
- }
- // Test that URLRequests get properly tagged.
- #if BUILDFLAG(IS_ANDROID)
- TEST_F(URLRequestTestHTTP, TestTagging) {
- if (!CanGetTaggedBytes()) {
- DVLOG(0) << "Skipping test - GetTaggedBytes unsupported.";
- return;
- }
- ASSERT_TRUE(http_test_server()->Start());
- // The tag under which the system reports untagged traffic.
- static const int32_t UNTAGGED_TAG = 0;
- uint64_t old_traffic = GetTaggedBytes(UNTAGGED_TAG);
- // Untagged traffic should be tagged with tag UNTAGGED_TAG.
- TestDelegate delegate;
- std::unique_ptr<URLRequest> req(default_context().CreateRequest(
- http_test_server()->GetURL("/"), DEFAULT_PRIORITY, &delegate,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- EXPECT_EQ(SocketTag(), req->socket_tag());
- req->Start();
- delegate.RunUntilComplete();
- EXPECT_GT(GetTaggedBytes(UNTAGGED_TAG), old_traffic);
- int32_t tag_val1 = 0x12345678;
- SocketTag tag1(SocketTag::UNSET_UID, tag_val1);
- old_traffic = GetTaggedBytes(tag_val1);
- // Test specific tag value.
- req = default_context().CreateRequest(http_test_server()->GetURL("/"),
- DEFAULT_PRIORITY, &delegate,
- TRAFFIC_ANNOTATION_FOR_TESTS);
- req->set_socket_tag(tag1);
- EXPECT_EQ(tag1, req->socket_tag());
- req->Start();
- delegate.RunUntilComplete();
- EXPECT_GT(GetTaggedBytes(tag_val1), old_traffic);
- }
- #endif
- namespace {
- class ReadBufferingListener
- : public test_server::EmbeddedTestServerConnectionListener {
- public:
- ReadBufferingListener() = default;
- ~ReadBufferingListener() override = default;
- void BufferNextConnection(int buffer_size) { buffer_size_ = buffer_size; }
- std::unique_ptr<StreamSocket> AcceptedSocket(
- std::unique_ptr<StreamSocket> socket) override {
- if (!buffer_size_) {
- return socket;
- }
- auto wrapped =
- std::make_unique<ReadBufferingStreamSocket>(std::move(socket));
- wrapped->BufferNextRead(buffer_size_);
- // Do not buffer subsequent connections, which may be a 0-RTT retry.
- buffer_size_ = 0;
- return wrapped;
- }
- void ReadFromSocket(const StreamSocket& socket, int rv) override {}
- private:
- int buffer_size_ = 0;
- };
- // Provides a response to the 0RTT request indicating whether it was received
- // as early data, sending HTTP_TOO_EARLY if enabled.
- class ZeroRTTResponse : public test_server::BasicHttpResponse {
- public:
- ZeroRTTResponse(bool zero_rtt, bool send_too_early)
- : zero_rtt_(zero_rtt), send_too_early_(send_too_early) {}
- ZeroRTTResponse(const ZeroRTTResponse&) = delete;
- ZeroRTTResponse& operator=(const ZeroRTTResponse&) = delete;
- ~ZeroRTTResponse() override = default;
- void SendResponse(
- base::WeakPtr<test_server::HttpResponseDelegate> delegate) override {
- AddCustomHeader("Vary", "Early-Data");
- set_content_type("text/plain");
- AddCustomHeader("Cache-Control", "no-cache");
- if (zero_rtt_) {
- if (send_too_early_)
- set_code(HTTP_TOO_EARLY);
- set_content("1");
- } else {
- set_content("0");
- }
- // Since the EmbeddedTestServer doesn't keep the socket open by default,
- // it is explicitly kept alive to allow the remaining leg of the 0RTT
- // handshake to be received after the early data.
- delegate->SendResponseHeaders(code(), GetHttpReasonPhrase(code()),
- BuildHeaders());
- delegate->SendContents(content(), base::DoNothing());
- }
- private:
- bool zero_rtt_;
- bool send_too_early_;
- };
- std::unique_ptr<test_server::HttpResponse> HandleZeroRTTRequest(
- const test_server::HttpRequest& request) {
- DCHECK(request.ssl_info);
- if (request.GetURL().path() != "/zerortt")
- return nullptr;
- return std::make_unique<ZeroRTTResponse>(
- request.ssl_info->early_data_received, false);
- }
- } // namespace
- class HTTPSEarlyDataTest : public TestWithTaskEnvironment {
- public:
- HTTPSEarlyDataTest() : test_server_(net::EmbeddedTestServer::TYPE_HTTPS) {
- HttpNetworkSessionParams params;
- params.enable_early_data = true;
- auto cert_verifier = std::make_unique<MockCertVerifier>();
- cert_verifier->set_default_result(OK);
- SSLContextConfig config;
- config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_http_network_session_params(params);
- context_builder->SetCertVerifier(std::move(cert_verifier));
- context_builder->set_ssl_config_service(
- std::make_unique<TestSSLConfigService>(config));
- context_ = context_builder->Build();
- test_server_.SetSSLConfig(
- net::EmbeddedTestServer::CERT_OK,
- CreateSSLServerConfig(SSL_PROTOCOL_VERSION_TLS1_3));
- RegisterDefaultHandlers(&test_server_);
- test_server_.RegisterRequestHandler(
- base::BindRepeating(&HandleZeroRTTRequest));
- test_server_.SetConnectionListener(&listener_);
- }
- ~HTTPSEarlyDataTest() override = default;
- URLRequestContext& context() { return *context_; }
- static SSLServerConfig CreateSSLServerConfig(uint16_t version) {
- SSLServerConfig ssl_config;
- ssl_config.version_max = version;
- ssl_config.early_data_enabled = true;
- return ssl_config;
- }
- void ResetSSLConfig(net::EmbeddedTestServer::ServerCertificate cert,
- uint16_t version) {
- SSLServerConfig ssl_config = CreateSSLServerConfig(version);
- test_server_.ResetSSLConfig(cert, ssl_config);
- }
- protected:
- std::unique_ptr<URLRequestContext> context_;
- ReadBufferingListener listener_;
- EmbeddedTestServer test_server_;
- };
- // TLSEarlyDataTest tests that we handle early data correctly.
- TEST_F(HTTPSEarlyDataTest, TLSEarlyDataTest) {
- ASSERT_TRUE(test_server_.Start());
- context().http_transaction_factory()->GetSession()->ClearSSLSessionCache();
- // kParamSize must be larger than any ClientHello sent by the client, but
- // smaller than the maximum amount of early data allowed by the server.
- const int kParamSize = 4 * 1024;
- const GURL kUrl =
- test_server_.GetURL("/zerortt?" + std::string(kParamSize, 'a'));
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> r(context().CreateRequest(
- kUrl, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- base::RunLoop().Run();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3,
- SSLConnectionStatusToVersion(r->ssl_info().connection_status));
- EXPECT_TRUE(r->ssl_info().unverified_cert.get());
- EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
- r->ssl_info().cert.get()));
- // The Early-Data header should be omitted in the initial request, and the
- // handler should return "0".
- EXPECT_EQ("0", d.data_received());
- }
- context().http_transaction_factory()->GetSession()->CloseAllConnections(
- ERR_FAILED, "Very good reason");
- // 0-RTT inherently involves a race condition: if the server responds with the
- // ServerHello before the client sends the HTTP request (the client may be
- // busy verifying a certificate), the client will send data over 1-RTT keys
- // rather than 0-RTT.
- //
- // This test ensures 0-RTT is sent if relevant by making the test server wait
- // for both the ClientHello and 0-RTT HTTP request before responding. We use
- // a ReadBufferingStreamSocket and enable buffering for the 0-RTT request. The
- // buffer size must be larger than the ClientHello but smaller than the
- // ClientHello combined with the HTTP request.
- listener_.BufferNextConnection(kParamSize);
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> r(context().CreateRequest(
- kUrl, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- base::RunLoop().Run();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3,
- SSLConnectionStatusToVersion(r->ssl_info().connection_status));
- EXPECT_TRUE(r->ssl_info().unverified_cert.get());
- EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
- r->ssl_info().cert.get()));
- // The Early-Data header should be a single '1' in the resumed request, and
- // the handler should return "1".
- EXPECT_EQ("1", d.data_received());
- }
- }
- // TLSEarlyDataTest tests that we handle early data correctly for POST.
- TEST_F(HTTPSEarlyDataTest, TLSEarlyDataPOSTTest) {
- ASSERT_TRUE(test_server_.Start());
- context().http_transaction_factory()->GetSession()->ClearSSLSessionCache();
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> r(context().CreateRequest(
- test_server_.GetURL("/zerortt"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- base::RunLoop().Run();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3,
- SSLConnectionStatusToVersion(r->ssl_info().connection_status));
- EXPECT_TRUE(r->ssl_info().unverified_cert.get());
- EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
- r->ssl_info().cert.get()));
- // The Early-Data header should be omitted in the initial request, and the
- // handler should return "0".
- EXPECT_EQ("0", d.data_received());
- }
- context().http_transaction_factory()->GetSession()->CloseAllConnections(
- ERR_FAILED, "Very good reason");
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> r(context().CreateRequest(
- test_server_.GetURL("/zerortt"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->set_method("POST");
- r->Start();
- EXPECT_TRUE(r->is_pending());
- base::RunLoop().Run();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3,
- SSLConnectionStatusToVersion(r->ssl_info().connection_status));
- EXPECT_TRUE(r->ssl_info().unverified_cert.get());
- EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
- r->ssl_info().cert.get()));
- // The Early-Data header should be omitted in the request, since we don't
- // send POSTs over early data, and the handler should return "0".
- EXPECT_EQ("0", d.data_received());
- }
- }
- // TLSEarlyDataTest tests that the 0-RTT is enabled for idempotent POST request.
- TEST_F(HTTPSEarlyDataTest, TLSEarlyDataIdempotentPOSTTest) {
- ASSERT_TRUE(test_server_.Start());
- context().http_transaction_factory()->GetSession()->ClearSSLSessionCache();
- const int kParamSize = 4 * 1024;
- const GURL kUrl =
- test_server_.GetURL("/zerortt?" + std::string(kParamSize, 'a'));
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> r(context().CreateRequest(
- kUrl, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- base::RunLoop().Run();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3,
- SSLConnectionStatusToVersion(r->ssl_info().connection_status));
- EXPECT_TRUE(r->ssl_info().unverified_cert.get());
- EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
- r->ssl_info().cert.get()));
- // The Early-Data header should be omitted in the initial request, and the
- // handler should return "0".
- EXPECT_EQ("0", d.data_received());
- }
- context().http_transaction_factory()->GetSession()->CloseAllConnections(
- ERR_FAILED, "Very good reason");
- listener_.BufferNextConnection(kParamSize);
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> r(context().CreateRequest(
- kUrl, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->set_method("POST");
- r->SetIdempotency(net::IDEMPOTENT);
- r->Start();
- EXPECT_TRUE(r->is_pending());
- base::RunLoop().Run();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3,
- SSLConnectionStatusToVersion(r->ssl_info().connection_status));
- EXPECT_TRUE(r->ssl_info().unverified_cert.get());
- EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
- r->ssl_info().cert.get()));
- // The Early-Data header should be set since the request is set as an
- // idempotent POST request.
- EXPECT_EQ("1", d.data_received());
- }
- }
- // TLSEarlyDataTest tests that the 0-RTT is disabled for non-idempotent request.
- TEST_F(HTTPSEarlyDataTest, TLSEarlyDataNonIdempotentRequestTest) {
- ASSERT_TRUE(test_server_.Start());
- context().http_transaction_factory()->GetSession()->ClearSSLSessionCache();
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> r(context().CreateRequest(
- test_server_.GetURL("/zerortt"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- base::RunLoop().Run();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3,
- SSLConnectionStatusToVersion(r->ssl_info().connection_status));
- EXPECT_TRUE(r->ssl_info().unverified_cert.get());
- EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
- r->ssl_info().cert.get()));
- // The Early-Data header should be omitted in the initial request, and the
- // handler should return "0".
- EXPECT_EQ("0", d.data_received());
- }
- context().http_transaction_factory()->GetSession()->CloseAllConnections(
- ERR_FAILED, "Very good reason");
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> r(context().CreateRequest(
- test_server_.GetURL("/zerortt"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- // Sets the GET request as not idempotent.
- r->SetIdempotency(net::NOT_IDEMPOTENT);
- r->Start();
- EXPECT_TRUE(r->is_pending());
- base::RunLoop().Run();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3,
- SSLConnectionStatusToVersion(r->ssl_info().connection_status));
- EXPECT_TRUE(r->ssl_info().unverified_cert.get());
- EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
- r->ssl_info().cert.get()));
- // The Early-Data header should be omitted in the initial request even
- // though it is a GET request, since the request is set as not idempotent.
- EXPECT_EQ("0", d.data_received());
- }
- }
- std::unique_ptr<test_server::HttpResponse> HandleTooEarly(
- bool* sent_425,
- const test_server::HttpRequest& request) {
- DCHECK(request.ssl_info);
- if (request.GetURL().path() != "/tooearly")
- return nullptr;
- if (request.ssl_info->early_data_received)
- *sent_425 = true;
- return std::make_unique<ZeroRTTResponse>(
- request.ssl_info->early_data_received, true);
- }
- // Test that we handle 425 (Too Early) correctly.
- TEST_F(HTTPSEarlyDataTest, TLSEarlyDataTooEarlyTest) {
- bool sent_425 = false;
- test_server_.RegisterRequestHandler(
- base::BindRepeating(&HandleTooEarly, base::Unretained(&sent_425)));
- ASSERT_TRUE(test_server_.Start());
- context().http_transaction_factory()->GetSession()->ClearSSLSessionCache();
- // kParamSize must be larger than any ClientHello sent by the client, but
- // smaller than the maximum amount of early data allowed by the server.
- const int kParamSize = 4 * 1024;
- const GURL kUrl =
- test_server_.GetURL("/tooearly?" + std::string(kParamSize, 'a'));
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> r(context().CreateRequest(
- kUrl, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3,
- SSLConnectionStatusToVersion(r->ssl_info().connection_status));
- EXPECT_TRUE(r->ssl_info().unverified_cert.get());
- EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
- r->ssl_info().cert.get()));
- // The Early-Data header should be omitted in the initial request, and the
- // handler should return "0".
- EXPECT_EQ("0", d.data_received());
- EXPECT_FALSE(sent_425);
- }
- context().http_transaction_factory()->GetSession()->CloseAllConnections(
- ERR_FAILED, "Very good reason");
- // 0-RTT inherently involves a race condition: if the server responds with the
- // ServerHello before the client sends the HTTP request (the client may be
- // busy verifying a certificate), the client will send data over 1-RTT keys
- // rather than 0-RTT.
- //
- // This test ensures 0-RTT is sent if relevant by making the test server wait
- // for both the ClientHello and 0-RTT HTTP request before responding. We use
- // a ReadBufferingStreamSocket and enable buffering for the 0-RTT request. The
- // buffer size must be larger than the ClientHello but smaller than the
- // ClientHello combined with the HTTP request.
- //
- // We must buffer exactly one connection because the HTTP 425 response will
- // trigger a retry, potentially on a new connection.
- listener_.BufferNextConnection(kParamSize);
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> r(context().CreateRequest(
- kUrl, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3,
- SSLConnectionStatusToVersion(r->ssl_info().connection_status));
- EXPECT_TRUE(r->ssl_info().unverified_cert.get());
- EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
- r->ssl_info().cert.get()));
- // The resumption request will encounter a 425 error and retry without early
- // data, and the handler should return "0".
- EXPECT_EQ("0", d.data_received());
- EXPECT_TRUE(sent_425);
- }
- }
- // TLSEarlyDataRejectTest tests that we gracefully handle an early data reject
- // and retry without early data.
- TEST_F(HTTPSEarlyDataTest, TLSEarlyDataRejectTest) {
- ASSERT_TRUE(test_server_.Start());
- context().http_transaction_factory()->GetSession()->ClearSSLSessionCache();
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> r(context().CreateRequest(
- test_server_.GetURL("/zerortt"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3,
- SSLConnectionStatusToVersion(r->ssl_info().connection_status));
- EXPECT_TRUE(r->ssl_info().unverified_cert.get());
- EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
- r->ssl_info().cert.get()));
- // The Early-Data header should be omitted in the initial request, and the
- // handler should return "0".
- EXPECT_EQ("0", d.data_received());
- }
- context().http_transaction_factory()->GetSession()->CloseAllConnections(
- ERR_FAILED, "Very good reason");
- // The certificate in the resumption is changed to confirm that the
- // certificate change is observed.
- scoped_refptr<X509Certificate> old_cert = test_server_.GetCertificate();
- ResetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED,
- SSL_PROTOCOL_VERSION_TLS1_3);
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> r(context().CreateRequest(
- test_server_.GetURL("/zerortt"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3,
- SSLConnectionStatusToVersion(r->ssl_info().connection_status));
- EXPECT_TRUE(r->ssl_info().unverified_cert.get());
- EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
- r->ssl_info().cert.get()));
- EXPECT_FALSE(old_cert->EqualsIncludingChain(r->ssl_info().cert.get()));
- // The Early-Data header should be omitted in the rejected request, and the
- // handler should return "0".
- EXPECT_EQ("0", d.data_received());
- }
- }
- // TLSEarlyDataTLS12RejectTest tests that we gracefully handle an early data
- // reject from a TLS 1.2 server and retry without early data.
- TEST_F(HTTPSEarlyDataTest, TLSEarlyDataTLS12RejectTest) {
- ASSERT_TRUE(test_server_.Start());
- context().http_transaction_factory()->GetSession()->ClearSSLSessionCache();
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> r(context().CreateRequest(
- test_server_.GetURL("/zerortt"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3,
- SSLConnectionStatusToVersion(r->ssl_info().connection_status));
- EXPECT_TRUE(r->ssl_info().unverified_cert.get());
- EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
- r->ssl_info().cert.get()));
- // The Early-Data header should be omitted in the initial request, and the
- // handler should return "0".
- EXPECT_EQ("0", d.data_received());
- }
- context().http_transaction_factory()->GetSession()->CloseAllConnections(
- ERR_FAILED, "Very good reason");
- // The certificate in the resumption is changed to confirm that the
- // certificate change is observed.
- scoped_refptr<X509Certificate> old_cert = test_server_.GetCertificate();
- ResetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED,
- SSL_PROTOCOL_VERSION_TLS1_2);
- {
- TestDelegate d;
- std::unique_ptr<URLRequest> r(context().CreateRequest(
- test_server_.GetURL("/zerortt"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- EXPECT_TRUE(r->is_pending());
- d.RunUntilComplete();
- EXPECT_EQ(1, d.response_started_count());
- EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_2,
- SSLConnectionStatusToVersion(r->ssl_info().connection_status));
- EXPECT_TRUE(r->ssl_info().unverified_cert.get());
- EXPECT_TRUE(test_server_.GetCertificate()->EqualsIncludingChain(
- r->ssl_info().cert.get()));
- EXPECT_FALSE(old_cert->EqualsIncludingChain(r->ssl_info().cert.get()));
- // The Early-Data header should be omitted in the rejected request, and the
- // handler should return "0".
- EXPECT_EQ("0", d.data_received());
- }
- }
- // Tests that AuthChallengeInfo is available on the request.
- TEST_F(URLRequestTestHTTP, AuthChallengeInfo) {
- ASSERT_TRUE(http_test_server()->Start());
- GURL url(http_test_server()->GetURL("/auth-basic"));
- TestDelegate delegate;
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- url, DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
- r->Start();
- delegate.RunUntilComplete();
- ASSERT_TRUE(r->auth_challenge_info().has_value());
- EXPECT_FALSE(r->auth_challenge_info()->is_proxy);
- EXPECT_EQ(url::SchemeHostPort(url), r->auth_challenge_info()->challenger);
- EXPECT_EQ("basic", r->auth_challenge_info()->scheme);
- EXPECT_EQ("testrealm", r->auth_challenge_info()->realm);
- EXPECT_EQ("Basic realm=\"testrealm\"", r->auth_challenge_info()->challenge);
- EXPECT_EQ("/auth-basic", r->auth_challenge_info()->path);
- }
- class URLRequestDnsAliasTest : public TestWithTaskEnvironment {
- protected:
- URLRequestDnsAliasTest() {
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->set_host_resolver(std::make_unique<MockHostResolver>());
- context_ = context_builder->Build();
- }
- URLRequestContext& context() { return *context_; }
- MockHostResolver& host_resolver() {
- // This cast is safe because we provided a MockHostResolver in the ctor.
- return *static_cast<MockHostResolver*>(context_->host_resolver());
- }
- void SetUp() override { ASSERT_TRUE(test_server_.Start()); }
- std::unique_ptr<URLRequestContext> context_;
- TestDelegate test_delegate_;
- EmbeddedTestServer test_server_;
- };
- TEST_F(URLRequestDnsAliasTest, WithDnsAliases) {
- GURL url(test_server_.GetURL("www.example.test", "/echo"));
- std::vector<std::string> aliases({"alias1", "alias2", "host"});
- host_resolver().rules()->AddIPLiteralRuleWithDnsAliases(
- "www.example.test", "127.0.0.1", std::move(aliases));
- std::unique_ptr<URLRequest> request(context().CreateRequest(
- url, DEFAULT_PRIORITY, &test_delegate_, TRAFFIC_ANNOTATION_FOR_TESTS));
- request->Start();
- test_delegate_.RunUntilComplete();
- EXPECT_THAT(test_delegate_.request_status(), IsOk());
- EXPECT_THAT(request->response_info().dns_aliases,
- testing::ElementsAre("alias1", "alias2", "host"));
- }
- TEST_F(URLRequestDnsAliasTest, NoAdditionalDnsAliases) {
- GURL url(test_server_.GetURL("www.example.test", "/echo"));
- host_resolver().rules()->AddIPLiteralRuleWithDnsAliases(
- "www.example.test", "127.0.0.1", /*dns_aliases=*/std::set<std::string>());
- std::unique_ptr<URLRequest> request(context().CreateRequest(
- url, DEFAULT_PRIORITY, &test_delegate_, TRAFFIC_ANNOTATION_FOR_TESTS));
- request->Start();
- test_delegate_.RunUntilComplete();
- EXPECT_THAT(test_delegate_.request_status(), IsOk());
- EXPECT_THAT(request->response_info().dns_aliases,
- testing::ElementsAre("www.example.test"));
- }
- TEST_F(URLRequestTest, SetURLChain) {
- TestDelegate d;
- {
- GURL original_url("http://localhost");
- std::unique_ptr<URLRequest> r(default_context().CreateRequest(
- original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- EXPECT_EQ(r->url_chain().size(), 1u);
- EXPECT_EQ(r->url_chain()[0], original_url);
- const std::vector<GURL> url_chain = {
- GURL("http://foo.test"),
- GURL("http://bar.test"),
- GURL("http://baz.test"),
- };
- r->SetURLChain(url_chain);
- EXPECT_EQ(r->url_chain().size(), 3u);
- EXPECT_EQ(r->url_chain()[0], url_chain[0]);
- EXPECT_EQ(r->url_chain()[1], url_chain[1]);
- EXPECT_EQ(r->url_chain()[2], original_url);
- }
- }
- class URLRequestMaybeAsyncFirstPartySetsTest
- : public URLRequestTest,
- public testing::WithParamInterface<bool> {
- public:
- URLRequestMaybeAsyncFirstPartySetsTest() { CHECK(test_server_.Start()); }
- std::unique_ptr<CookieStore> CreateCookieStore() {
- auto cookie_monster =
- std::make_unique<CookieMonster>(/*store=*/nullptr,
- /*net_log=*/nullptr,
- /*first_party_sets_enabled=*/true);
- auto cookie_access_delegate = std::make_unique<TestCookieAccessDelegate>();
- cookie_access_delegate->set_invoke_callbacks_asynchronously(
- invoke_callbacks_asynchronously());
- cookie_monster->SetCookieAccessDelegate(std::move(cookie_access_delegate));
- return cookie_monster;
- }
- bool invoke_callbacks_asynchronously() { return GetParam(); }
- HttpTestServer& test_server() { return test_server_; }
- private:
- HttpTestServer test_server_;
- };
- TEST_P(URLRequestMaybeAsyncFirstPartySetsTest, SimpleRequest) {
- const std::string kHost = "example.test";
- const url::Origin kOrigin =
- url::Origin::Create(test_server().GetURL(kHost, "/"));
- const SiteForCookies kSiteForCookies = SiteForCookies::FromOrigin(kOrigin);
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->SetCookieStore(CreateCookieStore());
- auto context = context_builder->Build();
- TestDelegate d;
- std::unique_ptr<URLRequest> req(context->CreateRequest(
- test_server().GetURL(kHost, "/echo"), DEFAULT_PRIORITY, &d,
- TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(
- IsolationInfo::Create(IsolationInfo::RequestType::kMainFrame, kOrigin,
- kOrigin, kSiteForCookies, {} /* party_context */));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(d.data_received(), "Echo");
- EXPECT_THAT(d.request_status(), IsOk());
- EXPECT_EQ(req->GetResponseCode(), 200);
- }
- TEST_P(URLRequestMaybeAsyncFirstPartySetsTest, SingleRedirect) {
- const std::string kHost = "example.test";
- const url::Origin kOrigin =
- url::Origin::Create(test_server().GetURL(kHost, "/"));
- const SiteForCookies kSiteForCookies = SiteForCookies::FromOrigin(kOrigin);
- auto context_builder = CreateTestURLRequestContextBuilder();
- context_builder->SetCookieStore(CreateCookieStore());
- auto context = context_builder->Build();
- TestDelegate d;
- std::unique_ptr<URLRequest> req(context->CreateRequest(
- test_server().GetURL(kHost,
- base::StrCat({
- "/server-redirect?",
- test_server().GetURL(kHost, "/echo").spec(),
- })),
- DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
- req->set_isolation_info(
- IsolationInfo::Create(IsolationInfo::RequestType::kMainFrame, kOrigin,
- kOrigin, kSiteForCookies, {} /* party_context */));
- req->Start();
- d.RunUntilComplete();
- EXPECT_EQ(d.data_received(), "Echo");
- EXPECT_THAT(d.request_status(), IsOk());
- EXPECT_EQ(req->GetResponseCode(), 200);
- }
- INSTANTIATE_TEST_SUITE_P(,
- URLRequestMaybeAsyncFirstPartySetsTest,
- testing::Bool());
- } // namespace net
|