HttpBaseChannel.cpp 108 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. // HttpLog.h should generally be included first
  6. #include "HttpLog.h"
  7. #include "mozilla/net/HttpBaseChannel.h"
  8. #include "nsHttpHandler.h"
  9. #include "nsHttpChannel.h"
  10. #include "nsMimeTypes.h"
  11. #include "nsNetCID.h"
  12. #include "nsNetUtil.h"
  13. #include "nsICachingChannel.h"
  14. #include "nsIDOMDocument.h"
  15. #include "nsIPrincipal.h"
  16. #include "nsIScriptError.h"
  17. #include "nsISeekableStream.h"
  18. #include "nsIStorageStream.h"
  19. #include "nsITimedChannel.h"
  20. #include "nsIEncodedChannel.h"
  21. #include "nsIApplicationCacheChannel.h"
  22. #include "nsIMutableArray.h"
  23. #include "nsEscape.h"
  24. #include "nsStreamListenerWrapper.h"
  25. #include "nsISecurityConsoleMessage.h"
  26. #include "nsURLHelper.h"
  27. #include "nsICookieService.h"
  28. #include "nsIStreamConverterService.h"
  29. #include "nsCRT.h"
  30. #include "nsContentUtils.h"
  31. #include "nsIScriptSecurityManager.h"
  32. #include "nsIObserverService.h"
  33. #include "nsProxyRelease.h"
  34. #include "nsPIDOMWindow.h"
  35. #include "nsIDocShell.h"
  36. #include "nsINetworkInterceptController.h"
  37. #include "mozilla/dom/Performance.h"
  38. #include "mozIThirdPartyUtil.h"
  39. #include "nsStreamUtils.h"
  40. #include "nsContentSecurityManager.h"
  41. #include "nsIChannelEventSink.h"
  42. #include "nsILoadGroupChild.h"
  43. #include "mozilla/ConsoleReportCollector.h"
  44. #include "LoadInfo.h"
  45. #include "nsNullPrincipal.h"
  46. #include "nsISSLSocketControl.h"
  47. #include "nsIURL.h"
  48. #include "nsIConsoleService.h"
  49. #include "mozilla/BinarySearch.h"
  50. #include "nsIHttpHeaderVisitor.h"
  51. #include "nsIXULRuntime.h"
  52. #include "nsICacheInfoChannel.h"
  53. #include "nsIDOMWindowUtils.h"
  54. #include <algorithm>
  55. #include "HttpBaseChannel.h"
  56. namespace mozilla {
  57. namespace net {
  58. HttpBaseChannel::HttpBaseChannel()
  59. : mStartPos(UINT64_MAX)
  60. , mStatus(NS_OK)
  61. , mLoadFlags(LOAD_NORMAL)
  62. , mCaps(0)
  63. , mClassOfService(0)
  64. , mPriority(PRIORITY_NORMAL)
  65. , mRedirectionLimit(gHttpHandler->RedirectionLimit())
  66. , mApplyConversion(true)
  67. , mCanceled(false)
  68. , mIsPending(false)
  69. , mWasOpened(false)
  70. , mRequestObserversCalled(false)
  71. , mResponseHeadersModified(false)
  72. , mAllowPipelining(true)
  73. , mAllowSTS(true)
  74. , mThirdPartyFlags(0)
  75. , mUploadStreamHasHeaders(false)
  76. , mInheritApplicationCache(true)
  77. , mChooseApplicationCache(false)
  78. , mLoadedFromApplicationCache(false)
  79. , mChannelIsForDownload(false)
  80. , mTracingEnabled(true)
  81. , mTimingEnabled(false)
  82. , mAllowSpdy(true)
  83. , mAllowAltSvc(true)
  84. , mBeConservative(false)
  85. , mResponseTimeoutEnabled(true)
  86. , mAllRedirectsSameOrigin(true)
  87. , mAllRedirectsPassTimingAllowCheck(true)
  88. , mResponseCouldBeSynthesized(false)
  89. , mBlockAuthPrompt(false)
  90. , mAllowStaleCacheContent(false)
  91. , mSuspendCount(0)
  92. , mInitialRwin(0)
  93. , mProxyResolveFlags(0)
  94. , mProxyURI(nullptr)
  95. , mContentDispositionHint(UINT32_MAX)
  96. , mHttpHandler(gHttpHandler)
  97. , mReferrerPolicy(REFERRER_POLICY_NO_REFERRER_WHEN_DOWNGRADE)
  98. , mRedirectCount(0)
  99. , mInternalRedirectCount(0)
  100. , mForcePending(false)
  101. , mCorsIncludeCredentials(false)
  102. , mCorsMode(nsIHttpChannelInternal::CORS_MODE_NO_CORS)
  103. , mRedirectMode(nsIHttpChannelInternal::REDIRECT_MODE_FOLLOW)
  104. , mFetchCacheMode(nsIHttpChannelInternal::FETCH_CACHE_MODE_DEFAULT)
  105. , mOnStartRequestCalled(false)
  106. , mOnStopRequestCalled(false)
  107. , mAfterOnStartRequestBegun(false)
  108. , mTransferSize(0)
  109. , mDecodedBodySize(0)
  110. , mEncodedBodySize(0)
  111. , mContentWindowId(0)
  112. , mRequireCORSPreflight(false)
  113. , mReportCollector(new ConsoleReportCollector())
  114. , mForceMainDocumentChannel(false)
  115. {
  116. LOG(("Creating HttpBaseChannel @%x\n", this));
  117. // Subfields of unions cannot be targeted in an initializer list.
  118. #ifdef MOZ_VALGRIND
  119. // Zero the entire unions so that Valgrind doesn't complain when we send them
  120. // to another process.
  121. memset(&mSelfAddr, 0, sizeof(NetAddr));
  122. memset(&mPeerAddr, 0, sizeof(NetAddr));
  123. #endif
  124. mSelfAddr.raw.family = PR_AF_UNSPEC;
  125. mPeerAddr.raw.family = PR_AF_UNSPEC;
  126. mRequestContextID.Clear();
  127. }
  128. HttpBaseChannel::~HttpBaseChannel()
  129. {
  130. LOG(("Destroying HttpBaseChannel @%x\n", this));
  131. NS_ReleaseOnMainThread(mLoadInfo.forget());
  132. // Make sure we don't leak
  133. CleanRedirectCacheChainIfNecessary();
  134. }
  135. nsresult
  136. HttpBaseChannel::Init(nsIURI *aURI,
  137. uint32_t aCaps,
  138. nsProxyInfo *aProxyInfo,
  139. uint32_t aProxyResolveFlags,
  140. nsIURI *aProxyURI,
  141. const nsID& aChannelId,
  142. nsContentPolicyType aContentPolicyType)
  143. {
  144. LOG(("HttpBaseChannel::Init [this=%p]\n", this));
  145. NS_PRECONDITION(aURI, "null uri");
  146. mURI = aURI;
  147. mOriginalURI = aURI;
  148. mDocumentURI = nullptr;
  149. mCaps = aCaps;
  150. mProxyResolveFlags = aProxyResolveFlags;
  151. mProxyURI = aProxyURI;
  152. mChannelId = aChannelId;
  153. // Construct connection info object
  154. nsAutoCString host;
  155. int32_t port = -1;
  156. bool isHTTPS = false;
  157. nsresult rv = mURI->GetAsciiHost(host);
  158. if (NS_FAILED(rv)) return rv;
  159. // Reject the URL if it doesn't specify a host
  160. if (host.IsEmpty())
  161. return NS_ERROR_MALFORMED_URI;
  162. rv = mURI->GetPort(&port);
  163. if (NS_FAILED(rv)) return rv;
  164. LOG(("host=%s port=%d\n", host.get(), port));
  165. rv = mURI->GetAsciiSpec(mSpec);
  166. if (NS_FAILED(rv)) return rv;
  167. LOG(("uri=%s\n", mSpec.get()));
  168. // Assert default request method
  169. MOZ_ASSERT(mRequestHead.EqualsMethod(nsHttpRequestHead::kMethod_Get));
  170. // Set request headers
  171. nsAutoCString hostLine;
  172. rv = nsHttpHandler::GenerateHostPort(host, port, hostLine);
  173. if (NS_FAILED(rv)) return rv;
  174. rv = mRequestHead.SetHeader(nsHttp::Host, hostLine);
  175. if (NS_FAILED(rv)) return rv;
  176. rv = gHttpHandler->AddStandardRequestHeaders(&mRequestHead, aContentPolicyType);
  177. if (NS_FAILED(rv)) return rv;
  178. nsAutoCString type;
  179. if (aProxyInfo && NS_SUCCEEDED(aProxyInfo->GetType(type)) &&
  180. !type.EqualsLiteral("unknown"))
  181. mProxyInfo = aProxyInfo;
  182. return rv;
  183. }
  184. //-----------------------------------------------------------------------------
  185. // HttpBaseChannel::nsISupports
  186. //-----------------------------------------------------------------------------
  187. NS_IMPL_ADDREF(HttpBaseChannel)
  188. NS_IMPL_RELEASE(HttpBaseChannel)
  189. NS_INTERFACE_MAP_BEGIN(HttpBaseChannel)
  190. NS_INTERFACE_MAP_ENTRY(nsIRequest)
  191. NS_INTERFACE_MAP_ENTRY(nsIChannel)
  192. NS_INTERFACE_MAP_ENTRY(nsIEncodedChannel)
  193. NS_INTERFACE_MAP_ENTRY(nsIHttpChannel)
  194. NS_INTERFACE_MAP_ENTRY(nsIHttpChannelInternal)
  195. NS_INTERFACE_MAP_ENTRY(nsIForcePendingChannel)
  196. NS_INTERFACE_MAP_ENTRY(nsIUploadChannel)
  197. NS_INTERFACE_MAP_ENTRY(nsIFormPOSTActionChannel)
  198. NS_INTERFACE_MAP_ENTRY(nsIUploadChannel2)
  199. NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)
  200. NS_INTERFACE_MAP_ENTRY(nsITraceableChannel)
  201. NS_INTERFACE_MAP_ENTRY(nsIPrivateBrowsingChannel)
  202. NS_INTERFACE_MAP_ENTRY(nsITimedChannel)
  203. NS_INTERFACE_MAP_ENTRY(nsIConsoleReportCollector)
  204. NS_INTERFACE_MAP_ENTRY(nsIThrottledInputChannel)
  205. NS_INTERFACE_MAP_END_INHERITING(nsHashPropertyBag)
  206. //-----------------------------------------------------------------------------
  207. // HttpBaseChannel::nsIRequest
  208. //-----------------------------------------------------------------------------
  209. NS_IMETHODIMP
  210. HttpBaseChannel::GetName(nsACString& aName)
  211. {
  212. aName = mSpec;
  213. return NS_OK;
  214. }
  215. NS_IMETHODIMP
  216. HttpBaseChannel::IsPending(bool *aIsPending)
  217. {
  218. NS_ENSURE_ARG_POINTER(aIsPending);
  219. *aIsPending = mIsPending || mForcePending;
  220. return NS_OK;
  221. }
  222. NS_IMETHODIMP
  223. HttpBaseChannel::GetStatus(nsresult *aStatus)
  224. {
  225. NS_ENSURE_ARG_POINTER(aStatus);
  226. *aStatus = mStatus;
  227. return NS_OK;
  228. }
  229. NS_IMETHODIMP
  230. HttpBaseChannel::GetLoadGroup(nsILoadGroup **aLoadGroup)
  231. {
  232. NS_ENSURE_ARG_POINTER(aLoadGroup);
  233. *aLoadGroup = mLoadGroup;
  234. NS_IF_ADDREF(*aLoadGroup);
  235. return NS_OK;
  236. }
  237. NS_IMETHODIMP
  238. HttpBaseChannel::SetLoadGroup(nsILoadGroup *aLoadGroup)
  239. {
  240. MOZ_ASSERT(NS_IsMainThread(), "Should only be called on the main thread.");
  241. if (!CanSetLoadGroup(aLoadGroup)) {
  242. return NS_ERROR_FAILURE;
  243. }
  244. mLoadGroup = aLoadGroup;
  245. mProgressSink = nullptr;
  246. UpdatePrivateBrowsing();
  247. return NS_OK;
  248. }
  249. NS_IMETHODIMP
  250. HttpBaseChannel::GetLoadFlags(nsLoadFlags *aLoadFlags)
  251. {
  252. NS_ENSURE_ARG_POINTER(aLoadFlags);
  253. *aLoadFlags = mLoadFlags;
  254. return NS_OK;
  255. }
  256. NS_IMETHODIMP
  257. HttpBaseChannel::SetLoadFlags(nsLoadFlags aLoadFlags)
  258. {
  259. bool synthesized = false;
  260. nsresult rv = GetResponseSynthesized(&synthesized);
  261. NS_ENSURE_SUCCESS(rv, rv);
  262. // If this channel is marked as awaiting a synthesized response,
  263. // modifying certain load flags can interfere with the implementation
  264. // of the network interception logic. This takes care of a couple
  265. // known cases that attempt to mark channels as anonymous due
  266. // to cross-origin redirects; since the response is entirely synthesized
  267. // this is an unnecessary precaution.
  268. // This should be removed when bug 1201683 is fixed.
  269. if (synthesized && aLoadFlags != mLoadFlags) {
  270. aLoadFlags &= ~LOAD_ANONYMOUS;
  271. }
  272. mLoadFlags = aLoadFlags;
  273. mForceMainDocumentChannel = (aLoadFlags & LOAD_DOCUMENT_URI);
  274. return NS_OK;
  275. }
  276. NS_IMETHODIMP
  277. HttpBaseChannel::SetDocshellUserAgentOverride()
  278. {
  279. // This sets the docshell specific user agent override, it will be overwritten
  280. // by UserAgentOverrides.jsm if site-specific user agent overrides are set.
  281. nsresult rv;
  282. nsCOMPtr<nsILoadContext> loadContext;
  283. NS_QueryNotificationCallbacks(this, loadContext);
  284. if (!loadContext) {
  285. return NS_OK;
  286. }
  287. nsCOMPtr<mozIDOMWindowProxy> domWindow;
  288. loadContext->GetAssociatedWindow(getter_AddRefs(domWindow));
  289. if (!domWindow) {
  290. return NS_OK;
  291. }
  292. auto* pDomWindow = nsPIDOMWindowOuter::From(domWindow);
  293. nsIDocShell* docshell = pDomWindow->GetDocShell();
  294. if (!docshell) {
  295. return NS_OK;
  296. }
  297. nsString customUserAgent;
  298. docshell->GetCustomUserAgent(customUserAgent);
  299. if (customUserAgent.IsEmpty()) {
  300. return NS_OK;
  301. }
  302. NS_ConvertUTF16toUTF8 utf8CustomUserAgent(customUserAgent);
  303. rv = SetRequestHeader(NS_LITERAL_CSTRING("User-Agent"), utf8CustomUserAgent, false);
  304. if (NS_FAILED(rv)) return rv;
  305. return NS_OK;
  306. }
  307. //-----------------------------------------------------------------------------
  308. // HttpBaseChannel::nsIChannel
  309. //-----------------------------------------------------------------------------
  310. NS_IMETHODIMP
  311. HttpBaseChannel::GetOriginalURI(nsIURI **aOriginalURI)
  312. {
  313. NS_ENSURE_ARG_POINTER(aOriginalURI);
  314. *aOriginalURI = mOriginalURI;
  315. NS_ADDREF(*aOriginalURI);
  316. return NS_OK;
  317. }
  318. NS_IMETHODIMP
  319. HttpBaseChannel::SetOriginalURI(nsIURI *aOriginalURI)
  320. {
  321. ENSURE_CALLED_BEFORE_CONNECT();
  322. NS_ENSURE_ARG_POINTER(aOriginalURI);
  323. mOriginalURI = aOriginalURI;
  324. return NS_OK;
  325. }
  326. NS_IMETHODIMP
  327. HttpBaseChannel::GetURI(nsIURI **aURI)
  328. {
  329. NS_ENSURE_ARG_POINTER(aURI);
  330. *aURI = mURI;
  331. NS_ADDREF(*aURI);
  332. return NS_OK;
  333. }
  334. NS_IMETHODIMP
  335. HttpBaseChannel::GetOwner(nsISupports **aOwner)
  336. {
  337. NS_ENSURE_ARG_POINTER(aOwner);
  338. *aOwner = mOwner;
  339. NS_IF_ADDREF(*aOwner);
  340. return NS_OK;
  341. }
  342. NS_IMETHODIMP
  343. HttpBaseChannel::SetOwner(nsISupports *aOwner)
  344. {
  345. mOwner = aOwner;
  346. return NS_OK;
  347. }
  348. NS_IMETHODIMP
  349. HttpBaseChannel::SetLoadInfo(nsILoadInfo *aLoadInfo)
  350. {
  351. mLoadInfo = aLoadInfo;
  352. return NS_OK;
  353. }
  354. NS_IMETHODIMP
  355. HttpBaseChannel::GetLoadInfo(nsILoadInfo **aLoadInfo)
  356. {
  357. NS_IF_ADDREF(*aLoadInfo = mLoadInfo);
  358. return NS_OK;
  359. }
  360. NS_IMETHODIMP
  361. HttpBaseChannel::GetNotificationCallbacks(nsIInterfaceRequestor **aCallbacks)
  362. {
  363. *aCallbacks = mCallbacks;
  364. NS_IF_ADDREF(*aCallbacks);
  365. return NS_OK;
  366. }
  367. NS_IMETHODIMP
  368. HttpBaseChannel::SetNotificationCallbacks(nsIInterfaceRequestor *aCallbacks)
  369. {
  370. MOZ_ASSERT(NS_IsMainThread(), "Should only be called on the main thread.");
  371. if (!CanSetCallbacks(aCallbacks)) {
  372. return NS_ERROR_FAILURE;
  373. }
  374. mCallbacks = aCallbacks;
  375. mProgressSink = nullptr;
  376. UpdatePrivateBrowsing();
  377. return NS_OK;
  378. }
  379. NS_IMETHODIMP
  380. HttpBaseChannel::GetContentType(nsACString& aContentType)
  381. {
  382. if (!mResponseHead) {
  383. aContentType.Truncate();
  384. return NS_ERROR_NOT_AVAILABLE;
  385. }
  386. mResponseHead->ContentType(aContentType);
  387. if (!aContentType.IsEmpty()) {
  388. return NS_OK;
  389. }
  390. aContentType.AssignLiteral(UNKNOWN_CONTENT_TYPE);
  391. return NS_OK;
  392. }
  393. NS_IMETHODIMP
  394. HttpBaseChannel::SetContentType(const nsACString& aContentType)
  395. {
  396. if (mListener || mWasOpened) {
  397. if (!mResponseHead)
  398. return NS_ERROR_NOT_AVAILABLE;
  399. nsAutoCString contentTypeBuf, charsetBuf;
  400. bool hadCharset;
  401. net_ParseContentType(aContentType, contentTypeBuf, charsetBuf, &hadCharset);
  402. mResponseHead->SetContentType(contentTypeBuf);
  403. // take care not to stomp on an existing charset
  404. if (hadCharset)
  405. mResponseHead->SetContentCharset(charsetBuf);
  406. } else {
  407. // We are being given a content-type hint.
  408. bool dummy;
  409. net_ParseContentType(aContentType, mContentTypeHint, mContentCharsetHint,
  410. &dummy);
  411. }
  412. return NS_OK;
  413. }
  414. NS_IMETHODIMP
  415. HttpBaseChannel::GetContentCharset(nsACString& aContentCharset)
  416. {
  417. if (!mResponseHead)
  418. return NS_ERROR_NOT_AVAILABLE;
  419. mResponseHead->ContentCharset(aContentCharset);
  420. return NS_OK;
  421. }
  422. NS_IMETHODIMP
  423. HttpBaseChannel::SetContentCharset(const nsACString& aContentCharset)
  424. {
  425. if (mListener) {
  426. if (!mResponseHead)
  427. return NS_ERROR_NOT_AVAILABLE;
  428. mResponseHead->SetContentCharset(aContentCharset);
  429. } else {
  430. // Charset hint
  431. mContentCharsetHint = aContentCharset;
  432. }
  433. return NS_OK;
  434. }
  435. NS_IMETHODIMP
  436. HttpBaseChannel::GetContentDisposition(uint32_t *aContentDisposition)
  437. {
  438. nsresult rv;
  439. nsCString header;
  440. rv = GetContentDispositionHeader(header);
  441. if (NS_FAILED(rv)) {
  442. if (mContentDispositionHint == UINT32_MAX)
  443. return rv;
  444. *aContentDisposition = mContentDispositionHint;
  445. return NS_OK;
  446. }
  447. *aContentDisposition = NS_GetContentDispositionFromHeader(header, this);
  448. return NS_OK;
  449. }
  450. NS_IMETHODIMP
  451. HttpBaseChannel::SetContentDisposition(uint32_t aContentDisposition)
  452. {
  453. mContentDispositionHint = aContentDisposition;
  454. return NS_OK;
  455. }
  456. NS_IMETHODIMP
  457. HttpBaseChannel::GetContentDispositionFilename(nsAString& aContentDispositionFilename)
  458. {
  459. aContentDispositionFilename.Truncate();
  460. nsresult rv;
  461. nsCString header;
  462. rv = GetContentDispositionHeader(header);
  463. if (NS_FAILED(rv)) {
  464. if (!mContentDispositionFilename)
  465. return rv;
  466. aContentDispositionFilename = *mContentDispositionFilename;
  467. return NS_OK;
  468. }
  469. return NS_GetFilenameFromDisposition(aContentDispositionFilename,
  470. header, mURI);
  471. }
  472. NS_IMETHODIMP
  473. HttpBaseChannel::SetContentDispositionFilename(const nsAString& aContentDispositionFilename)
  474. {
  475. mContentDispositionFilename = new nsString(aContentDispositionFilename);
  476. // For safety reasons ensure the filename doesn't contain null characters and
  477. // replace them with underscores. We may later pass the extension to system
  478. // MIME APIs that expect null terminated strings.
  479. mContentDispositionFilename->ReplaceChar(char16_t(0), '_');
  480. return NS_OK;
  481. }
  482. NS_IMETHODIMP
  483. HttpBaseChannel::GetContentDispositionHeader(nsACString& aContentDispositionHeader)
  484. {
  485. if (!mResponseHead)
  486. return NS_ERROR_NOT_AVAILABLE;
  487. nsresult rv = mResponseHead->GetHeader(nsHttp::Content_Disposition,
  488. aContentDispositionHeader);
  489. if (NS_FAILED(rv) || aContentDispositionHeader.IsEmpty())
  490. return NS_ERROR_NOT_AVAILABLE;
  491. return NS_OK;
  492. }
  493. NS_IMETHODIMP
  494. HttpBaseChannel::GetContentLength(int64_t *aContentLength)
  495. {
  496. NS_ENSURE_ARG_POINTER(aContentLength);
  497. if (!mResponseHead)
  498. return NS_ERROR_NOT_AVAILABLE;
  499. *aContentLength = mResponseHead->ContentLength();
  500. return NS_OK;
  501. }
  502. NS_IMETHODIMP
  503. HttpBaseChannel::SetContentLength(int64_t value)
  504. {
  505. NS_NOTYETIMPLEMENTED("HttpBaseChannel::SetContentLength");
  506. return NS_ERROR_NOT_IMPLEMENTED;
  507. }
  508. NS_IMETHODIMP
  509. HttpBaseChannel::Open(nsIInputStream **aResult)
  510. {
  511. NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_IN_PROGRESS);
  512. if (!gHttpHandler->Active()) {
  513. LOG(("HttpBaseChannel::Open after HTTP shutdown..."));
  514. return NS_ERROR_NOT_AVAILABLE;
  515. }
  516. return NS_ImplementChannelOpen(this, aResult);
  517. }
  518. NS_IMETHODIMP
  519. HttpBaseChannel::Open2(nsIInputStream** aStream)
  520. {
  521. if (!gHttpHandler->Active()) {
  522. LOG(("HttpBaseChannel::Open after HTTP shutdown..."));
  523. return NS_ERROR_NOT_AVAILABLE;
  524. }
  525. nsCOMPtr<nsIStreamListener> listener;
  526. nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
  527. NS_ENSURE_SUCCESS(rv, rv);
  528. return Open(aStream);
  529. }
  530. //-----------------------------------------------------------------------------
  531. // HttpBaseChannel::nsIUploadChannel
  532. //-----------------------------------------------------------------------------
  533. NS_IMETHODIMP
  534. HttpBaseChannel::GetUploadStream(nsIInputStream **stream)
  535. {
  536. NS_ENSURE_ARG_POINTER(stream);
  537. *stream = mUploadStream;
  538. NS_IF_ADDREF(*stream);
  539. return NS_OK;
  540. }
  541. NS_IMETHODIMP
  542. HttpBaseChannel::SetUploadStream(nsIInputStream *stream,
  543. const nsACString &contentTypeArg,
  544. int64_t contentLength)
  545. {
  546. // NOTE: for backwards compatibility and for compatibility with old style
  547. // plugins, |stream| may include headers, specifically Content-Type and
  548. // Content-Length headers. in this case, |contentType| and |contentLength|
  549. // would be unspecified. this is traditionally the case of a POST request,
  550. // and so we select POST as the request method if contentType and
  551. // contentLength are unspecified.
  552. if (stream) {
  553. nsAutoCString method;
  554. bool hasHeaders;
  555. // This method and ExplicitSetUploadStream mean different things by "empty
  556. // content type string". This method means "no header", but
  557. // ExplicitSetUploadStream means "header with empty value". So we have to
  558. // massage the contentType argument into the form ExplicitSetUploadStream
  559. // expects.
  560. nsAutoCString contentType;
  561. if (contentTypeArg.IsEmpty()) {
  562. method = NS_LITERAL_CSTRING("POST");
  563. hasHeaders = true;
  564. contentType.SetIsVoid(true);
  565. } else {
  566. method = NS_LITERAL_CSTRING("PUT");
  567. hasHeaders = false;
  568. contentType = contentTypeArg;
  569. }
  570. return ExplicitSetUploadStream(stream, contentType, contentLength,
  571. method, hasHeaders);
  572. }
  573. // if stream is null, ExplicitSetUploadStream returns error.
  574. // So we need special case for GET method.
  575. mUploadStreamHasHeaders = false;
  576. mRequestHead.SetMethod(NS_LITERAL_CSTRING("GET")); // revert to GET request
  577. mUploadStream = stream;
  578. return NS_OK;
  579. }
  580. namespace {
  581. void
  582. CopyComplete(void* aClosure, nsresult aStatus) {
  583. // Called on the STS thread by NS_AsyncCopy
  584. auto channel = static_cast<HttpBaseChannel*>(aClosure);
  585. nsCOMPtr<nsIRunnable> runnable = NewRunnableMethod<nsresult>(
  586. channel, &HttpBaseChannel::EnsureUploadStreamIsCloneableComplete, aStatus);
  587. NS_DispatchToMainThread(runnable.forget());
  588. }
  589. } // anonymous namespace
  590. NS_IMETHODIMP
  591. HttpBaseChannel::EnsureUploadStreamIsCloneable(nsIRunnable* aCallback)
  592. {
  593. MOZ_ASSERT(NS_IsMainThread(), "Should only be called on the main thread.");
  594. NS_ENSURE_ARG_POINTER(aCallback);
  595. // We could in theory allow multiple callers to use this method,
  596. // but the complexity does not seem worth it yet. Just fail if
  597. // this is called more than once simultaneously.
  598. NS_ENSURE_FALSE(mUploadCloneableCallback, NS_ERROR_UNEXPECTED);
  599. // If the CloneUploadStream() will succeed, then synchronously invoke
  600. // the callback to indicate we're already cloneable.
  601. if (!mUploadStream || NS_InputStreamIsCloneable(mUploadStream)) {
  602. aCallback->Run();
  603. return NS_OK;
  604. }
  605. nsCOMPtr<nsIStorageStream> storageStream;
  606. nsresult rv = NS_NewStorageStream(4096, UINT32_MAX,
  607. getter_AddRefs(storageStream));
  608. NS_ENSURE_SUCCESS(rv, rv);
  609. nsCOMPtr<nsIInputStream> newUploadStream;
  610. rv = storageStream->NewInputStream(0, getter_AddRefs(newUploadStream));
  611. NS_ENSURE_SUCCESS(rv, rv);
  612. nsCOMPtr<nsIOutputStream> sink;
  613. rv = storageStream->GetOutputStream(0, getter_AddRefs(sink));
  614. NS_ENSURE_SUCCESS(rv, rv);
  615. nsCOMPtr<nsIInputStream> source;
  616. if (NS_InputStreamIsBuffered(mUploadStream)) {
  617. source = mUploadStream;
  618. } else {
  619. rv = NS_NewBufferedInputStream(getter_AddRefs(source), mUploadStream, 4096);
  620. NS_ENSURE_SUCCESS(rv, rv);
  621. }
  622. nsCOMPtr<nsIEventTarget> target =
  623. do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
  624. mUploadCloneableCallback = aCallback;
  625. rv = NS_AsyncCopy(source, sink, target, NS_ASYNCCOPY_VIA_READSEGMENTS,
  626. 4096, // copy segment size
  627. CopyComplete, this);
  628. if (NS_WARN_IF(NS_FAILED(rv))) {
  629. mUploadCloneableCallback = nullptr;
  630. return rv;
  631. }
  632. // Since we're consuming the old stream, replace it with the new
  633. // stream immediately.
  634. mUploadStream = newUploadStream;
  635. // Explicity hold the stream alive until copying is complete. This will
  636. // be released in EnsureUploadStreamIsCloneableComplete().
  637. AddRef();
  638. return NS_OK;
  639. }
  640. void
  641. HttpBaseChannel::EnsureUploadStreamIsCloneableComplete(nsresult aStatus)
  642. {
  643. MOZ_ASSERT(NS_IsMainThread(), "Should only be called on the main thread.");
  644. MOZ_ASSERT(mUploadCloneableCallback);
  645. if (NS_SUCCEEDED(mStatus)) {
  646. mStatus = aStatus;
  647. }
  648. mUploadCloneableCallback->Run();
  649. mUploadCloneableCallback = nullptr;
  650. // Release the reference we grabbed in EnsureUploadStreamIsCloneable() now
  651. // that the copying is complete.
  652. Release();
  653. }
  654. NS_IMETHODIMP
  655. HttpBaseChannel::CloneUploadStream(nsIInputStream** aClonedStream)
  656. {
  657. NS_ENSURE_ARG_POINTER(aClonedStream);
  658. *aClonedStream = nullptr;
  659. if (!mUploadStream) {
  660. return NS_OK;
  661. }
  662. nsCOMPtr<nsIInputStream> clonedStream;
  663. nsresult rv = NS_CloneInputStream(mUploadStream, getter_AddRefs(clonedStream));
  664. NS_ENSURE_SUCCESS(rv, rv);
  665. clonedStream.forget(aClonedStream);
  666. return NS_OK;
  667. }
  668. //-----------------------------------------------------------------------------
  669. // HttpBaseChannel::nsIUploadChannel2
  670. //-----------------------------------------------------------------------------
  671. NS_IMETHODIMP
  672. HttpBaseChannel::ExplicitSetUploadStream(nsIInputStream *aStream,
  673. const nsACString &aContentType,
  674. int64_t aContentLength,
  675. const nsACString &aMethod,
  676. bool aStreamHasHeaders)
  677. {
  678. // Ensure stream is set and method is valid
  679. NS_ENSURE_TRUE(aStream, NS_ERROR_FAILURE);
  680. if (aContentLength < 0 && !aStreamHasHeaders) {
  681. nsresult rv = aStream->Available(reinterpret_cast<uint64_t*>(&aContentLength));
  682. if (NS_FAILED(rv) || aContentLength < 0) {
  683. NS_ERROR("unable to determine content length");
  684. return NS_ERROR_FAILURE;
  685. }
  686. }
  687. nsresult rv = SetRequestMethod(aMethod);
  688. NS_ENSURE_SUCCESS(rv, rv);
  689. if (!aStreamHasHeaders) {
  690. // SetRequestHeader propagates headers to chrome if HttpChannelChild
  691. nsAutoCString contentLengthStr;
  692. contentLengthStr.AppendInt(aContentLength);
  693. SetRequestHeader(NS_LITERAL_CSTRING("Content-Length"), contentLengthStr,
  694. false);
  695. if (!aContentType.IsVoid()) {
  696. if (aContentType.IsEmpty()) {
  697. SetEmptyRequestHeader(NS_LITERAL_CSTRING("Content-Type"));
  698. } else {
  699. SetRequestHeader(NS_LITERAL_CSTRING("Content-Type"), aContentType,
  700. false);
  701. }
  702. }
  703. }
  704. mUploadStreamHasHeaders = aStreamHasHeaders;
  705. mUploadStream = aStream;
  706. return NS_OK;
  707. }
  708. NS_IMETHODIMP
  709. HttpBaseChannel::GetUploadStreamHasHeaders(bool *hasHeaders)
  710. {
  711. NS_ENSURE_ARG(hasHeaders);
  712. *hasHeaders = mUploadStreamHasHeaders;
  713. return NS_OK;
  714. }
  715. //-----------------------------------------------------------------------------
  716. // HttpBaseChannel::nsIEncodedChannel
  717. //-----------------------------------------------------------------------------
  718. NS_IMETHODIMP
  719. HttpBaseChannel::GetApplyConversion(bool *value)
  720. {
  721. *value = mApplyConversion;
  722. return NS_OK;
  723. }
  724. NS_IMETHODIMP
  725. HttpBaseChannel::SetApplyConversion(bool value)
  726. {
  727. LOG(("HttpBaseChannel::SetApplyConversion [this=%p value=%d]\n", this, value));
  728. mApplyConversion = value;
  729. return NS_OK;
  730. }
  731. nsresult
  732. HttpBaseChannel::DoApplyContentConversions(nsIStreamListener* aNextListener,
  733. nsIStreamListener** aNewNextListener)
  734. {
  735. return DoApplyContentConversions(aNextListener,
  736. aNewNextListener,
  737. mListenerContext);
  738. }
  739. // create a listener chain that looks like this
  740. // http-channel -> decompressor (n times) -> InterceptFailedOnSTop -> channel-creator-listener
  741. //
  742. // we need to do this because not every decompressor has fully streamed output so
  743. // may need a call to OnStopRequest to identify its completion state.. and if it
  744. // creates an error there the channel status code needs to be updated before calling
  745. // the terminal listener. Having the decompress do it via cancel() means channels cannot
  746. // effectively be used in two contexts (specifically this one and a peek context for
  747. // sniffing)
  748. //
  749. class InterceptFailedOnStop : public nsIStreamListener
  750. {
  751. virtual ~InterceptFailedOnStop() {}
  752. nsCOMPtr<nsIStreamListener> mNext;
  753. HttpBaseChannel *mChannel;
  754. public:
  755. InterceptFailedOnStop(nsIStreamListener *arg, HttpBaseChannel *chan)
  756. : mNext(arg)
  757. , mChannel(chan) {}
  758. NS_DECL_THREADSAFE_ISUPPORTS
  759. NS_IMETHOD OnStartRequest(nsIRequest *aRequest, nsISupports *aContext) override
  760. {
  761. return mNext->OnStartRequest(aRequest, aContext);
  762. }
  763. NS_IMETHOD OnStopRequest(nsIRequest *aRequest, nsISupports *aContext, nsresult aStatusCode) override
  764. {
  765. if (NS_FAILED(aStatusCode) && NS_SUCCEEDED(mChannel->mStatus)) {
  766. LOG(("HttpBaseChannel::InterceptFailedOnStop %p seting status %x", mChannel, aStatusCode));
  767. mChannel->mStatus = aStatusCode;
  768. }
  769. return mNext->OnStopRequest(aRequest, aContext, aStatusCode);
  770. }
  771. NS_IMETHOD OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext,
  772. nsIInputStream *aInputStream, uint64_t aOffset,
  773. uint32_t aCount) override
  774. {
  775. return mNext->OnDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount);
  776. }
  777. };
  778. NS_IMPL_ISUPPORTS(InterceptFailedOnStop, nsIStreamListener, nsIRequestObserver)
  779. NS_IMETHODIMP
  780. HttpBaseChannel::DoApplyContentConversions(nsIStreamListener* aNextListener,
  781. nsIStreamListener** aNewNextListener,
  782. nsISupports *aCtxt)
  783. {
  784. *aNewNextListener = nullptr;
  785. if (!mResponseHead || ! aNextListener) {
  786. return NS_OK;
  787. }
  788. LOG(("HttpBaseChannel::DoApplyContentConversions [this=%p]\n", this));
  789. if (!mApplyConversion) {
  790. LOG(("not applying conversion per mApplyConversion\n"));
  791. return NS_OK;
  792. }
  793. if (!mAvailableCachedAltDataType.IsEmpty()) {
  794. LOG(("not applying conversion because delivering alt-data\n"));
  795. return NS_OK;
  796. }
  797. nsAutoCString contentEncoding;
  798. nsresult rv = mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding);
  799. if (NS_FAILED(rv) || contentEncoding.IsEmpty())
  800. return NS_OK;
  801. nsCOMPtr<nsIStreamListener> nextListener = new InterceptFailedOnStop(aNextListener, this);
  802. // The encodings are listed in the order they were applied
  803. // (see rfc 2616 section 14.11), so they need to removed in reverse
  804. // order. This is accomplished because the converter chain ends up
  805. // being a stack with the last converter created being the first one
  806. // to accept the raw network data.
  807. char* cePtr = contentEncoding.BeginWriting();
  808. uint32_t count = 0;
  809. while (char* val = nsCRT::strtok(cePtr, HTTP_LWS ",", &cePtr)) {
  810. if (++count > 16) {
  811. // That's ridiculous. We only understand 2 different ones :)
  812. // but for compatibility with old code, we will just carry on without
  813. // removing the encodings
  814. LOG(("Too many Content-Encodings. Ignoring remainder.\n"));
  815. break;
  816. }
  817. if (gHttpHandler->IsAcceptableEncoding(val)) {
  818. nsCOMPtr<nsIStreamConverterService> serv;
  819. rv = gHttpHandler->GetStreamConverterService(getter_AddRefs(serv));
  820. // we won't fail to load the page just because we couldn't load the
  821. // stream converter service.. carry on..
  822. if (NS_FAILED(rv)) {
  823. if (val)
  824. LOG(("Unknown content encoding '%s', ignoring\n", val));
  825. continue;
  826. }
  827. nsCOMPtr<nsIStreamListener> converter;
  828. nsAutoCString from(val);
  829. ToLowerCase(from);
  830. rv = serv->AsyncConvertData(from.get(),
  831. "uncompressed",
  832. nextListener,
  833. aCtxt,
  834. getter_AddRefs(converter));
  835. if (NS_FAILED(rv)) {
  836. LOG(("Unexpected failure of AsyncConvertData %s\n", val));
  837. return rv;
  838. }
  839. LOG(("converter removed '%s' content-encoding\n", val));
  840. nextListener = converter;
  841. }
  842. else {
  843. if (val)
  844. LOG(("Unknown content encoding '%s', ignoring\n", val));
  845. }
  846. }
  847. *aNewNextListener = nextListener;
  848. NS_IF_ADDREF(*aNewNextListener);
  849. return NS_OK;
  850. }
  851. NS_IMETHODIMP
  852. HttpBaseChannel::GetContentEncodings(nsIUTF8StringEnumerator** aEncodings)
  853. {
  854. if (!mResponseHead) {
  855. *aEncodings = nullptr;
  856. return NS_OK;
  857. }
  858. nsAutoCString encoding;
  859. mResponseHead->GetHeader(nsHttp::Content_Encoding, encoding);
  860. if (encoding.IsEmpty()) {
  861. *aEncodings = nullptr;
  862. return NS_OK;
  863. }
  864. nsContentEncodings* enumerator = new nsContentEncodings(this,
  865. encoding.get());
  866. NS_ADDREF(*aEncodings = enumerator);
  867. return NS_OK;
  868. }
  869. //-----------------------------------------------------------------------------
  870. // HttpBaseChannel::nsContentEncodings <public>
  871. //-----------------------------------------------------------------------------
  872. HttpBaseChannel::nsContentEncodings::nsContentEncodings(nsIHttpChannel* aChannel,
  873. const char* aEncodingHeader)
  874. : mEncodingHeader(aEncodingHeader)
  875. , mChannel(aChannel)
  876. , mReady(false)
  877. {
  878. mCurEnd = aEncodingHeader + strlen(aEncodingHeader);
  879. mCurStart = mCurEnd;
  880. }
  881. HttpBaseChannel::nsContentEncodings::~nsContentEncodings()
  882. {
  883. }
  884. //-----------------------------------------------------------------------------
  885. // HttpBaseChannel::nsContentEncodings::nsISimpleEnumerator
  886. //-----------------------------------------------------------------------------
  887. NS_IMETHODIMP
  888. HttpBaseChannel::nsContentEncodings::HasMore(bool* aMoreEncodings)
  889. {
  890. if (mReady) {
  891. *aMoreEncodings = true;
  892. return NS_OK;
  893. }
  894. nsresult rv = PrepareForNext();
  895. *aMoreEncodings = NS_SUCCEEDED(rv);
  896. return NS_OK;
  897. }
  898. NS_IMETHODIMP
  899. HttpBaseChannel::nsContentEncodings::GetNext(nsACString& aNextEncoding)
  900. {
  901. aNextEncoding.Truncate();
  902. if (!mReady) {
  903. nsresult rv = PrepareForNext();
  904. if (NS_FAILED(rv)) {
  905. return NS_ERROR_FAILURE;
  906. }
  907. }
  908. const nsACString & encoding = Substring(mCurStart, mCurEnd);
  909. nsACString::const_iterator start, end;
  910. encoding.BeginReading(start);
  911. encoding.EndReading(end);
  912. bool haveType = false;
  913. if (CaseInsensitiveFindInReadable(NS_LITERAL_CSTRING("gzip"), start, end)) {
  914. aNextEncoding.AssignLiteral(APPLICATION_GZIP);
  915. haveType = true;
  916. }
  917. if (!haveType) {
  918. encoding.BeginReading(start);
  919. if (CaseInsensitiveFindInReadable(NS_LITERAL_CSTRING("compress"), start, end)) {
  920. aNextEncoding.AssignLiteral(APPLICATION_COMPRESS);
  921. haveType = true;
  922. }
  923. }
  924. if (!haveType) {
  925. encoding.BeginReading(start);
  926. if (CaseInsensitiveFindInReadable(NS_LITERAL_CSTRING("deflate"), start, end)) {
  927. aNextEncoding.AssignLiteral(APPLICATION_ZIP);
  928. haveType = true;
  929. }
  930. }
  931. if (!haveType) {
  932. encoding.BeginReading(start);
  933. if (CaseInsensitiveFindInReadable(NS_LITERAL_CSTRING("br"), start, end)) {
  934. aNextEncoding.AssignLiteral(APPLICATION_BROTLI);
  935. haveType = true;
  936. }
  937. }
  938. // Prepare to fetch the next encoding
  939. mCurEnd = mCurStart;
  940. mReady = false;
  941. if (haveType)
  942. return NS_OK;
  943. NS_WARNING("Unknown encoding type");
  944. return NS_ERROR_FAILURE;
  945. }
  946. //-----------------------------------------------------------------------------
  947. // HttpBaseChannel::nsContentEncodings::nsISupports
  948. //-----------------------------------------------------------------------------
  949. NS_IMPL_ISUPPORTS(HttpBaseChannel::nsContentEncodings, nsIUTF8StringEnumerator)
  950. //-----------------------------------------------------------------------------
  951. // HttpBaseChannel::nsContentEncodings <private>
  952. //-----------------------------------------------------------------------------
  953. nsresult
  954. HttpBaseChannel::nsContentEncodings::PrepareForNext(void)
  955. {
  956. MOZ_ASSERT(mCurStart == mCurEnd, "Indeterminate state");
  957. // At this point both mCurStart and mCurEnd point to somewhere
  958. // past the end of the next thing we want to return
  959. while (mCurEnd != mEncodingHeader) {
  960. --mCurEnd;
  961. if (*mCurEnd != ',' && !nsCRT::IsAsciiSpace(*mCurEnd))
  962. break;
  963. }
  964. if (mCurEnd == mEncodingHeader)
  965. return NS_ERROR_NOT_AVAILABLE; // no more encodings
  966. ++mCurEnd;
  967. // At this point mCurEnd points to the first char _after_ the
  968. // header we want. Furthermore, mCurEnd - 1 != mEncodingHeader
  969. mCurStart = mCurEnd - 1;
  970. while (mCurStart != mEncodingHeader &&
  971. *mCurStart != ',' && !nsCRT::IsAsciiSpace(*mCurStart))
  972. --mCurStart;
  973. if (*mCurStart == ',' || nsCRT::IsAsciiSpace(*mCurStart))
  974. ++mCurStart; // we stopped because of a weird char, so move up one
  975. // At this point mCurStart and mCurEnd bracket the encoding string
  976. // we want. Check that it's not "identity"
  977. if (Substring(mCurStart, mCurEnd).Equals("identity",
  978. nsCaseInsensitiveCStringComparator())) {
  979. mCurEnd = mCurStart;
  980. return PrepareForNext();
  981. }
  982. mReady = true;
  983. return NS_OK;
  984. }
  985. //-----------------------------------------------------------------------------
  986. // HttpBaseChannel::nsIHttpChannel
  987. //-----------------------------------------------------------------------------
  988. NS_IMETHODIMP
  989. HttpBaseChannel::GetChannelId(nsACString& aChannelId)
  990. {
  991. char id[NSID_LENGTH];
  992. mChannelId.ToProvidedString(id);
  993. aChannelId.AssignASCII(id);
  994. return NS_OK;
  995. }
  996. NS_IMETHODIMP
  997. HttpBaseChannel::SetChannelId(const nsACString& aChannelId)
  998. {
  999. nsID newId;
  1000. nsAutoCString idStr(aChannelId);
  1001. if (newId.Parse(idStr.get())) {
  1002. mChannelId = newId;
  1003. return NS_OK;
  1004. }
  1005. return NS_ERROR_FAILURE;
  1006. }
  1007. NS_IMETHODIMP HttpBaseChannel::GetTopLevelContentWindowId(uint64_t *aWindowId)
  1008. {
  1009. if (!mContentWindowId) {
  1010. nsCOMPtr<nsILoadContext> loadContext;
  1011. GetCallback(loadContext);
  1012. if (loadContext) {
  1013. nsCOMPtr<mozIDOMWindowProxy> topWindow;
  1014. loadContext->GetTopWindow(getter_AddRefs(topWindow));
  1015. nsCOMPtr<nsIDOMWindowUtils> windowUtils = do_GetInterface(topWindow);
  1016. if (windowUtils) {
  1017. windowUtils->GetCurrentInnerWindowID(&mContentWindowId);
  1018. }
  1019. }
  1020. }
  1021. *aWindowId = mContentWindowId;
  1022. return NS_OK;
  1023. }
  1024. NS_IMETHODIMP HttpBaseChannel::SetTopLevelContentWindowId(uint64_t aWindowId)
  1025. {
  1026. mContentWindowId = aWindowId;
  1027. return NS_OK;
  1028. }
  1029. NS_IMETHODIMP
  1030. HttpBaseChannel::GetTransferSize(uint64_t *aTransferSize)
  1031. {
  1032. *aTransferSize = mTransferSize;
  1033. return NS_OK;
  1034. }
  1035. NS_IMETHODIMP
  1036. HttpBaseChannel::GetDecodedBodySize(uint64_t *aDecodedBodySize)
  1037. {
  1038. *aDecodedBodySize = mDecodedBodySize;
  1039. return NS_OK;
  1040. }
  1041. NS_IMETHODIMP
  1042. HttpBaseChannel::GetEncodedBodySize(uint64_t *aEncodedBodySize)
  1043. {
  1044. *aEncodedBodySize = mEncodedBodySize;
  1045. return NS_OK;
  1046. }
  1047. NS_IMETHODIMP
  1048. HttpBaseChannel::GetRequestMethod(nsACString& aMethod)
  1049. {
  1050. mRequestHead.Method(aMethod);
  1051. return NS_OK;
  1052. }
  1053. NS_IMETHODIMP
  1054. HttpBaseChannel::SetRequestMethod(const nsACString& aMethod)
  1055. {
  1056. ENSURE_CALLED_BEFORE_CONNECT();
  1057. const nsCString& flatMethod = PromiseFlatCString(aMethod);
  1058. // Method names are restricted to valid HTTP tokens.
  1059. if (!nsHttp::IsValidToken(flatMethod))
  1060. return NS_ERROR_INVALID_ARG;
  1061. mRequestHead.SetMethod(flatMethod);
  1062. return NS_OK;
  1063. }
  1064. NS_IMETHODIMP
  1065. HttpBaseChannel::GetNetworkInterfaceId(nsACString& aNetworkInterfaceId)
  1066. {
  1067. aNetworkInterfaceId = mNetworkInterfaceId;
  1068. return NS_OK;
  1069. }
  1070. NS_IMETHODIMP
  1071. HttpBaseChannel::SetNetworkInterfaceId(const nsACString& aNetworkInterfaceId)
  1072. {
  1073. ENSURE_CALLED_BEFORE_CONNECT();
  1074. mNetworkInterfaceId = aNetworkInterfaceId;
  1075. return NS_OK;
  1076. }
  1077. NS_IMETHODIMP
  1078. HttpBaseChannel::GetReferrer(nsIURI **referrer)
  1079. {
  1080. NS_ENSURE_ARG_POINTER(referrer);
  1081. *referrer = mReferrer;
  1082. NS_IF_ADDREF(*referrer);
  1083. return NS_OK;
  1084. }
  1085. NS_IMETHODIMP
  1086. HttpBaseChannel::SetReferrer(nsIURI *referrer)
  1087. {
  1088. return SetReferrerWithPolicy(referrer, REFERRER_POLICY_NO_REFERRER_WHEN_DOWNGRADE);
  1089. }
  1090. NS_IMETHODIMP
  1091. HttpBaseChannel::GetReferrerPolicy(uint32_t *referrerPolicy)
  1092. {
  1093. NS_ENSURE_ARG_POINTER(referrerPolicy);
  1094. *referrerPolicy = mReferrerPolicy;
  1095. return NS_OK;
  1096. }
  1097. NS_IMETHODIMP
  1098. HttpBaseChannel::SetReferrerWithPolicy(nsIURI *referrer,
  1099. uint32_t referrerPolicy)
  1100. {
  1101. ENSURE_CALLED_BEFORE_CONNECT();
  1102. // clear existing referrer, if any
  1103. mReferrer = nullptr;
  1104. nsresult rv = mRequestHead.ClearHeader(nsHttp::Referer);
  1105. if(NS_FAILED(rv)) {
  1106. return rv;
  1107. }
  1108. mReferrerPolicy = REFERRER_POLICY_NO_REFERRER_WHEN_DOWNGRADE;
  1109. if (!referrer) {
  1110. return NS_OK;
  1111. }
  1112. // Don't send referrer at all when the meta referrer setting is "no-referrer"
  1113. if (referrerPolicy == REFERRER_POLICY_NO_REFERRER) {
  1114. mReferrerPolicy = REFERRER_POLICY_NO_REFERRER;
  1115. return NS_OK;
  1116. }
  1117. // 0: never send referer
  1118. // 1: send referer for direct user action
  1119. // 2: always send referer
  1120. uint32_t userReferrerLevel = gHttpHandler->ReferrerLevel();
  1121. // false: use real referrer
  1122. // true: spoof with URI of the current request
  1123. bool userSpoofReferrerSource = gHttpHandler->SpoofReferrerSource();
  1124. // 0: full URI
  1125. // 1: scheme+host+port+path
  1126. // 2: scheme+host+port
  1127. int userReferrerTrimmingPolicy = gHttpHandler->ReferrerTrimmingPolicy();
  1128. // 0: send referer no matter what
  1129. // 1: send referer ONLY when base domains match
  1130. // 2: send referer ONLY when hosts match
  1131. int userReferrerXOriginPolicy = gHttpHandler->ReferrerXOriginPolicy();
  1132. // check referrer blocking pref
  1133. uint32_t referrerLevel;
  1134. if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) {
  1135. referrerLevel = 1; // user action
  1136. } else {
  1137. referrerLevel = 2; // inline content
  1138. }
  1139. if (userReferrerLevel < referrerLevel) {
  1140. return NS_OK;
  1141. }
  1142. nsCOMPtr<nsIURI> referrerGrip;
  1143. bool match;
  1144. //
  1145. // Strip off "wyciwyg://123/" from wyciwyg referrers.
  1146. //
  1147. // XXX this really belongs elsewhere since wyciwyg URLs aren't part of necko.
  1148. // perhaps some sort of generic nsINestedURI could be used. then, if an URI
  1149. // fails the whitelist test, then we could check for an inner URI and try
  1150. // that instead. though, that might be too automatic.
  1151. //
  1152. rv = referrer->SchemeIs("wyciwyg", &match);
  1153. if (NS_FAILED(rv)) return rv;
  1154. if (match) {
  1155. nsAutoCString path;
  1156. rv = referrer->GetPath(path);
  1157. if (NS_FAILED(rv)) return rv;
  1158. uint32_t pathLength = path.Length();
  1159. if (pathLength <= 2) return NS_ERROR_FAILURE;
  1160. // Path is of the form "//123/http://foo/bar", with a variable number of
  1161. // digits. To figure out where the "real" URL starts, search path for a
  1162. // '/', starting at the third character.
  1163. int32_t slashIndex = path.FindChar('/', 2);
  1164. if (slashIndex == kNotFound) return NS_ERROR_FAILURE;
  1165. // Get charset of the original URI so we can pass it to our fixed up URI.
  1166. nsAutoCString charset;
  1167. referrer->GetOriginCharset(charset);
  1168. // Replace |referrer| with a URI without wyciwyg://123/.
  1169. rv = NS_NewURI(getter_AddRefs(referrerGrip),
  1170. Substring(path, slashIndex + 1, pathLength - slashIndex - 1),
  1171. charset.get());
  1172. if (NS_FAILED(rv)) return rv;
  1173. referrer = referrerGrip.get();
  1174. }
  1175. //
  1176. // block referrer if not on our white list...
  1177. //
  1178. static const char *const referrerWhiteList[] = {
  1179. "http",
  1180. "https",
  1181. "ftp",
  1182. nullptr
  1183. };
  1184. match = false;
  1185. const char *const *scheme = referrerWhiteList;
  1186. for (; *scheme && !match; ++scheme) {
  1187. rv = referrer->SchemeIs(*scheme, &match);
  1188. if (NS_FAILED(rv)) return rv;
  1189. }
  1190. if (!match) return NS_OK; // kick out....
  1191. //
  1192. // Handle secure referrals.
  1193. //
  1194. // Support referrals from a secure server if this is a secure site
  1195. // and (optionally) if the host names are the same.
  1196. //
  1197. rv = referrer->SchemeIs("https", &match);
  1198. if (NS_FAILED(rv)) return rv;
  1199. if (match) {
  1200. rv = mURI->SchemeIs("https", &match);
  1201. if (NS_FAILED(rv)) return rv;
  1202. // It's ok to send referrer for https-to-http scenarios if the referrer
  1203. // policy is "unsafe-url", "origin", or "origin-when-cross-origin".
  1204. if (referrerPolicy != REFERRER_POLICY_UNSAFE_URL &&
  1205. referrerPolicy != REFERRER_POLICY_ORIGIN_WHEN_XORIGIN &&
  1206. referrerPolicy != REFERRER_POLICY_ORIGIN) {
  1207. // in other referrer policies, https->http is not allowed...
  1208. if (!match) return NS_OK;
  1209. }
  1210. }
  1211. // for cross-origin-based referrer changes (not just host-based), figure out
  1212. // if the referrer is being sent cross-origin.
  1213. nsCOMPtr<nsIURI> triggeringURI;
  1214. bool isCrossOrigin = true;
  1215. if (mLoadInfo) {
  1216. nsCOMPtr<nsIPrincipal> triggeringPrincipal = mLoadInfo->TriggeringPrincipal();
  1217. if (triggeringPrincipal) {
  1218. triggeringPrincipal->GetURI(getter_AddRefs(triggeringURI));
  1219. }
  1220. }
  1221. if (triggeringURI) {
  1222. if (LOG_ENABLED()) {
  1223. nsAutoCString triggeringURISpec;
  1224. rv = triggeringURI->GetAsciiSpec(triggeringURISpec);
  1225. if (!NS_FAILED(rv)) {
  1226. LOG(("triggeringURI=%s\n", triggeringURISpec.get()));
  1227. }
  1228. }
  1229. nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
  1230. rv = ssm->CheckSameOriginURI(triggeringURI, mURI, false);
  1231. isCrossOrigin = NS_FAILED(rv);
  1232. } else {
  1233. LOG(("no triggering principal available via loadInfo, assuming load is cross-origin"));
  1234. }
  1235. // Don't send referrer when the request is cross-origin and policy is "same-origin".
  1236. if (isCrossOrigin && referrerPolicy == REFERRER_POLICY_SAME_ORIGIN) {
  1237. mReferrerPolicy = REFERRER_POLICY_SAME_ORIGIN;
  1238. return NS_OK;
  1239. }
  1240. nsCOMPtr<nsIURI> clone;
  1241. //
  1242. // we need to clone the referrer, so we can:
  1243. // (1) modify it
  1244. // (2) keep a reference to it after returning from this function
  1245. //
  1246. // Use CloneIgnoringRef to strip away any fragment per RFC 2616 section 14.36
  1247. // and Referrer Policy section 6.3.5.
  1248. rv = referrer->CloneIgnoringRef(getter_AddRefs(clone));
  1249. if (NS_FAILED(rv)) return rv;
  1250. nsAutoCString currentHost;
  1251. nsAutoCString referrerHost;
  1252. rv = mURI->GetAsciiHost(currentHost);
  1253. if (NS_FAILED(rv)) return rv;
  1254. rv = clone->GetAsciiHost(referrerHost);
  1255. if (NS_FAILED(rv)) return rv;
  1256. // check policy for sending ref only when hosts match
  1257. if (userReferrerXOriginPolicy == 2 && !currentHost.Equals(referrerHost))
  1258. return NS_OK;
  1259. if (userReferrerXOriginPolicy == 1) {
  1260. nsAutoCString currentDomain = currentHost;
  1261. nsAutoCString referrerDomain = referrerHost;
  1262. uint32_t extraDomains = 0;
  1263. nsCOMPtr<nsIEffectiveTLDService> eTLDService = do_GetService(
  1264. NS_EFFECTIVETLDSERVICE_CONTRACTID);
  1265. if (eTLDService) {
  1266. rv = eTLDService->GetBaseDomain(mURI, extraDomains, currentDomain);
  1267. if (NS_FAILED(rv)) return rv;
  1268. rv = eTLDService->GetBaseDomain(clone, extraDomains, referrerDomain);
  1269. if (NS_FAILED(rv)) return rv;
  1270. }
  1271. // check policy for sending only when effective top level domain matches.
  1272. // this falls back on using host if eTLDService does not work
  1273. if (!currentDomain.Equals(referrerDomain))
  1274. return NS_OK;
  1275. }
  1276. // send spoofed referrer if desired
  1277. if (userSpoofReferrerSource) {
  1278. nsCOMPtr<nsIURI> mURIclone;
  1279. rv = mURI->CloneIgnoringRef(getter_AddRefs(mURIclone));
  1280. if (NS_FAILED(rv)) return rv;
  1281. clone = mURIclone;
  1282. currentHost = referrerHost;
  1283. }
  1284. // strip away any userpass; we don't want to be giving out passwords ;-)
  1285. // This is required by Referrer Policy stripping algorithm.
  1286. rv = clone->SetUserPass(EmptyCString());
  1287. if (NS_FAILED(rv)) return rv;
  1288. nsAutoCString spec;
  1289. // Apply the user cross-origin trimming policy if it's more
  1290. // restrictive than the general one.
  1291. if (isCrossOrigin) {
  1292. int userReferrerXOriginTrimmingPolicy =
  1293. gHttpHandler->ReferrerXOriginTrimmingPolicy();
  1294. userReferrerTrimmingPolicy =
  1295. std::max(userReferrerTrimmingPolicy, userReferrerXOriginTrimmingPolicy);
  1296. }
  1297. // site-specified referrer trimming may affect the trim level
  1298. // "unsafe-url" behaves like "origin" (send referrer in the same situations) but
  1299. // "unsafe-url" sends the whole referrer and origin removes the path.
  1300. // "origin-when-cross-origin" trims the referrer only when the request is
  1301. // cross-origin.
  1302. // "Strict" request from https->http case was bailed out, so here:
  1303. // "strict-origin" behaves the same as "origin".
  1304. // "strict-origin-when-cross-origin" behaves the same as "origin-when-cross-origin"
  1305. if (referrerPolicy == REFERRER_POLICY_ORIGIN ||
  1306. referrerPolicy == REFERRER_POLICY_STRICT_ORIGIN ||
  1307. (isCrossOrigin && (referrerPolicy == REFERRER_POLICY_ORIGIN_WHEN_XORIGIN ||
  1308. referrerPolicy == REFERRER_POLICY_STRICT_ORIGIN_WHEN_XORIGIN))) {
  1309. // We can override the user trimming preference because "origin"
  1310. // (network.http.referer.trimmingPolicy = 2) is the strictest
  1311. // trimming policy that users can specify.
  1312. userReferrerTrimmingPolicy = 2;
  1313. }
  1314. // check how much referer to send
  1315. if (userReferrerTrimmingPolicy) {
  1316. // All output strings start with: scheme+host+port
  1317. // We want the IDN-normalized PrePath. That's not something currently
  1318. // available and there doesn't yet seem to be justification for adding it to
  1319. // the interfaces, so just build it up ourselves from scheme+AsciiHostPort
  1320. nsAutoCString scheme, asciiHostPort;
  1321. rv = clone->GetScheme(scheme);
  1322. if (NS_FAILED(rv)) return rv;
  1323. spec = scheme;
  1324. spec.AppendLiteral("://");
  1325. // Note we explicitly cleared UserPass above, so do not need to build it.
  1326. rv = clone->GetAsciiHostPort(asciiHostPort);
  1327. if (NS_FAILED(rv)) return rv;
  1328. spec.Append(asciiHostPort);
  1329. switch (userReferrerTrimmingPolicy) {
  1330. case 1: { // scheme+host+port+path
  1331. nsCOMPtr<nsIURL> url(do_QueryInterface(clone));
  1332. if (url) {
  1333. nsAutoCString path;
  1334. rv = url->GetFilePath(path);
  1335. if (NS_FAILED(rv)) return rv;
  1336. spec.Append(path);
  1337. rv = url->SetQuery(EmptyCString());
  1338. if (NS_FAILED(rv)) return rv;
  1339. rv = url->SetRef(EmptyCString());
  1340. if (NS_FAILED(rv)) return rv;
  1341. break;
  1342. }
  1343. // No URL, so fall through to truncating the path and any query/ref off
  1344. // as well.
  1345. }
  1346. MOZ_FALLTHROUGH;
  1347. default: // (Pref limited to [0,2] enforced by clamp, MOZ_CRASH overkill.)
  1348. case 2: // scheme+host+port+/
  1349. spec.AppendLiteral("/");
  1350. // This nukes any query/ref present as well in the case of nsStandardURL
  1351. rv = clone->SetPath(EmptyCString());
  1352. if (NS_FAILED(rv)) return rv;
  1353. break;
  1354. }
  1355. } else {
  1356. // use the full URI
  1357. rv = clone->GetAsciiSpec(spec);
  1358. if (NS_FAILED(rv)) return rv;
  1359. }
  1360. // finally, remember the referrer URI and set the Referer header.
  1361. rv = SetRequestHeader(NS_LITERAL_CSTRING("Referer"), spec, false);
  1362. if (NS_FAILED(rv)) return rv;
  1363. mReferrer = clone;
  1364. mReferrerPolicy = referrerPolicy;
  1365. return NS_OK;
  1366. }
  1367. // Return the channel's proxy URI, or if it doesn't exist, the
  1368. // channel's main URI.
  1369. NS_IMETHODIMP
  1370. HttpBaseChannel::GetProxyURI(nsIURI **aOut)
  1371. {
  1372. NS_ENSURE_ARG_POINTER(aOut);
  1373. nsCOMPtr<nsIURI> result(mProxyURI);
  1374. result.forget(aOut);
  1375. return NS_OK;
  1376. }
  1377. NS_IMETHODIMP
  1378. HttpBaseChannel::GetRequestHeader(const nsACString& aHeader,
  1379. nsACString& aValue)
  1380. {
  1381. aValue.Truncate();
  1382. // XXX might be better to search the header list directly instead of
  1383. // hitting the http atom hash table.
  1384. nsHttpAtom atom = nsHttp::ResolveAtom(aHeader);
  1385. if (!atom)
  1386. return NS_ERROR_NOT_AVAILABLE;
  1387. return mRequestHead.GetHeader(atom, aValue);
  1388. }
  1389. NS_IMETHODIMP
  1390. HttpBaseChannel::SetRequestHeader(const nsACString& aHeader,
  1391. const nsACString& aValue,
  1392. bool aMerge)
  1393. {
  1394. const nsCString &flatHeader = PromiseFlatCString(aHeader);
  1395. const nsCString &flatValue = PromiseFlatCString(aValue);
  1396. LOG(("HttpBaseChannel::SetRequestHeader [this=%p header=\"%s\" value=\"%s\" merge=%u]\n",
  1397. this, flatHeader.get(), flatValue.get(), aMerge));
  1398. // Verify header names are valid HTTP tokens and header values are reasonably
  1399. // close to whats allowed in RFC 2616.
  1400. if (!nsHttp::IsValidToken(flatHeader) ||
  1401. !nsHttp::IsReasonableHeaderValue(flatValue)) {
  1402. return NS_ERROR_INVALID_ARG;
  1403. }
  1404. return mRequestHead.SetHeader(aHeader, flatValue, aMerge);
  1405. }
  1406. NS_IMETHODIMP
  1407. HttpBaseChannel::SetEmptyRequestHeader(const nsACString& aHeader)
  1408. {
  1409. const nsCString &flatHeader = PromiseFlatCString(aHeader);
  1410. LOG(("HttpBaseChannel::SetEmptyRequestHeader [this=%p header=\"%s\"]\n",
  1411. this, flatHeader.get()));
  1412. // Verify header names are valid HTTP tokens and header values are reasonably
  1413. // close to whats allowed in RFC 2616.
  1414. if (!nsHttp::IsValidToken(flatHeader)) {
  1415. return NS_ERROR_INVALID_ARG;
  1416. }
  1417. return mRequestHead.SetEmptyHeader(aHeader);
  1418. }
  1419. NS_IMETHODIMP
  1420. HttpBaseChannel::VisitRequestHeaders(nsIHttpHeaderVisitor *visitor)
  1421. {
  1422. return mRequestHead.VisitHeaders(visitor);
  1423. }
  1424. NS_IMETHODIMP
  1425. HttpBaseChannel::VisitNonDefaultRequestHeaders(nsIHttpHeaderVisitor *visitor)
  1426. {
  1427. return mRequestHead.VisitHeaders(visitor,
  1428. nsHttpHeaderArray::eFilterSkipDefault);
  1429. }
  1430. NS_IMETHODIMP
  1431. HttpBaseChannel::GetResponseHeader(const nsACString &header, nsACString &value)
  1432. {
  1433. value.Truncate();
  1434. if (!mResponseHead)
  1435. return NS_ERROR_NOT_AVAILABLE;
  1436. nsHttpAtom atom = nsHttp::ResolveAtom(header);
  1437. if (!atom)
  1438. return NS_ERROR_NOT_AVAILABLE;
  1439. return mResponseHead->GetHeader(atom, value);
  1440. }
  1441. NS_IMETHODIMP
  1442. HttpBaseChannel::SetResponseHeader(const nsACString& header,
  1443. const nsACString& value,
  1444. bool merge)
  1445. {
  1446. LOG(("HttpBaseChannel::SetResponseHeader [this=%p header=\"%s\" value=\"%s\" merge=%u]\n",
  1447. this, PromiseFlatCString(header).get(), PromiseFlatCString(value).get(), merge));
  1448. if (!mResponseHead)
  1449. return NS_ERROR_NOT_AVAILABLE;
  1450. nsHttpAtom atom = nsHttp::ResolveAtom(header);
  1451. if (!atom)
  1452. return NS_ERROR_NOT_AVAILABLE;
  1453. // these response headers must not be changed
  1454. if (atom == nsHttp::Content_Type ||
  1455. atom == nsHttp::Content_Length ||
  1456. atom == nsHttp::Content_Encoding ||
  1457. atom == nsHttp::Trailer ||
  1458. atom == nsHttp::Transfer_Encoding)
  1459. return NS_ERROR_ILLEGAL_VALUE;
  1460. mResponseHeadersModified = true;
  1461. return mResponseHead->SetHeader(header, value, merge);
  1462. }
  1463. NS_IMETHODIMP
  1464. HttpBaseChannel::VisitResponseHeaders(nsIHttpHeaderVisitor *visitor)
  1465. {
  1466. if (!mResponseHead) {
  1467. return NS_ERROR_NOT_AVAILABLE;
  1468. }
  1469. return mResponseHead->VisitHeaders(visitor,
  1470. nsHttpHeaderArray::eFilterResponse);
  1471. }
  1472. NS_IMETHODIMP
  1473. HttpBaseChannel::GetOriginalResponseHeader(const nsACString& aHeader,
  1474. nsIHttpHeaderVisitor *aVisitor)
  1475. {
  1476. if (!mResponseHead) {
  1477. return NS_ERROR_NOT_AVAILABLE;
  1478. }
  1479. nsHttpAtom atom = nsHttp::ResolveAtom(aHeader);
  1480. if (!atom) {
  1481. return NS_ERROR_NOT_AVAILABLE;
  1482. }
  1483. return mResponseHead->GetOriginalHeader(atom, aVisitor);
  1484. }
  1485. NS_IMETHODIMP
  1486. HttpBaseChannel::VisitOriginalResponseHeaders(nsIHttpHeaderVisitor *aVisitor)
  1487. {
  1488. if (!mResponseHead) {
  1489. return NS_ERROR_NOT_AVAILABLE;
  1490. }
  1491. return mResponseHead->VisitHeaders(aVisitor,
  1492. nsHttpHeaderArray::eFilterResponseOriginal);
  1493. }
  1494. NS_IMETHODIMP
  1495. HttpBaseChannel::GetAllowPipelining(bool *value)
  1496. {
  1497. NS_ENSURE_ARG_POINTER(value);
  1498. *value = mAllowPipelining;
  1499. return NS_OK;
  1500. }
  1501. NS_IMETHODIMP
  1502. HttpBaseChannel::SetAllowPipelining(bool value)
  1503. {
  1504. ENSURE_CALLED_BEFORE_CONNECT();
  1505. mAllowPipelining = value;
  1506. return NS_OK;
  1507. }
  1508. NS_IMETHODIMP
  1509. HttpBaseChannel::GetAllowSTS(bool *value)
  1510. {
  1511. NS_ENSURE_ARG_POINTER(value);
  1512. *value = mAllowSTS;
  1513. return NS_OK;
  1514. }
  1515. NS_IMETHODIMP
  1516. HttpBaseChannel::SetAllowSTS(bool value)
  1517. {
  1518. ENSURE_CALLED_BEFORE_CONNECT();
  1519. mAllowSTS = value;
  1520. return NS_OK;
  1521. }
  1522. NS_IMETHODIMP
  1523. HttpBaseChannel::GetRedirectionLimit(uint32_t *value)
  1524. {
  1525. NS_ENSURE_ARG_POINTER(value);
  1526. *value = mRedirectionLimit;
  1527. return NS_OK;
  1528. }
  1529. NS_IMETHODIMP
  1530. HttpBaseChannel::SetRedirectionLimit(uint32_t value)
  1531. {
  1532. ENSURE_CALLED_BEFORE_CONNECT();
  1533. mRedirectionLimit = std::min<uint32_t>(value, 0xff);
  1534. return NS_OK;
  1535. }
  1536. nsresult
  1537. HttpBaseChannel::OverrideSecurityInfo(nsISupports* aSecurityInfo)
  1538. {
  1539. MOZ_ASSERT(!mSecurityInfo,
  1540. "This can only be called when we don't have a security info object already");
  1541. MOZ_RELEASE_ASSERT(aSecurityInfo,
  1542. "This can only be called with a valid security info object");
  1543. MOZ_ASSERT(!BypassServiceWorker(),
  1544. "This can only be called on channels that are not bypassing interception");
  1545. MOZ_ASSERT(mResponseCouldBeSynthesized,
  1546. "This can only be called on channels that can be intercepted");
  1547. if (mSecurityInfo) {
  1548. LOG(("HttpBaseChannel::OverrideSecurityInfo mSecurityInfo is null! "
  1549. "[this=%p]\n", this));
  1550. return NS_ERROR_UNEXPECTED;
  1551. }
  1552. if (!mResponseCouldBeSynthesized) {
  1553. LOG(("HttpBaseChannel::OverrideSecurityInfo channel cannot be intercepted! "
  1554. "[this=%p]\n", this));
  1555. return NS_ERROR_UNEXPECTED;
  1556. }
  1557. mSecurityInfo = aSecurityInfo;
  1558. return NS_OK;
  1559. }
  1560. NS_IMETHODIMP
  1561. HttpBaseChannel::IsNoStoreResponse(bool *value)
  1562. {
  1563. if (!mResponseHead)
  1564. return NS_ERROR_NOT_AVAILABLE;
  1565. *value = mResponseHead->NoStore();
  1566. return NS_OK;
  1567. }
  1568. NS_IMETHODIMP
  1569. HttpBaseChannel::IsNoCacheResponse(bool *value)
  1570. {
  1571. if (!mResponseHead)
  1572. return NS_ERROR_NOT_AVAILABLE;
  1573. *value = mResponseHead->NoCache();
  1574. if (!*value)
  1575. *value = mResponseHead->ExpiresInPast();
  1576. return NS_OK;
  1577. }
  1578. NS_IMETHODIMP
  1579. HttpBaseChannel::IsPrivateResponse(bool *value)
  1580. {
  1581. if (!mResponseHead)
  1582. return NS_ERROR_NOT_AVAILABLE;
  1583. *value = mResponseHead->Private();
  1584. return NS_OK;
  1585. }
  1586. NS_IMETHODIMP
  1587. HttpBaseChannel::GetResponseStatus(uint32_t *aValue)
  1588. {
  1589. if (!mResponseHead)
  1590. return NS_ERROR_NOT_AVAILABLE;
  1591. *aValue = mResponseHead->Status();
  1592. return NS_OK;
  1593. }
  1594. NS_IMETHODIMP
  1595. HttpBaseChannel::GetResponseStatusText(nsACString& aValue)
  1596. {
  1597. if (!mResponseHead)
  1598. return NS_ERROR_NOT_AVAILABLE;
  1599. mResponseHead->StatusText(aValue);
  1600. return NS_OK;
  1601. }
  1602. NS_IMETHODIMP
  1603. HttpBaseChannel::GetRequestSucceeded(bool *aValue)
  1604. {
  1605. if (!mResponseHead)
  1606. return NS_ERROR_NOT_AVAILABLE;
  1607. uint32_t status = mResponseHead->Status();
  1608. *aValue = (status / 100 == 2);
  1609. return NS_OK;
  1610. }
  1611. NS_IMETHODIMP
  1612. HttpBaseChannel::RedirectTo(nsIURI *targetURI)
  1613. {
  1614. // We cannot redirect after OnStartRequest of the listener
  1615. // has been called, since to redirect we have to switch channels
  1616. // and the dance with OnStartRequest et al has to start over.
  1617. // This would break the nsIStreamListener contract.
  1618. NS_ENSURE_FALSE(mOnStartRequestCalled, NS_ERROR_NOT_AVAILABLE);
  1619. mAPIRedirectToURI = targetURI;
  1620. return NS_OK;
  1621. }
  1622. NS_IMETHODIMP
  1623. HttpBaseChannel::GetRequestContextID(nsID *aRCID)
  1624. {
  1625. NS_ENSURE_ARG_POINTER(aRCID);
  1626. *aRCID = mRequestContextID;
  1627. return NS_OK;
  1628. }
  1629. NS_IMETHODIMP
  1630. HttpBaseChannel::SetRequestContextID(const nsID aRCID)
  1631. {
  1632. mRequestContextID = aRCID;
  1633. return NS_OK;
  1634. }
  1635. NS_IMETHODIMP
  1636. HttpBaseChannel::GetIsMainDocumentChannel(bool* aValue)
  1637. {
  1638. NS_ENSURE_ARG_POINTER(aValue);
  1639. *aValue = mForceMainDocumentChannel || (mLoadFlags & LOAD_DOCUMENT_URI);
  1640. return NS_OK;
  1641. }
  1642. NS_IMETHODIMP
  1643. HttpBaseChannel::SetIsMainDocumentChannel(bool aValue)
  1644. {
  1645. mForceMainDocumentChannel = aValue;
  1646. return NS_OK;
  1647. }
  1648. NS_IMETHODIMP
  1649. HttpBaseChannel::GetProtocolVersion(nsACString& aProtocolVersion)
  1650. {
  1651. nsresult rv;
  1652. nsCOMPtr<nsISSLSocketControl> ssl = do_QueryInterface(mSecurityInfo, &rv);
  1653. nsAutoCString protocol;
  1654. if (NS_SUCCEEDED(rv) && ssl &&
  1655. NS_SUCCEEDED(ssl->GetNegotiatedNPN(protocol)) &&
  1656. !protocol.IsEmpty()) {
  1657. // The negotiated protocol was not empty so we can use it.
  1658. aProtocolVersion = protocol;
  1659. return NS_OK;
  1660. }
  1661. if (mResponseHead) {
  1662. uint32_t version = mResponseHead->Version();
  1663. aProtocolVersion.Assign(nsHttp::GetProtocolVersion(version));
  1664. return NS_OK;
  1665. }
  1666. return NS_ERROR_NOT_AVAILABLE;
  1667. }
  1668. //-----------------------------------------------------------------------------
  1669. // HttpBaseChannel::nsIHttpChannelInternal
  1670. //-----------------------------------------------------------------------------
  1671. NS_IMETHODIMP
  1672. HttpBaseChannel::GetTopWindowURI(nsIURI **aTopWindowURI)
  1673. {
  1674. nsresult rv = NS_OK;
  1675. nsCOMPtr<mozIThirdPartyUtil> util;
  1676. // Only compute the top window URI once. In e10s, this must be computed in the
  1677. // child. The parent gets the top window URI through HttpChannelOpenArgs.
  1678. if (!mTopWindowURI) {
  1679. util = do_GetService(THIRDPARTYUTIL_CONTRACTID);
  1680. if (!util) {
  1681. return NS_ERROR_NOT_AVAILABLE;
  1682. }
  1683. nsCOMPtr<mozIDOMWindowProxy> win;
  1684. rv = util->GetTopWindowForChannel(this, getter_AddRefs(win));
  1685. if (NS_SUCCEEDED(rv)) {
  1686. rv = util->GetURIFromWindow(win, getter_AddRefs(mTopWindowURI));
  1687. #if DEBUG
  1688. if (mTopWindowURI) {
  1689. nsCString spec;
  1690. if (NS_SUCCEEDED(mTopWindowURI->GetSpec(spec))) {
  1691. LOG(("HttpChannelBase::Setting topwindow URI spec %s [this=%p]\n",
  1692. spec.get(), this));
  1693. }
  1694. }
  1695. #endif
  1696. }
  1697. }
  1698. NS_IF_ADDREF(*aTopWindowURI = mTopWindowURI);
  1699. return rv;
  1700. }
  1701. NS_IMETHODIMP
  1702. HttpBaseChannel::GetDocumentURI(nsIURI **aDocumentURI)
  1703. {
  1704. NS_ENSURE_ARG_POINTER(aDocumentURI);
  1705. *aDocumentURI = mDocumentURI;
  1706. NS_IF_ADDREF(*aDocumentURI);
  1707. return NS_OK;
  1708. }
  1709. NS_IMETHODIMP
  1710. HttpBaseChannel::SetDocumentURI(nsIURI *aDocumentURI)
  1711. {
  1712. ENSURE_CALLED_BEFORE_CONNECT();
  1713. mDocumentURI = aDocumentURI;
  1714. return NS_OK;
  1715. }
  1716. NS_IMETHODIMP
  1717. HttpBaseChannel::GetRequestVersion(uint32_t *major, uint32_t *minor)
  1718. {
  1719. nsHttpVersion version = mRequestHead.Version();
  1720. if (major) { *major = version / 10; }
  1721. if (minor) { *minor = version % 10; }
  1722. return NS_OK;
  1723. }
  1724. NS_IMETHODIMP
  1725. HttpBaseChannel::GetResponseVersion(uint32_t *major, uint32_t *minor)
  1726. {
  1727. if (!mResponseHead)
  1728. {
  1729. *major = *minor = 0; // we should at least be kind about it
  1730. return NS_ERROR_NOT_AVAILABLE;
  1731. }
  1732. nsHttpVersion version = mResponseHead->Version();
  1733. if (major) { *major = version / 10; }
  1734. if (minor) { *minor = version % 10; }
  1735. return NS_OK;
  1736. }
  1737. void
  1738. HttpBaseChannel::NotifySetCookie(char const *aCookie)
  1739. {
  1740. nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
  1741. if (obs) {
  1742. nsAutoString cookie;
  1743. CopyASCIItoUTF16(aCookie, cookie);
  1744. obs->NotifyObservers(static_cast<nsIChannel*>(this),
  1745. "http-on-response-set-cookie",
  1746. cookie.get());
  1747. }
  1748. }
  1749. NS_IMETHODIMP
  1750. HttpBaseChannel::SetCookie(const char *aCookieHeader)
  1751. {
  1752. if (mLoadFlags & LOAD_ANONYMOUS)
  1753. return NS_OK;
  1754. // empty header isn't an error
  1755. if (!(aCookieHeader && *aCookieHeader))
  1756. return NS_OK;
  1757. nsICookieService *cs = gHttpHandler->GetCookieService();
  1758. NS_ENSURE_TRUE(cs, NS_ERROR_FAILURE);
  1759. nsAutoCString date;
  1760. mResponseHead->GetHeader(nsHttp::Date, date);
  1761. nsresult rv =
  1762. cs->SetCookieStringFromHttp(mURI, nullptr, nullptr, aCookieHeader,
  1763. date.get(), this);
  1764. if (NS_SUCCEEDED(rv)) {
  1765. NotifySetCookie(aCookieHeader);
  1766. }
  1767. return rv;
  1768. }
  1769. NS_IMETHODIMP
  1770. HttpBaseChannel::GetThirdPartyFlags(uint32_t *aFlags)
  1771. {
  1772. *aFlags = mThirdPartyFlags;
  1773. return NS_OK;
  1774. }
  1775. NS_IMETHODIMP
  1776. HttpBaseChannel::SetThirdPartyFlags(uint32_t aFlags)
  1777. {
  1778. ENSURE_CALLED_BEFORE_ASYNC_OPEN();
  1779. mThirdPartyFlags = aFlags;
  1780. return NS_OK;
  1781. }
  1782. NS_IMETHODIMP
  1783. HttpBaseChannel::GetForceAllowThirdPartyCookie(bool *aForce)
  1784. {
  1785. *aForce = !!(mThirdPartyFlags & nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW);
  1786. return NS_OK;
  1787. }
  1788. NS_IMETHODIMP
  1789. HttpBaseChannel::SetForceAllowThirdPartyCookie(bool aForce)
  1790. {
  1791. ENSURE_CALLED_BEFORE_ASYNC_OPEN();
  1792. if (aForce)
  1793. mThirdPartyFlags |= nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW;
  1794. else
  1795. mThirdPartyFlags &= ~nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW;
  1796. return NS_OK;
  1797. }
  1798. NS_IMETHODIMP
  1799. HttpBaseChannel::GetCanceled(bool *aCanceled)
  1800. {
  1801. *aCanceled = mCanceled;
  1802. return NS_OK;
  1803. }
  1804. NS_IMETHODIMP
  1805. HttpBaseChannel::GetChannelIsForDownload(bool *aChannelIsForDownload)
  1806. {
  1807. *aChannelIsForDownload = mChannelIsForDownload;
  1808. return NS_OK;
  1809. }
  1810. NS_IMETHODIMP
  1811. HttpBaseChannel::SetChannelIsForDownload(bool aChannelIsForDownload)
  1812. {
  1813. mChannelIsForDownload = aChannelIsForDownload;
  1814. return NS_OK;
  1815. }
  1816. NS_IMETHODIMP
  1817. HttpBaseChannel::SetCacheKeysRedirectChain(nsTArray<nsCString> *cacheKeys)
  1818. {
  1819. mRedirectedCachekeys = cacheKeys;
  1820. return NS_OK;
  1821. }
  1822. NS_IMETHODIMP
  1823. HttpBaseChannel::GetLocalAddress(nsACString& addr)
  1824. {
  1825. if (mSelfAddr.raw.family == PR_AF_UNSPEC)
  1826. return NS_ERROR_NOT_AVAILABLE;
  1827. addr.SetCapacity(kIPv6CStrBufSize);
  1828. NetAddrToString(&mSelfAddr, addr.BeginWriting(), kIPv6CStrBufSize);
  1829. addr.SetLength(strlen(addr.BeginReading()));
  1830. return NS_OK;
  1831. }
  1832. NS_IMETHODIMP
  1833. HttpBaseChannel::TakeAllSecurityMessages(
  1834. nsCOMArray<nsISecurityConsoleMessage> &aMessages)
  1835. {
  1836. aMessages.Clear();
  1837. aMessages.SwapElements(mSecurityConsoleMessages);
  1838. return NS_OK;
  1839. }
  1840. /* Please use this method with care. This can cause the message
  1841. * queue to grow large and cause the channel to take up a lot
  1842. * of memory. Use only static string messages and do not add
  1843. * server side data to the queue, as that can be large.
  1844. * Add only a limited number of messages to the queue to keep
  1845. * the channel size down and do so only in rare erroneous situations.
  1846. * More information can be found here:
  1847. * https://bugzilla.mozilla.org/show_bug.cgi?id=846918
  1848. */
  1849. nsresult
  1850. HttpBaseChannel::AddSecurityMessage(const nsAString &aMessageTag,
  1851. const nsAString &aMessageCategory)
  1852. {
  1853. nsresult rv;
  1854. nsCOMPtr<nsISecurityConsoleMessage> message =
  1855. do_CreateInstance(NS_SECURITY_CONSOLE_MESSAGE_CONTRACTID, &rv);
  1856. NS_ENSURE_SUCCESS(rv, rv);
  1857. message->SetTag(aMessageTag);
  1858. message->SetCategory(aMessageCategory);
  1859. mSecurityConsoleMessages.AppendElement(message);
  1860. nsCOMPtr<nsIConsoleService> console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
  1861. if (!console) {
  1862. return NS_ERROR_FAILURE;
  1863. }
  1864. nsCOMPtr<nsILoadInfo> loadInfo;
  1865. GetLoadInfo(getter_AddRefs(loadInfo));
  1866. if (!loadInfo) {
  1867. return NS_ERROR_FAILURE;
  1868. }
  1869. uint32_t innerWindowID = loadInfo->GetInnerWindowID();
  1870. nsXPIDLString errorText;
  1871. rv = nsContentUtils::GetLocalizedString(
  1872. nsContentUtils::eSECURITY_PROPERTIES,
  1873. NS_ConvertUTF16toUTF8(aMessageTag).get(),
  1874. errorText);
  1875. NS_ENSURE_SUCCESS(rv, rv);
  1876. nsAutoCString spec;
  1877. if (mURI) {
  1878. spec = mURI->GetSpecOrDefault();
  1879. }
  1880. nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
  1881. error->InitWithWindowID(errorText, NS_ConvertUTF8toUTF16(spec),
  1882. EmptyString(), 0, 0, nsIScriptError::warningFlag,
  1883. NS_ConvertUTF16toUTF8(aMessageCategory),
  1884. innerWindowID);
  1885. console->LogMessage(error);
  1886. return NS_OK;
  1887. }
  1888. NS_IMETHODIMP
  1889. HttpBaseChannel::GetLocalPort(int32_t* port)
  1890. {
  1891. NS_ENSURE_ARG_POINTER(port);
  1892. if (mSelfAddr.raw.family == PR_AF_INET) {
  1893. *port = (int32_t)ntohs(mSelfAddr.inet.port);
  1894. }
  1895. else if (mSelfAddr.raw.family == PR_AF_INET6) {
  1896. *port = (int32_t)ntohs(mSelfAddr.inet6.port);
  1897. }
  1898. else
  1899. return NS_ERROR_NOT_AVAILABLE;
  1900. return NS_OK;
  1901. }
  1902. NS_IMETHODIMP
  1903. HttpBaseChannel::GetRemoteAddress(nsACString& addr)
  1904. {
  1905. if (mPeerAddr.raw.family == PR_AF_UNSPEC)
  1906. return NS_ERROR_NOT_AVAILABLE;
  1907. addr.SetCapacity(kIPv6CStrBufSize);
  1908. NetAddrToString(&mPeerAddr, addr.BeginWriting(), kIPv6CStrBufSize);
  1909. addr.SetLength(strlen(addr.BeginReading()));
  1910. return NS_OK;
  1911. }
  1912. NS_IMETHODIMP
  1913. HttpBaseChannel::GetRemotePort(int32_t* port)
  1914. {
  1915. NS_ENSURE_ARG_POINTER(port);
  1916. if (mPeerAddr.raw.family == PR_AF_INET) {
  1917. *port = (int32_t)ntohs(mPeerAddr.inet.port);
  1918. }
  1919. else if (mPeerAddr.raw.family == PR_AF_INET6) {
  1920. *port = (int32_t)ntohs(mPeerAddr.inet6.port);
  1921. }
  1922. else
  1923. return NS_ERROR_NOT_AVAILABLE;
  1924. return NS_OK;
  1925. }
  1926. NS_IMETHODIMP
  1927. HttpBaseChannel::HTTPUpgrade(const nsACString &aProtocolName,
  1928. nsIHttpUpgradeListener *aListener)
  1929. {
  1930. NS_ENSURE_ARG(!aProtocolName.IsEmpty());
  1931. NS_ENSURE_ARG_POINTER(aListener);
  1932. mUpgradeProtocol = aProtocolName;
  1933. mUpgradeProtocolCallback = aListener;
  1934. return NS_OK;
  1935. }
  1936. NS_IMETHODIMP
  1937. HttpBaseChannel::GetAllowSpdy(bool *aAllowSpdy)
  1938. {
  1939. NS_ENSURE_ARG_POINTER(aAllowSpdy);
  1940. *aAllowSpdy = mAllowSpdy;
  1941. return NS_OK;
  1942. }
  1943. NS_IMETHODIMP
  1944. HttpBaseChannel::SetAllowSpdy(bool aAllowSpdy)
  1945. {
  1946. mAllowSpdy = aAllowSpdy;
  1947. return NS_OK;
  1948. }
  1949. NS_IMETHODIMP
  1950. HttpBaseChannel::GetAllowAltSvc(bool *aAllowAltSvc)
  1951. {
  1952. NS_ENSURE_ARG_POINTER(aAllowAltSvc);
  1953. *aAllowAltSvc = mAllowAltSvc;
  1954. return NS_OK;
  1955. }
  1956. NS_IMETHODIMP
  1957. HttpBaseChannel::SetAllowAltSvc(bool aAllowAltSvc)
  1958. {
  1959. mAllowAltSvc = aAllowAltSvc;
  1960. return NS_OK;
  1961. }
  1962. NS_IMETHODIMP
  1963. HttpBaseChannel::GetBeConservative(bool *aBeConservative)
  1964. {
  1965. NS_ENSURE_ARG_POINTER(aBeConservative);
  1966. *aBeConservative = mBeConservative;
  1967. return NS_OK;
  1968. }
  1969. NS_IMETHODIMP
  1970. HttpBaseChannel::SetBeConservative(bool aBeConservative)
  1971. {
  1972. mBeConservative = aBeConservative;
  1973. return NS_OK;
  1974. }
  1975. NS_IMETHODIMP
  1976. HttpBaseChannel::GetApiRedirectToURI(nsIURI ** aResult)
  1977. {
  1978. NS_ENSURE_ARG_POINTER(aResult);
  1979. NS_IF_ADDREF(*aResult = mAPIRedirectToURI);
  1980. return NS_OK;
  1981. }
  1982. NS_IMETHODIMP
  1983. HttpBaseChannel::GetResponseTimeoutEnabled(bool *aEnable)
  1984. {
  1985. if (NS_WARN_IF(!aEnable)) {
  1986. return NS_ERROR_NULL_POINTER;
  1987. }
  1988. *aEnable = mResponseTimeoutEnabled;
  1989. return NS_OK;
  1990. }
  1991. NS_IMETHODIMP
  1992. HttpBaseChannel::SetResponseTimeoutEnabled(bool aEnable)
  1993. {
  1994. mResponseTimeoutEnabled = aEnable;
  1995. return NS_OK;
  1996. }
  1997. NS_IMETHODIMP
  1998. HttpBaseChannel::GetInitialRwin(uint32_t *aRwin)
  1999. {
  2000. if (NS_WARN_IF(!aRwin)) {
  2001. return NS_ERROR_NULL_POINTER;
  2002. }
  2003. *aRwin = mInitialRwin;
  2004. return NS_OK;
  2005. }
  2006. NS_IMETHODIMP
  2007. HttpBaseChannel::SetInitialRwin(uint32_t aRwin)
  2008. {
  2009. ENSURE_CALLED_BEFORE_CONNECT();
  2010. mInitialRwin = aRwin;
  2011. return NS_OK;
  2012. }
  2013. NS_IMETHODIMP
  2014. HttpBaseChannel::ForcePending(bool aForcePending)
  2015. {
  2016. mForcePending = aForcePending;
  2017. return NS_OK;
  2018. }
  2019. NS_IMETHODIMP
  2020. HttpBaseChannel::GetLastModifiedTime(PRTime* lastModifiedTime)
  2021. {
  2022. if (!mResponseHead)
  2023. return NS_ERROR_NOT_AVAILABLE;
  2024. uint32_t lastMod;
  2025. mResponseHead->GetLastModifiedValue(&lastMod);
  2026. *lastModifiedTime = lastMod;
  2027. return NS_OK;
  2028. }
  2029. NS_IMETHODIMP
  2030. HttpBaseChannel::GetCorsIncludeCredentials(bool* aInclude)
  2031. {
  2032. *aInclude = mCorsIncludeCredentials;
  2033. return NS_OK;
  2034. }
  2035. NS_IMETHODIMP
  2036. HttpBaseChannel::SetCorsIncludeCredentials(bool aInclude)
  2037. {
  2038. mCorsIncludeCredentials = aInclude;
  2039. return NS_OK;
  2040. }
  2041. NS_IMETHODIMP
  2042. HttpBaseChannel::GetCorsMode(uint32_t* aMode)
  2043. {
  2044. *aMode = mCorsMode;
  2045. return NS_OK;
  2046. }
  2047. NS_IMETHODIMP
  2048. HttpBaseChannel::SetCorsMode(uint32_t aMode)
  2049. {
  2050. mCorsMode = aMode;
  2051. return NS_OK;
  2052. }
  2053. NS_IMETHODIMP
  2054. HttpBaseChannel::GetRedirectMode(uint32_t* aMode)
  2055. {
  2056. *aMode = mRedirectMode;
  2057. return NS_OK;
  2058. }
  2059. NS_IMETHODIMP
  2060. HttpBaseChannel::SetRedirectMode(uint32_t aMode)
  2061. {
  2062. mRedirectMode = aMode;
  2063. return NS_OK;
  2064. }
  2065. NS_IMETHODIMP
  2066. HttpBaseChannel::GetFetchCacheMode(uint32_t* aFetchCacheMode)
  2067. {
  2068. NS_ENSURE_ARG_POINTER(aFetchCacheMode);
  2069. // If the fetch cache mode is overriden, then use it directly.
  2070. if (mFetchCacheMode != nsIHttpChannelInternal::FETCH_CACHE_MODE_DEFAULT) {
  2071. *aFetchCacheMode = mFetchCacheMode;
  2072. return NS_OK;
  2073. }
  2074. // Otherwise try to guess an appropriate cache mode from the load flags.
  2075. if (mLoadFlags & (INHIBIT_CACHING | LOAD_BYPASS_CACHE)) {
  2076. *aFetchCacheMode = nsIHttpChannelInternal::FETCH_CACHE_MODE_NO_STORE;
  2077. } else if (mLoadFlags & LOAD_BYPASS_CACHE) {
  2078. *aFetchCacheMode = nsIHttpChannelInternal::FETCH_CACHE_MODE_RELOAD;
  2079. } else if (mLoadFlags & VALIDATE_ALWAYS) {
  2080. *aFetchCacheMode = nsIHttpChannelInternal::FETCH_CACHE_MODE_NO_CACHE;
  2081. } else if (mLoadFlags & (VALIDATE_NEVER | nsICachingChannel::LOAD_ONLY_FROM_CACHE)) {
  2082. *aFetchCacheMode = nsIHttpChannelInternal::FETCH_CACHE_MODE_ONLY_IF_CACHED;
  2083. } else if (mLoadFlags & VALIDATE_NEVER) {
  2084. *aFetchCacheMode = nsIHttpChannelInternal::FETCH_CACHE_MODE_FORCE_CACHE;
  2085. } else {
  2086. *aFetchCacheMode = nsIHttpChannelInternal::FETCH_CACHE_MODE_DEFAULT;
  2087. }
  2088. return NS_OK;
  2089. }
  2090. NS_IMETHODIMP
  2091. HttpBaseChannel::SetFetchCacheMode(uint32_t aFetchCacheMode)
  2092. {
  2093. ENSURE_CALLED_BEFORE_CONNECT();
  2094. MOZ_ASSERT(mFetchCacheMode == nsIHttpChannelInternal::FETCH_CACHE_MODE_DEFAULT,
  2095. "SetFetchCacheMode() should only be called once per channel");
  2096. mFetchCacheMode = aFetchCacheMode;
  2097. // Now, set the load flags that implement each cache mode.
  2098. switch (mFetchCacheMode) {
  2099. case nsIHttpChannelInternal::FETCH_CACHE_MODE_NO_STORE:
  2100. // no-store means don't consult the cache on the way to the network, and
  2101. // don't store the response in the cache even if it's cacheable.
  2102. mLoadFlags |= INHIBIT_CACHING | LOAD_BYPASS_CACHE;
  2103. break;
  2104. case nsIHttpChannelInternal::FETCH_CACHE_MODE_RELOAD:
  2105. // reload means don't consult the cache on the way to the network, but
  2106. // do store the response in the cache if possible.
  2107. mLoadFlags |= LOAD_BYPASS_CACHE;
  2108. break;
  2109. case nsIHttpChannelInternal::FETCH_CACHE_MODE_NO_CACHE:
  2110. // no-cache means always validate what's in the cache.
  2111. mLoadFlags |= VALIDATE_ALWAYS;
  2112. break;
  2113. case nsIHttpChannelInternal::FETCH_CACHE_MODE_FORCE_CACHE:
  2114. // force-cache means don't validate unless if the response would vary.
  2115. mLoadFlags |= VALIDATE_NEVER;
  2116. break;
  2117. case nsIHttpChannelInternal::FETCH_CACHE_MODE_ONLY_IF_CACHED:
  2118. // only-if-cached means only from cache, no network, no validation, generate
  2119. // a network error if the document was't in the cache.
  2120. // The privacy implications of these flags (making it fast/easy to check if
  2121. // the user has things in their cache without any network traffic side
  2122. // effects) are addressed in the Request constructor which enforces/requires
  2123. // same-origin request mode.
  2124. mLoadFlags |= VALIDATE_NEVER | nsICachingChannel::LOAD_ONLY_FROM_CACHE;
  2125. break;
  2126. }
  2127. return NS_OK;
  2128. }
  2129. NS_IMETHODIMP
  2130. HttpBaseChannel::SetIntegrityMetadata(const nsAString& aIntegrityMetadata)
  2131. {
  2132. mIntegrityMetadata = aIntegrityMetadata;
  2133. return NS_OK;
  2134. }
  2135. NS_IMETHODIMP
  2136. HttpBaseChannel::GetIntegrityMetadata(nsAString& aIntegrityMetadata)
  2137. {
  2138. aIntegrityMetadata = mIntegrityMetadata;
  2139. return NS_OK;
  2140. }
  2141. mozilla::net::nsHttpChannel*
  2142. HttpBaseChannel::QueryHttpChannelImpl(void)
  2143. {
  2144. return nullptr;
  2145. }
  2146. //-----------------------------------------------------------------------------
  2147. // HttpBaseChannel::nsISupportsPriority
  2148. //-----------------------------------------------------------------------------
  2149. NS_IMETHODIMP
  2150. HttpBaseChannel::GetPriority(int32_t *value)
  2151. {
  2152. *value = mPriority;
  2153. return NS_OK;
  2154. }
  2155. NS_IMETHODIMP
  2156. HttpBaseChannel::AdjustPriority(int32_t delta)
  2157. {
  2158. return SetPriority(mPriority + delta);
  2159. }
  2160. //-----------------------------------------------------------------------------
  2161. // HttpBaseChannel::nsIResumableChannel
  2162. //-----------------------------------------------------------------------------
  2163. NS_IMETHODIMP
  2164. HttpBaseChannel::GetEntityID(nsACString& aEntityID)
  2165. {
  2166. // Don't return an entity ID for Non-GET requests which require
  2167. // additional data
  2168. if (!mRequestHead.IsGet()) {
  2169. return NS_ERROR_NOT_RESUMABLE;
  2170. }
  2171. uint64_t size = UINT64_MAX;
  2172. nsAutoCString etag, lastmod;
  2173. if (mResponseHead) {
  2174. // Don't return an entity if the server sent the following header:
  2175. // Accept-Ranges: none
  2176. // Not sending the Accept-Ranges header means we can still try
  2177. // sending range requests.
  2178. nsAutoCString acceptRanges;
  2179. mResponseHead->GetHeader(nsHttp::Accept_Ranges, acceptRanges);
  2180. if (!acceptRanges.IsEmpty() &&
  2181. !nsHttp::FindToken(acceptRanges.get(), "bytes", HTTP_HEADER_VALUE_SEPS)) {
  2182. return NS_ERROR_NOT_RESUMABLE;
  2183. }
  2184. size = mResponseHead->TotalEntitySize();
  2185. mResponseHead->GetHeader(nsHttp::Last_Modified, lastmod);
  2186. mResponseHead->GetHeader(nsHttp::ETag, etag);
  2187. }
  2188. nsCString entityID;
  2189. NS_EscapeURL(etag.BeginReading(), etag.Length(), esc_AlwaysCopy |
  2190. esc_FileBaseName | esc_Forced, entityID);
  2191. entityID.Append('/');
  2192. entityID.AppendInt(int64_t(size));
  2193. entityID.Append('/');
  2194. entityID.Append(lastmod);
  2195. // NOTE: Appending lastmod as the last part avoids having to escape it
  2196. aEntityID = entityID;
  2197. return NS_OK;
  2198. }
  2199. //-----------------------------------------------------------------------------
  2200. // HttpBaseChannel::nsIConsoleReportCollector
  2201. //-----------------------------------------------------------------------------
  2202. void
  2203. HttpBaseChannel::AddConsoleReport(uint32_t aErrorFlags,
  2204. const nsACString& aCategory,
  2205. nsContentUtils::PropertiesFile aPropertiesFile,
  2206. const nsACString& aSourceFileURI,
  2207. uint32_t aLineNumber, uint32_t aColumnNumber,
  2208. const nsACString& aMessageName,
  2209. const nsTArray<nsString>& aStringParams)
  2210. {
  2211. mReportCollector->AddConsoleReport(aErrorFlags, aCategory, aPropertiesFile,
  2212. aSourceFileURI, aLineNumber,
  2213. aColumnNumber, aMessageName,
  2214. aStringParams);
  2215. }
  2216. void
  2217. HttpBaseChannel::FlushConsoleReports(nsIDocument* aDocument,
  2218. ReportAction aAction)
  2219. {
  2220. mReportCollector->FlushConsoleReports(aDocument, aAction);
  2221. }
  2222. void
  2223. HttpBaseChannel::FlushConsoleReports(nsIConsoleReportCollector* aCollector)
  2224. {
  2225. mReportCollector->FlushConsoleReports(aCollector);
  2226. }
  2227. void
  2228. HttpBaseChannel::FlushReportsByWindowId(uint64_t aWindowId,
  2229. ReportAction aAction)
  2230. {
  2231. mReportCollector->FlushReportsByWindowId(aWindowId, aAction);
  2232. }
  2233. void
  2234. HttpBaseChannel::ClearConsoleReports()
  2235. {
  2236. mReportCollector->ClearConsoleReports();
  2237. }
  2238. nsIPrincipal *
  2239. HttpBaseChannel::GetURIPrincipal()
  2240. {
  2241. if (mPrincipal) {
  2242. return mPrincipal;
  2243. }
  2244. nsIScriptSecurityManager *securityManager =
  2245. nsContentUtils::GetSecurityManager();
  2246. if (!securityManager) {
  2247. LOG(("HttpBaseChannel::GetURIPrincipal: No security manager [this=%p]",
  2248. this));
  2249. return nullptr;
  2250. }
  2251. securityManager->GetChannelURIPrincipal(this, getter_AddRefs(mPrincipal));
  2252. if (!mPrincipal) {
  2253. LOG(("HttpBaseChannel::GetURIPrincipal: No channel principal [this=%p]",
  2254. this));
  2255. return nullptr;
  2256. }
  2257. return mPrincipal;
  2258. }
  2259. bool
  2260. HttpBaseChannel::IsNavigation()
  2261. {
  2262. return mForceMainDocumentChannel;
  2263. }
  2264. bool
  2265. HttpBaseChannel::BypassServiceWorker() const
  2266. {
  2267. return mLoadFlags & LOAD_BYPASS_SERVICE_WORKER;
  2268. }
  2269. bool
  2270. HttpBaseChannel::ShouldIntercept(nsIURI* aURI)
  2271. {
  2272. nsCOMPtr<nsINetworkInterceptController> controller;
  2273. GetCallback(controller);
  2274. bool shouldIntercept = false;
  2275. if (controller && !BypassServiceWorker() && mLoadInfo) {
  2276. nsresult rv = controller->ShouldPrepareForIntercept(aURI ? aURI : mURI.get(),
  2277. nsContentUtils::IsNonSubresourceRequest(this),
  2278. &shouldIntercept);
  2279. if (NS_FAILED(rv)) {
  2280. return false;
  2281. }
  2282. }
  2283. return shouldIntercept;
  2284. }
  2285. #ifdef DEBUG
  2286. void HttpBaseChannel::AssertPrivateBrowsingId()
  2287. {
  2288. nsCOMPtr<nsILoadContext> loadContext;
  2289. NS_QueryNotificationCallbacks(this, loadContext);
  2290. // For addons it's possible that mLoadInfo is null.
  2291. if (!mLoadInfo) {
  2292. return;
  2293. }
  2294. if (!loadContext) {
  2295. return;
  2296. }
  2297. // We skip testing of favicon loading here since it could be triggered by XUL image
  2298. // which uses SystemPrincipal. The SystemPrincpal doesn't have mPrivateBrowsingId.
  2299. if (nsContentUtils::IsSystemPrincipal(mLoadInfo->LoadingPrincipal()) &&
  2300. mLoadInfo->InternalContentPolicyType() == nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON) {
  2301. return;
  2302. }
  2303. DocShellOriginAttributes docShellAttrs;
  2304. loadContext->GetOriginAttributes(docShellAttrs);
  2305. MOZ_ASSERT(mLoadInfo->GetOriginAttributes().mPrivateBrowsingId == docShellAttrs.mPrivateBrowsingId,
  2306. "PrivateBrowsingId values are not the same between LoadInfo and LoadContext.");
  2307. }
  2308. #endif
  2309. //-----------------------------------------------------------------------------
  2310. // nsHttpChannel::nsITraceableChannel
  2311. //-----------------------------------------------------------------------------
  2312. NS_IMETHODIMP
  2313. HttpBaseChannel::SetNewListener(nsIStreamListener *aListener, nsIStreamListener **_retval)
  2314. {
  2315. LOG(("HttpBaseChannel::SetNewListener [this=%p, mListener=%p, newListener=%p]",
  2316. this, mListener.get(), aListener));
  2317. if (!mTracingEnabled)
  2318. return NS_ERROR_FAILURE;
  2319. NS_ENSURE_STATE(mListener);
  2320. NS_ENSURE_ARG_POINTER(aListener);
  2321. nsCOMPtr<nsIStreamListener> wrapper = new nsStreamListenerWrapper(mListener);
  2322. wrapper.forget(_retval);
  2323. mListener = aListener;
  2324. return NS_OK;
  2325. }
  2326. //-----------------------------------------------------------------------------
  2327. // HttpBaseChannel helpers
  2328. //-----------------------------------------------------------------------------
  2329. void
  2330. HttpBaseChannel::ReleaseListeners()
  2331. {
  2332. MOZ_ASSERT(NS_IsMainThread(), "Should only be called on the main thread.");
  2333. mListener = nullptr;
  2334. mListenerContext = nullptr;
  2335. mCallbacks = nullptr;
  2336. mProgressSink = nullptr;
  2337. mCompressListener = nullptr;
  2338. }
  2339. void
  2340. HttpBaseChannel::DoNotifyListener()
  2341. {
  2342. if (mListener) {
  2343. MOZ_ASSERT(!mOnStartRequestCalled,
  2344. "We should not call OnStartRequest twice");
  2345. nsCOMPtr<nsIStreamListener> listener = mListener;
  2346. listener->OnStartRequest(this, mListenerContext);
  2347. mOnStartRequestCalled = true;
  2348. }
  2349. // Make sure mIsPending is set to false. At this moment we are done from
  2350. // the point of view of our consumer and we have to report our self
  2351. // as not-pending.
  2352. mIsPending = false;
  2353. if (mListener) {
  2354. MOZ_ASSERT(!mOnStopRequestCalled,
  2355. "We should not call OnStopRequest twice");
  2356. nsCOMPtr<nsIStreamListener> listener = mListener;
  2357. listener->OnStopRequest(this, mListenerContext, mStatus);
  2358. mOnStopRequestCalled = true;
  2359. }
  2360. // We have to make sure to drop the references to listeners and callbacks
  2361. // no longer needed
  2362. ReleaseListeners();
  2363. DoNotifyListenerCleanup();
  2364. // If this is a navigation, then we must let the docshell flush the reports
  2365. // to the console later. The LoadDocument() is pointing at the detached
  2366. // document that started the navigation. We want to show the reports on the
  2367. // new document. Otherwise the console is wiped and the user never sees
  2368. // the information.
  2369. if (!IsNavigation() && mLoadInfo) {
  2370. nsCOMPtr<nsIDOMDocument> dommyDoc;
  2371. mLoadInfo->GetLoadingDocument(getter_AddRefs(dommyDoc));
  2372. nsCOMPtr<nsIDocument> doc = do_QueryInterface(dommyDoc);
  2373. FlushConsoleReports(doc);
  2374. }
  2375. }
  2376. void
  2377. HttpBaseChannel::AddCookiesToRequest()
  2378. {
  2379. if (mLoadFlags & LOAD_ANONYMOUS) {
  2380. return;
  2381. }
  2382. bool useCookieService =
  2383. (XRE_IsParentProcess());
  2384. nsXPIDLCString cookie;
  2385. if (useCookieService) {
  2386. nsICookieService *cs = gHttpHandler->GetCookieService();
  2387. if (cs) {
  2388. cs->GetCookieStringFromHttp(mURI,
  2389. nullptr,
  2390. this, getter_Copies(cookie));
  2391. }
  2392. if (cookie.IsEmpty()) {
  2393. cookie = mUserSetCookieHeader;
  2394. }
  2395. else if (!mUserSetCookieHeader.IsEmpty()) {
  2396. cookie.AppendLiteral("; ");
  2397. cookie.Append(mUserSetCookieHeader);
  2398. }
  2399. }
  2400. else {
  2401. cookie = mUserSetCookieHeader;
  2402. }
  2403. // If we are in the child process, we want the parent seeing any
  2404. // cookie headers that might have been set by SetRequestHeader()
  2405. SetRequestHeader(nsDependentCString(nsHttp::Cookie), cookie, false);
  2406. }
  2407. bool
  2408. HttpBaseChannel::ShouldRewriteRedirectToGET(uint32_t httpStatus,
  2409. nsHttpRequestHead::ParsedMethodType method)
  2410. {
  2411. // for 301 and 302, only rewrite POST
  2412. if (httpStatus == 301 || httpStatus == 302)
  2413. return method == nsHttpRequestHead::kMethod_Post;
  2414. // rewrite for 303 unless it was HEAD
  2415. if (httpStatus == 303)
  2416. return method != nsHttpRequestHead::kMethod_Head;
  2417. // otherwise, such as for 307, do not rewrite
  2418. return false;
  2419. }
  2420. static
  2421. bool IsHeaderBlacklistedForRedirectCopy(nsHttpAtom const& aHeader)
  2422. {
  2423. // IMPORTANT: keep this list ASCII-code sorted
  2424. static nsHttpAtom const* blackList[] = {
  2425. &nsHttp::Accept,
  2426. &nsHttp::Accept_Encoding,
  2427. &nsHttp::Accept_Language,
  2428. &nsHttp::Authentication,
  2429. &nsHttp::Authorization,
  2430. &nsHttp::Connection,
  2431. &nsHttp::Content_Length,
  2432. &nsHttp::Cookie,
  2433. &nsHttp::Host,
  2434. &nsHttp::If,
  2435. &nsHttp::If_Match,
  2436. &nsHttp::If_Modified_Since,
  2437. &nsHttp::If_None_Match,
  2438. &nsHttp::If_None_Match_Any,
  2439. &nsHttp::If_Range,
  2440. &nsHttp::If_Unmodified_Since,
  2441. &nsHttp::Proxy_Authenticate,
  2442. &nsHttp::Proxy_Authorization,
  2443. &nsHttp::Range,
  2444. &nsHttp::TE,
  2445. &nsHttp::Transfer_Encoding,
  2446. &nsHttp::Upgrade,
  2447. &nsHttp::User_Agent,
  2448. &nsHttp::WWW_Authenticate
  2449. };
  2450. class HttpAtomComparator
  2451. {
  2452. nsHttpAtom const& mTarget;
  2453. public:
  2454. explicit HttpAtomComparator(nsHttpAtom const& aTarget)
  2455. : mTarget(aTarget) {}
  2456. int operator()(nsHttpAtom const* aVal) const {
  2457. if (mTarget == *aVal) {
  2458. return 0;
  2459. }
  2460. return strcmp(mTarget._val, aVal->_val);
  2461. }
  2462. };
  2463. size_t unused;
  2464. return BinarySearchIf(blackList, 0, ArrayLength(blackList),
  2465. HttpAtomComparator(aHeader), &unused);
  2466. }
  2467. class SetupReplacementChannelHeaderVisitor final : public nsIHttpHeaderVisitor
  2468. {
  2469. public:
  2470. NS_DECL_ISUPPORTS
  2471. explicit SetupReplacementChannelHeaderVisitor(nsIHttpChannel *aChannel)
  2472. : mChannel(aChannel)
  2473. {
  2474. }
  2475. NS_IMETHOD VisitHeader(const nsACString& aHeader,
  2476. const nsACString& aValue) override
  2477. {
  2478. nsHttpAtom atom = nsHttp::ResolveAtom(aHeader);
  2479. if (!IsHeaderBlacklistedForRedirectCopy(atom)) {
  2480. mChannel->SetRequestHeader(aHeader, aValue, false);
  2481. }
  2482. return NS_OK;
  2483. }
  2484. private:
  2485. ~SetupReplacementChannelHeaderVisitor()
  2486. {
  2487. }
  2488. nsCOMPtr<nsIHttpChannel> mChannel;
  2489. };
  2490. NS_IMPL_ISUPPORTS(SetupReplacementChannelHeaderVisitor, nsIHttpHeaderVisitor)
  2491. nsresult
  2492. HttpBaseChannel::SetupReplacementChannel(nsIURI *newURI,
  2493. nsIChannel *newChannel,
  2494. bool preserveMethod,
  2495. uint32_t redirectFlags)
  2496. {
  2497. LOG(("HttpBaseChannel::SetupReplacementChannel "
  2498. "[this=%p newChannel=%p preserveMethod=%d]",
  2499. this, newChannel, preserveMethod));
  2500. uint32_t newLoadFlags = mLoadFlags | LOAD_REPLACE;
  2501. // if the original channel was using SSL and this channel is not using
  2502. // SSL, then no need to inhibit persistent caching. however, if the
  2503. // original channel was not using SSL and has INHIBIT_PERSISTENT_CACHING
  2504. // set, then allow the flag to apply to the redirected channel as well.
  2505. // since we force set INHIBIT_PERSISTENT_CACHING on all HTTPS channels,
  2506. // we only need to check if the original channel was using SSL.
  2507. bool usingSSL = false;
  2508. nsresult rv = mURI->SchemeIs("https", &usingSSL);
  2509. if (NS_SUCCEEDED(rv) && usingSSL)
  2510. newLoadFlags &= ~INHIBIT_PERSISTENT_CACHING;
  2511. // Do not pass along LOAD_CHECK_OFFLINE_CACHE
  2512. newLoadFlags &= ~nsICachingChannel::LOAD_CHECK_OFFLINE_CACHE;
  2513. newChannel->SetLoadGroup(mLoadGroup);
  2514. newChannel->SetNotificationCallbacks(mCallbacks);
  2515. newChannel->SetLoadFlags(newLoadFlags);
  2516. // Try to preserve the privacy bit if it has been overridden
  2517. if (mPrivateBrowsingOverriden) {
  2518. nsCOMPtr<nsIPrivateBrowsingChannel> newPBChannel =
  2519. do_QueryInterface(newChannel);
  2520. if (newPBChannel) {
  2521. newPBChannel->SetPrivate(mPrivateBrowsing);
  2522. }
  2523. }
  2524. // make a copy of the loadinfo, append to the redirectchain
  2525. // and set it on the new channel
  2526. if (mLoadInfo) {
  2527. nsCOMPtr<nsILoadInfo> newLoadInfo =
  2528. static_cast<mozilla::LoadInfo*>(mLoadInfo.get())->Clone();
  2529. nsContentPolicyType contentPolicyType = mLoadInfo->GetExternalContentPolicyType();
  2530. if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
  2531. contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT) {
  2532. nsCOMPtr<nsIPrincipal> nullPrincipalToInherit = nsNullPrincipal::Create();
  2533. newLoadInfo->SetPrincipalToInherit(nullPrincipalToInherit);
  2534. }
  2535. // re-compute the origin attributes of the loadInfo if it's top-level load.
  2536. bool isTopLevelDoc =
  2537. newLoadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_DOCUMENT;
  2538. if (isTopLevelDoc) {
  2539. nsCOMPtr<nsILoadContext> loadContext;
  2540. NS_QueryNotificationCallbacks(this, loadContext);
  2541. DocShellOriginAttributes docShellAttrs;
  2542. if (loadContext) {
  2543. loadContext->GetOriginAttributes(docShellAttrs);
  2544. }
  2545. MOZ_ASSERT(docShellAttrs.mFirstPartyDomain.IsEmpty(),
  2546. "top-level docshell shouldn't have firstPartyDomain attribute.");
  2547. NeckoOriginAttributes attrs = newLoadInfo->GetOriginAttributes();
  2548. MOZ_ASSERT(docShellAttrs.mAppId == attrs.mAppId,
  2549. "docshell and necko should have the same appId attribute.");
  2550. MOZ_ASSERT(docShellAttrs.mUserContextId == attrs.mUserContextId,
  2551. "docshell and necko should have the same userContextId attribute.");
  2552. MOZ_ASSERT(docShellAttrs.mInIsolatedMozBrowser == attrs.mInIsolatedMozBrowser,
  2553. "docshell and necko should have the same inIsolatedMozBrowser attribute.");
  2554. MOZ_ASSERT(docShellAttrs.mPrivateBrowsingId == attrs.mPrivateBrowsingId,
  2555. "docshell and necko should have the same privateBrowsingId attribute.");
  2556. attrs.InheritFromDocShellToNecko(docShellAttrs, true, newURI);
  2557. newLoadInfo->SetOriginAttributes(attrs);
  2558. }
  2559. bool isInternalRedirect =
  2560. (redirectFlags & (nsIChannelEventSink::REDIRECT_INTERNAL |
  2561. nsIChannelEventSink::REDIRECT_STS_UPGRADE));
  2562. newLoadInfo->AppendRedirectedPrincipal(GetURIPrincipal(), isInternalRedirect);
  2563. newChannel->SetLoadInfo(newLoadInfo);
  2564. }
  2565. else {
  2566. // the newChannel was created with a dummy loadInfo, we should clear
  2567. // it in case the original channel does not have a loadInfo
  2568. newChannel->SetLoadInfo(nullptr);
  2569. }
  2570. nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(newChannel);
  2571. if (!httpChannel)
  2572. return NS_OK; // no other options to set
  2573. // Preserve the CORS preflight information.
  2574. nsCOMPtr<nsIHttpChannelInternal> httpInternal = do_QueryInterface(newChannel);
  2575. if (mRequireCORSPreflight && httpInternal) {
  2576. httpInternal->SetCorsPreflightParameters(mUnsafeHeaders);
  2577. }
  2578. if (preserveMethod) {
  2579. nsCOMPtr<nsIUploadChannel> uploadChannel =
  2580. do_QueryInterface(httpChannel);
  2581. nsCOMPtr<nsIUploadChannel2> uploadChannel2 =
  2582. do_QueryInterface(httpChannel);
  2583. if (mUploadStream && (uploadChannel2 || uploadChannel)) {
  2584. // rewind upload stream
  2585. nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mUploadStream);
  2586. if (seekable)
  2587. seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
  2588. // replicate original call to SetUploadStream...
  2589. if (uploadChannel2) {
  2590. nsAutoCString ctype;
  2591. // If header is not present mRequestHead.HasHeaderValue will truncated
  2592. // it. But we want to end up with a void string, not an empty string,
  2593. // because ExplicitSetUploadStream treats the former as "no header" and
  2594. // the latter as "header with empty string value".
  2595. nsresult ctypeOK = mRequestHead.GetHeader(nsHttp::Content_Type, ctype);
  2596. if (NS_FAILED(ctypeOK)) {
  2597. ctype.SetIsVoid(true);
  2598. }
  2599. nsAutoCString clen;
  2600. mRequestHead.GetHeader(nsHttp::Content_Length, clen);
  2601. nsAutoCString method;
  2602. mRequestHead.Method(method);
  2603. int64_t len = clen.IsEmpty() ? -1 : nsCRT::atoll(clen.get());
  2604. uploadChannel2->ExplicitSetUploadStream(
  2605. mUploadStream, ctype, len,
  2606. method,
  2607. mUploadStreamHasHeaders);
  2608. } else {
  2609. if (mUploadStreamHasHeaders) {
  2610. uploadChannel->SetUploadStream(mUploadStream, EmptyCString(),
  2611. -1);
  2612. } else {
  2613. nsAutoCString ctype;
  2614. if (NS_FAILED(mRequestHead.GetHeader(nsHttp::Content_Type, ctype))) {
  2615. ctype = NS_LITERAL_CSTRING("application/octet-stream");
  2616. }
  2617. nsAutoCString clen;
  2618. if (NS_SUCCEEDED(mRequestHead.GetHeader(nsHttp::Content_Length, clen))
  2619. &&
  2620. !clen.IsEmpty()) {
  2621. uploadChannel->SetUploadStream(mUploadStream,
  2622. ctype,
  2623. nsCRT::atoll(clen.get()));
  2624. }
  2625. }
  2626. }
  2627. }
  2628. // since preserveMethod is true, we need to ensure that the appropriate
  2629. // request method gets set on the channel, regardless of whether or not
  2630. // we set the upload stream above. This means SetRequestMethod() will
  2631. // be called twice if ExplicitSetUploadStream() gets called above.
  2632. nsAutoCString method;
  2633. mRequestHead.Method(method);
  2634. httpChannel->SetRequestMethod(method);
  2635. }
  2636. // convey the referrer if one was used for this channel to the next one
  2637. if (mReferrer)
  2638. httpChannel->SetReferrerWithPolicy(mReferrer, mReferrerPolicy);
  2639. // convey the mAllowPipelining and mAllowSTS flags
  2640. httpChannel->SetAllowPipelining(mAllowPipelining);
  2641. httpChannel->SetAllowSTS(mAllowSTS);
  2642. // convey the Accept header value
  2643. {
  2644. nsAutoCString oldAcceptValue;
  2645. nsresult hasHeader = mRequestHead.GetHeader(nsHttp::Accept, oldAcceptValue);
  2646. if (NS_SUCCEEDED(hasHeader)) {
  2647. httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
  2648. oldAcceptValue,
  2649. false);
  2650. }
  2651. }
  2652. // share the request context - see bug 1236650
  2653. httpChannel->SetRequestContextID(mRequestContextID);
  2654. if (httpInternal) {
  2655. // Convey third party cookie, conservative, and spdy flags.
  2656. httpInternal->SetThirdPartyFlags(mThirdPartyFlags);
  2657. httpInternal->SetAllowSpdy(mAllowSpdy);
  2658. httpInternal->SetAllowAltSvc(mAllowAltSvc);
  2659. httpInternal->SetBeConservative(mBeConservative);
  2660. RefPtr<nsHttpChannel> realChannel;
  2661. CallQueryInterface(newChannel, realChannel.StartAssignment());
  2662. if (realChannel) {
  2663. realChannel->SetTopWindowURI(mTopWindowURI);
  2664. }
  2665. // update the DocumentURI indicator since we are being redirected.
  2666. // if this was a top-level document channel, then the new channel
  2667. // should have its mDocumentURI point to newURI; otherwise, we
  2668. // just need to pass along our mDocumentURI to the new channel.
  2669. if (newURI && (mURI == mDocumentURI))
  2670. httpInternal->SetDocumentURI(newURI);
  2671. else
  2672. httpInternal->SetDocumentURI(mDocumentURI);
  2673. // if there is a chain of keys for redirect-responses we transfer it to
  2674. // the new channel (see bug #561276)
  2675. if (mRedirectedCachekeys) {
  2676. LOG(("HttpBaseChannel::SetupReplacementChannel "
  2677. "[this=%p] transferring chain of redirect cache-keys", this));
  2678. httpInternal->SetCacheKeysRedirectChain(mRedirectedCachekeys.forget());
  2679. }
  2680. // Preserve CORS mode flag.
  2681. httpInternal->SetCorsMode(mCorsMode);
  2682. // Preserve Redirect mode flag.
  2683. httpInternal->SetRedirectMode(mRedirectMode);
  2684. // Preserve Cache mode flag.
  2685. httpInternal->SetFetchCacheMode(mFetchCacheMode);
  2686. // Preserve Integrity metadata.
  2687. httpInternal->SetIntegrityMetadata(mIntegrityMetadata);
  2688. }
  2689. // transfer application cache information
  2690. nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
  2691. do_QueryInterface(newChannel);
  2692. if (appCacheChannel) {
  2693. appCacheChannel->SetApplicationCache(mApplicationCache);
  2694. appCacheChannel->SetInheritApplicationCache(mInheritApplicationCache);
  2695. // We purposely avoid transfering mChooseApplicationCache.
  2696. }
  2697. // transfer any properties
  2698. nsCOMPtr<nsIWritablePropertyBag> bag(do_QueryInterface(newChannel));
  2699. if (bag) {
  2700. for (auto iter = mPropertyHash.Iter(); !iter.Done(); iter.Next()) {
  2701. bag->SetProperty(iter.Key(), iter.UserData());
  2702. }
  2703. }
  2704. // Transfer the timing data (if we are dealing with an nsITimedChannel).
  2705. nsCOMPtr<nsITimedChannel> newTimedChannel(do_QueryInterface(newChannel));
  2706. nsCOMPtr<nsITimedChannel> oldTimedChannel(
  2707. do_QueryInterface(static_cast<nsIHttpChannel*>(this)));
  2708. if (oldTimedChannel && newTimedChannel) {
  2709. newTimedChannel->SetTimingEnabled(mTimingEnabled);
  2710. if (redirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL) {
  2711. int8_t newCount = mInternalRedirectCount + 1;
  2712. newTimedChannel->SetInternalRedirectCount(
  2713. std::max(newCount, mInternalRedirectCount));
  2714. } else {
  2715. int8_t newCount = mRedirectCount + 1;
  2716. newTimedChannel->SetRedirectCount(
  2717. std::max(newCount, mRedirectCount));
  2718. }
  2719. // If the RedirectStart is null, we will use the AsyncOpen value of the
  2720. // previous channel (this is the first redirect in the redirects chain).
  2721. if (mRedirectStartTimeStamp.IsNull()) {
  2722. // Only do this for real redirects. Internal redirects should be hidden.
  2723. if (!(redirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL)) {
  2724. TimeStamp asyncOpen;
  2725. oldTimedChannel->GetAsyncOpen(&asyncOpen);
  2726. newTimedChannel->SetRedirectStart(asyncOpen);
  2727. }
  2728. } else {
  2729. newTimedChannel->SetRedirectStart(mRedirectStartTimeStamp);
  2730. }
  2731. // For internal redirects just propagate the last redirect end time
  2732. // forward. Otherwise the new redirect end time is the last response
  2733. // end time.
  2734. TimeStamp newRedirectEnd;
  2735. if (redirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL) {
  2736. oldTimedChannel->GetRedirectEnd(&newRedirectEnd);
  2737. } else {
  2738. oldTimedChannel->GetResponseEnd(&newRedirectEnd);
  2739. }
  2740. newTimedChannel->SetRedirectEnd(newRedirectEnd);
  2741. nsAutoString initiatorType;
  2742. oldTimedChannel->GetInitiatorType(initiatorType);
  2743. newTimedChannel->SetInitiatorType(initiatorType);
  2744. // Check whether or not this was a cross-domain redirect.
  2745. newTimedChannel->SetAllRedirectsSameOrigin(
  2746. mAllRedirectsSameOrigin && SameOriginWithOriginalUri(newURI));
  2747. // Execute the timing allow check to determine whether
  2748. // to report the redirect timing info
  2749. nsCOMPtr<nsILoadInfo> loadInfo;
  2750. GetLoadInfo(getter_AddRefs(loadInfo));
  2751. // TYPE_DOCUMENT loads don't have a loadingPrincipal, so we can't set
  2752. // AllRedirectsPassTimingAllowCheck on them.
  2753. if (loadInfo && loadInfo->GetExternalContentPolicyType() != nsIContentPolicy::TYPE_DOCUMENT) {
  2754. nsCOMPtr<nsIPrincipal> principal = loadInfo->LoadingPrincipal();
  2755. newTimedChannel->SetAllRedirectsPassTimingAllowCheck(
  2756. mAllRedirectsPassTimingAllowCheck &&
  2757. oldTimedChannel->TimingAllowCheck(principal));
  2758. }
  2759. // Propagate service worker measurements across redirects. The
  2760. // PeformanceResourceTiming.workerStart API expects to see the
  2761. // worker start time after a redirect.
  2762. newTimedChannel->SetLaunchServiceWorkerStart(mLaunchServiceWorkerStart);
  2763. newTimedChannel->SetLaunchServiceWorkerEnd(mLaunchServiceWorkerEnd);
  2764. newTimedChannel->SetDispatchFetchEventStart(mDispatchFetchEventStart);
  2765. newTimedChannel->SetDispatchFetchEventEnd(mDispatchFetchEventEnd);
  2766. newTimedChannel->SetHandleFetchEventStart(mHandleFetchEventStart);
  2767. newTimedChannel->SetHandleFetchEventEnd(mHandleFetchEventEnd);
  2768. }
  2769. // Pass the preferred alt-data type on to the new channel.
  2770. nsCOMPtr<nsICacheInfoChannel> cacheInfoChan(do_QueryInterface(newChannel));
  2771. if (cacheInfoChan) {
  2772. cacheInfoChan->PreferAlternativeDataType(mPreferredCachedAltDataType);
  2773. }
  2774. if (redirectFlags & (nsIChannelEventSink::REDIRECT_INTERNAL |
  2775. nsIChannelEventSink::REDIRECT_STS_UPGRADE)) {
  2776. // Copy non-origin related headers to the new channel.
  2777. nsCOMPtr<nsIHttpHeaderVisitor> visitor =
  2778. new SetupReplacementChannelHeaderVisitor(httpChannel);
  2779. mRequestHead.VisitHeaders(visitor);
  2780. }
  2781. // This channel has been redirected. Don't report timing info.
  2782. mTimingEnabled = false;
  2783. return NS_OK;
  2784. }
  2785. // Redirect Tracking
  2786. bool
  2787. HttpBaseChannel::SameOriginWithOriginalUri(nsIURI *aURI)
  2788. {
  2789. nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
  2790. nsresult rv = ssm->CheckSameOriginURI(aURI, mOriginalURI, false);
  2791. return (NS_SUCCEEDED(rv));
  2792. }
  2793. //-----------------------------------------------------------------------------
  2794. // HttpBaseChannel::nsITimedChannel
  2795. //-----------------------------------------------------------------------------
  2796. NS_IMETHODIMP
  2797. HttpBaseChannel::SetTimingEnabled(bool enabled) {
  2798. mTimingEnabled = enabled;
  2799. return NS_OK;
  2800. }
  2801. NS_IMETHODIMP
  2802. HttpBaseChannel::GetTimingEnabled(bool* _retval) {
  2803. *_retval = mTimingEnabled;
  2804. return NS_OK;
  2805. }
  2806. NS_IMETHODIMP
  2807. HttpBaseChannel::GetChannelCreation(TimeStamp* _retval) {
  2808. *_retval = mChannelCreationTimestamp;
  2809. return NS_OK;
  2810. }
  2811. NS_IMETHODIMP
  2812. HttpBaseChannel::GetAsyncOpen(TimeStamp* _retval) {
  2813. *_retval = mAsyncOpenTime;
  2814. return NS_OK;
  2815. }
  2816. /**
  2817. * @return the number of redirects. There is no check for cross-domain
  2818. * redirects. This check must be done by the consumers.
  2819. */
  2820. NS_IMETHODIMP
  2821. HttpBaseChannel::GetRedirectCount(uint8_t *aRedirectCount)
  2822. {
  2823. *aRedirectCount = mRedirectCount;
  2824. return NS_OK;
  2825. }
  2826. NS_IMETHODIMP
  2827. HttpBaseChannel::SetRedirectCount(uint8_t aRedirectCount)
  2828. {
  2829. mRedirectCount = aRedirectCount;
  2830. return NS_OK;
  2831. }
  2832. NS_IMETHODIMP
  2833. HttpBaseChannel::GetInternalRedirectCount(uint8_t *aRedirectCount)
  2834. {
  2835. *aRedirectCount = mInternalRedirectCount;
  2836. return NS_OK;
  2837. }
  2838. NS_IMETHODIMP
  2839. HttpBaseChannel::SetInternalRedirectCount(uint8_t aRedirectCount)
  2840. {
  2841. mInternalRedirectCount = aRedirectCount;
  2842. return NS_OK;
  2843. }
  2844. NS_IMETHODIMP
  2845. HttpBaseChannel::GetRedirectStart(TimeStamp* _retval)
  2846. {
  2847. *_retval = mRedirectStartTimeStamp;
  2848. return NS_OK;
  2849. }
  2850. NS_IMETHODIMP
  2851. HttpBaseChannel::SetRedirectStart(TimeStamp aRedirectStart)
  2852. {
  2853. mRedirectStartTimeStamp = aRedirectStart;
  2854. return NS_OK;
  2855. }
  2856. NS_IMETHODIMP
  2857. HttpBaseChannel::GetRedirectEnd(TimeStamp* _retval)
  2858. {
  2859. *_retval = mRedirectEndTimeStamp;
  2860. return NS_OK;
  2861. }
  2862. NS_IMETHODIMP
  2863. HttpBaseChannel::SetRedirectEnd(TimeStamp aRedirectEnd)
  2864. {
  2865. mRedirectEndTimeStamp = aRedirectEnd;
  2866. return NS_OK;
  2867. }
  2868. NS_IMETHODIMP
  2869. HttpBaseChannel::GetAllRedirectsSameOrigin(bool *aAllRedirectsSameOrigin)
  2870. {
  2871. *aAllRedirectsSameOrigin = mAllRedirectsSameOrigin;
  2872. return NS_OK;
  2873. }
  2874. NS_IMETHODIMP
  2875. HttpBaseChannel::SetAllRedirectsSameOrigin(bool aAllRedirectsSameOrigin)
  2876. {
  2877. mAllRedirectsSameOrigin = aAllRedirectsSameOrigin;
  2878. return NS_OK;
  2879. }
  2880. NS_IMETHODIMP
  2881. HttpBaseChannel::GetAllRedirectsPassTimingAllowCheck(bool *aPassesCheck)
  2882. {
  2883. *aPassesCheck = mAllRedirectsPassTimingAllowCheck;
  2884. return NS_OK;
  2885. }
  2886. NS_IMETHODIMP
  2887. HttpBaseChannel::SetAllRedirectsPassTimingAllowCheck(bool aPassesCheck)
  2888. {
  2889. mAllRedirectsPassTimingAllowCheck = aPassesCheck;
  2890. return NS_OK;
  2891. }
  2892. // http://www.w3.org/TR/resource-timing/#timing-allow-check
  2893. NS_IMETHODIMP
  2894. HttpBaseChannel::TimingAllowCheck(nsIPrincipal *aOrigin, bool *_retval)
  2895. {
  2896. nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
  2897. nsCOMPtr<nsIPrincipal> resourcePrincipal;
  2898. nsresult rv = ssm->GetChannelURIPrincipal(this, getter_AddRefs(resourcePrincipal));
  2899. if (NS_FAILED(rv) || !resourcePrincipal || !aOrigin) {
  2900. *_retval = false;
  2901. return NS_OK;
  2902. }
  2903. bool sameOrigin = false;
  2904. rv = resourcePrincipal->Equals(aOrigin, &sameOrigin);
  2905. if (NS_SUCCEEDED(rv) && sameOrigin) {
  2906. *_retval = true;
  2907. return NS_OK;
  2908. }
  2909. nsAutoCString headerValue;
  2910. rv = GetResponseHeader(NS_LITERAL_CSTRING("Timing-Allow-Origin"), headerValue);
  2911. if (NS_FAILED(rv)) {
  2912. *_retval = false;
  2913. return NS_OK;
  2914. }
  2915. if (headerValue == "*") {
  2916. *_retval = true;
  2917. return NS_OK;
  2918. }
  2919. nsAutoCString origin;
  2920. nsContentUtils::GetASCIIOrigin(aOrigin, origin);
  2921. if (headerValue == origin) {
  2922. *_retval = true;
  2923. return NS_OK;
  2924. }
  2925. *_retval = false;
  2926. return NS_OK;
  2927. }
  2928. NS_IMETHODIMP
  2929. HttpBaseChannel::GetLaunchServiceWorkerStart(TimeStamp* _retval) {
  2930. MOZ_ASSERT(_retval);
  2931. *_retval = mLaunchServiceWorkerStart;
  2932. return NS_OK;
  2933. }
  2934. NS_IMETHODIMP
  2935. HttpBaseChannel::SetLaunchServiceWorkerStart(TimeStamp aTimeStamp) {
  2936. mLaunchServiceWorkerStart = aTimeStamp;
  2937. return NS_OK;
  2938. }
  2939. NS_IMETHODIMP
  2940. HttpBaseChannel::GetLaunchServiceWorkerEnd(TimeStamp* _retval) {
  2941. MOZ_ASSERT(_retval);
  2942. *_retval = mLaunchServiceWorkerEnd;
  2943. return NS_OK;
  2944. }
  2945. NS_IMETHODIMP
  2946. HttpBaseChannel::SetLaunchServiceWorkerEnd(TimeStamp aTimeStamp) {
  2947. mLaunchServiceWorkerEnd = aTimeStamp;
  2948. return NS_OK;
  2949. }
  2950. NS_IMETHODIMP
  2951. HttpBaseChannel::GetDispatchFetchEventStart(TimeStamp* _retval) {
  2952. MOZ_ASSERT(_retval);
  2953. *_retval = mDispatchFetchEventStart;
  2954. return NS_OK;
  2955. }
  2956. NS_IMETHODIMP
  2957. HttpBaseChannel::SetDispatchFetchEventStart(TimeStamp aTimeStamp) {
  2958. mDispatchFetchEventStart = aTimeStamp;
  2959. return NS_OK;
  2960. }
  2961. NS_IMETHODIMP
  2962. HttpBaseChannel::GetDispatchFetchEventEnd(TimeStamp* _retval) {
  2963. MOZ_ASSERT(_retval);
  2964. *_retval = mDispatchFetchEventEnd;
  2965. return NS_OK;
  2966. }
  2967. NS_IMETHODIMP
  2968. HttpBaseChannel::SetDispatchFetchEventEnd(TimeStamp aTimeStamp) {
  2969. mDispatchFetchEventEnd = aTimeStamp;
  2970. return NS_OK;
  2971. }
  2972. NS_IMETHODIMP
  2973. HttpBaseChannel::GetHandleFetchEventStart(TimeStamp* _retval) {
  2974. MOZ_ASSERT(_retval);
  2975. *_retval = mHandleFetchEventStart;
  2976. return NS_OK;
  2977. }
  2978. NS_IMETHODIMP
  2979. HttpBaseChannel::SetHandleFetchEventStart(TimeStamp aTimeStamp) {
  2980. mHandleFetchEventStart = aTimeStamp;
  2981. return NS_OK;
  2982. }
  2983. NS_IMETHODIMP
  2984. HttpBaseChannel::GetHandleFetchEventEnd(TimeStamp* _retval) {
  2985. MOZ_ASSERT(_retval);
  2986. *_retval = mHandleFetchEventEnd;
  2987. return NS_OK;
  2988. }
  2989. NS_IMETHODIMP
  2990. HttpBaseChannel::SetHandleFetchEventEnd(TimeStamp aTimeStamp) {
  2991. mHandleFetchEventEnd = aTimeStamp;
  2992. return NS_OK;
  2993. }
  2994. NS_IMETHODIMP
  2995. HttpBaseChannel::GetDomainLookupStart(TimeStamp* _retval) {
  2996. *_retval = mTransactionTimings.domainLookupStart;
  2997. return NS_OK;
  2998. }
  2999. NS_IMETHODIMP
  3000. HttpBaseChannel::GetDomainLookupEnd(TimeStamp* _retval) {
  3001. *_retval = mTransactionTimings.domainLookupEnd;
  3002. return NS_OK;
  3003. }
  3004. NS_IMETHODIMP
  3005. HttpBaseChannel::GetConnectStart(TimeStamp* _retval) {
  3006. *_retval = mTransactionTimings.connectStart;
  3007. return NS_OK;
  3008. }
  3009. NS_IMETHODIMP
  3010. HttpBaseChannel::GetSecureConnectionStart(TimeStamp* _retval) {
  3011. *_retval = mTransactionTimings.secureConnectionStart;
  3012. return NS_OK;
  3013. }
  3014. NS_IMETHODIMP
  3015. HttpBaseChannel::GetConnectEnd(TimeStamp* _retval) {
  3016. *_retval = mTransactionTimings.connectEnd;
  3017. return NS_OK;
  3018. }
  3019. NS_IMETHODIMP
  3020. HttpBaseChannel::GetRequestStart(TimeStamp* _retval) {
  3021. *_retval = mTransactionTimings.requestStart;
  3022. return NS_OK;
  3023. }
  3024. NS_IMETHODIMP
  3025. HttpBaseChannel::GetResponseStart(TimeStamp* _retval) {
  3026. *_retval = mTransactionTimings.responseStart;
  3027. return NS_OK;
  3028. }
  3029. NS_IMETHODIMP
  3030. HttpBaseChannel::GetResponseEnd(TimeStamp* _retval) {
  3031. *_retval = mTransactionTimings.responseEnd;
  3032. return NS_OK;
  3033. }
  3034. NS_IMETHODIMP
  3035. HttpBaseChannel::GetCacheReadStart(TimeStamp* _retval) {
  3036. *_retval = mCacheReadStart;
  3037. return NS_OK;
  3038. }
  3039. NS_IMETHODIMP
  3040. HttpBaseChannel::GetCacheReadEnd(TimeStamp* _retval) {
  3041. *_retval = mCacheReadEnd;
  3042. return NS_OK;
  3043. }
  3044. NS_IMETHODIMP
  3045. HttpBaseChannel::GetInitiatorType(nsAString & aInitiatorType)
  3046. {
  3047. aInitiatorType = mInitiatorType;
  3048. return NS_OK;
  3049. }
  3050. NS_IMETHODIMP
  3051. HttpBaseChannel::SetInitiatorType(const nsAString & aInitiatorType)
  3052. {
  3053. mInitiatorType = aInitiatorType;
  3054. return NS_OK;
  3055. }
  3056. #define IMPL_TIMING_ATTR(name) \
  3057. NS_IMETHODIMP \
  3058. HttpBaseChannel::Get##name##Time(PRTime* _retval) { \
  3059. TimeStamp stamp; \
  3060. Get##name(&stamp); \
  3061. if (stamp.IsNull()) { \
  3062. *_retval = 0; \
  3063. return NS_OK; \
  3064. } \
  3065. *_retval = mChannelCreationTime + \
  3066. (PRTime) ((stamp - mChannelCreationTimestamp).ToSeconds() * 1e6); \
  3067. return NS_OK; \
  3068. }
  3069. IMPL_TIMING_ATTR(ChannelCreation)
  3070. IMPL_TIMING_ATTR(AsyncOpen)
  3071. IMPL_TIMING_ATTR(LaunchServiceWorkerStart)
  3072. IMPL_TIMING_ATTR(LaunchServiceWorkerEnd)
  3073. IMPL_TIMING_ATTR(DispatchFetchEventStart)
  3074. IMPL_TIMING_ATTR(DispatchFetchEventEnd)
  3075. IMPL_TIMING_ATTR(HandleFetchEventStart)
  3076. IMPL_TIMING_ATTR(HandleFetchEventEnd)
  3077. IMPL_TIMING_ATTR(DomainLookupStart)
  3078. IMPL_TIMING_ATTR(DomainLookupEnd)
  3079. IMPL_TIMING_ATTR(ConnectStart)
  3080. IMPL_TIMING_ATTR(SecureConnectionStart)
  3081. IMPL_TIMING_ATTR(ConnectEnd)
  3082. IMPL_TIMING_ATTR(RequestStart)
  3083. IMPL_TIMING_ATTR(ResponseStart)
  3084. IMPL_TIMING_ATTR(ResponseEnd)
  3085. IMPL_TIMING_ATTR(CacheReadStart)
  3086. IMPL_TIMING_ATTR(CacheReadEnd)
  3087. IMPL_TIMING_ATTR(RedirectStart)
  3088. IMPL_TIMING_ATTR(RedirectEnd)
  3089. #undef IMPL_TIMING_ATTR
  3090. mozilla::dom::Performance*
  3091. HttpBaseChannel::GetPerformance()
  3092. {
  3093. // If performance timing is disabled, there is no need for the Performance
  3094. // object anymore.
  3095. if (!mTimingEnabled) {
  3096. return nullptr;
  3097. }
  3098. // There is no point in continuing, since the performance object in the parent
  3099. // isn't the same as the one in the child which will be reporting resource performance.
  3100. if (XRE_IsParentProcess() && BrowserTabsRemoteAutostart()) {
  3101. return nullptr;
  3102. }
  3103. if (!mLoadInfo) {
  3104. return nullptr;
  3105. }
  3106. // We don't need to report the resource timing entry for a TYPE_DOCUMENT load.
  3107. if (mLoadInfo->GetExternalContentPolicyType() == nsIContentPolicyBase::TYPE_DOCUMENT) {
  3108. return nullptr;
  3109. }
  3110. nsCOMPtr<nsIDOMDocument> domDocument;
  3111. mLoadInfo->GetLoadingDocument(getter_AddRefs(domDocument));
  3112. if (!domDocument) {
  3113. return nullptr;
  3114. }
  3115. nsCOMPtr<nsIDocument> loadingDocument = do_QueryInterface(domDocument);
  3116. if (!loadingDocument) {
  3117. return nullptr;
  3118. }
  3119. if (!mLoadInfo->TriggeringPrincipal()->Equals(loadingDocument->NodePrincipal())) {
  3120. return nullptr;
  3121. }
  3122. if (mLoadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_SUBDOCUMENT &&
  3123. !mLoadInfo->GetIsFromProcessingFrameAttributes()) {
  3124. // We only report loads caused by processing the attributes of the
  3125. // browsing context container.
  3126. return nullptr;
  3127. }
  3128. nsCOMPtr<nsPIDOMWindowInner> innerWindow = loadingDocument->GetInnerWindow();
  3129. if (!innerWindow) {
  3130. return nullptr;
  3131. }
  3132. mozilla::dom::Performance* docPerformance = innerWindow->GetPerformance();
  3133. if (!docPerformance) {
  3134. return nullptr;
  3135. }
  3136. return docPerformance;
  3137. }
  3138. nsIURI*
  3139. HttpBaseChannel::GetReferringPage()
  3140. {
  3141. nsCOMPtr<nsPIDOMWindowInner> pDomWindow = GetInnerDOMWindow();
  3142. if (!pDomWindow) {
  3143. return nullptr;
  3144. }
  3145. return pDomWindow->GetDocumentURI();
  3146. }
  3147. nsPIDOMWindowInner*
  3148. HttpBaseChannel::GetInnerDOMWindow()
  3149. {
  3150. nsCOMPtr<nsILoadContext> loadContext;
  3151. NS_QueryNotificationCallbacks(this, loadContext);
  3152. if (!loadContext) {
  3153. return nullptr;
  3154. }
  3155. nsCOMPtr<mozIDOMWindowProxy> domWindow;
  3156. loadContext->GetAssociatedWindow(getter_AddRefs(domWindow));
  3157. if (!domWindow) {
  3158. return nullptr;
  3159. }
  3160. auto* pDomWindow = nsPIDOMWindowOuter::From(domWindow);
  3161. if (!pDomWindow) {
  3162. return nullptr;
  3163. }
  3164. nsCOMPtr<nsPIDOMWindowInner> innerWindow = pDomWindow->GetCurrentInnerWindow();
  3165. if (!innerWindow) {
  3166. return nullptr;
  3167. }
  3168. return innerWindow;
  3169. }
  3170. //-----------------------------------------------------------------------------
  3171. // HttpBaseChannel::nsIThrottledInputChannel
  3172. //-----------------------------------------------------------------------------
  3173. NS_IMETHODIMP
  3174. HttpBaseChannel::SetThrottleQueue(nsIInputChannelThrottleQueue* aQueue)
  3175. {
  3176. if (!XRE_IsParentProcess()) {
  3177. return NS_ERROR_FAILURE;
  3178. }
  3179. mThrottleQueue = aQueue;
  3180. return NS_OK;
  3181. }
  3182. NS_IMETHODIMP
  3183. HttpBaseChannel::GetThrottleQueue(nsIInputChannelThrottleQueue** aQueue)
  3184. {
  3185. *aQueue = mThrottleQueue;
  3186. return NS_OK;
  3187. }
  3188. //------------------------------------------------------------------------------
  3189. bool
  3190. HttpBaseChannel::EnsureRequestContextID()
  3191. {
  3192. nsID nullID;
  3193. nullID.Clear();
  3194. if (!mRequestContextID.Equals(nullID)) {
  3195. // Already have a request context ID, no need to do the rest of this work
  3196. return true;
  3197. }
  3198. // Find the loadgroup at the end of the chain in order
  3199. // to make sure all channels derived from the load group
  3200. // use the same connection scope.
  3201. nsCOMPtr<nsILoadGroupChild> childLoadGroup = do_QueryInterface(mLoadGroup);
  3202. if (!childLoadGroup) {
  3203. return false;
  3204. }
  3205. nsCOMPtr<nsILoadGroup> rootLoadGroup;
  3206. childLoadGroup->GetRootLoadGroup(getter_AddRefs(rootLoadGroup));
  3207. if (!rootLoadGroup) {
  3208. return false;
  3209. }
  3210. // Set the load group connection scope on the transaction
  3211. rootLoadGroup->GetRequestContextID(&mRequestContextID);
  3212. return true;
  3213. }
  3214. void
  3215. HttpBaseChannel::SetCorsPreflightParameters(const nsTArray<nsCString>& aUnsafeHeaders)
  3216. {
  3217. MOZ_RELEASE_ASSERT(!mRequestObserversCalled);
  3218. mRequireCORSPreflight = true;
  3219. mUnsafeHeaders = aUnsafeHeaders;
  3220. }
  3221. NS_IMETHODIMP
  3222. HttpBaseChannel::GetBlockAuthPrompt(bool* aValue)
  3223. {
  3224. if (!aValue) {
  3225. return NS_ERROR_FAILURE;
  3226. }
  3227. *aValue = mBlockAuthPrompt;
  3228. return NS_OK;
  3229. }
  3230. NS_IMETHODIMP
  3231. HttpBaseChannel::SetBlockAuthPrompt(bool aValue)
  3232. {
  3233. ENSURE_CALLED_BEFORE_CONNECT();
  3234. mBlockAuthPrompt = aValue;
  3235. return NS_OK;
  3236. }
  3237. NS_IMETHODIMP
  3238. HttpBaseChannel::GetConnectionInfoHashKey(nsACString& aConnectionInfoHashKey)
  3239. {
  3240. if (!mConnectionInfo) {
  3241. return NS_ERROR_FAILURE;
  3242. }
  3243. aConnectionInfoHashKey.Assign(mConnectionInfo->HashKey());
  3244. return NS_OK;
  3245. }
  3246. } // namespace net
  3247. } // namespace mozilla