bool HttpChannelParent::RecvRedirect2Verify(const nsresult& result, const RequestHeaderTuples& changedHeaders, const OptionalURIParams& aAPIRedirectURI) { LOG(("HttpChannelParent::RecvRedirect2Verify [this=%p result=%x]\n", this, result)); if (NS_SUCCEEDED(result)) { nsCOMPtr<nsIHttpChannel> newHttpChannel = do_QueryInterface(mRedirectChannel); if (newHttpChannel) { nsCOMPtr<nsIURI> apiRedirectUri = DeserializeURI(aAPIRedirectURI); if (apiRedirectUri) newHttpChannel->RedirectTo(apiRedirectUri); for (uint32_t i = 0; i < changedHeaders.Length(); i++) { if (changedHeaders[i].mEmpty) { newHttpChannel->SetEmptyRequestHeader(changedHeaders[i].mHeader); } else { newHttpChannel->SetRequestHeader(changedHeaders[i].mHeader, changedHeaders[i].mValue, changedHeaders[i].mMerge); } } } } if (!mRedirectCallback) { // This should according the logic never happen, log the situation. if (mReceivedRedirect2Verify) LOG(("RecvRedirect2Verify[%p]: Duplicate fire", this)); if (mSentRedirect1BeginFailed) LOG(("RecvRedirect2Verify[%p]: Send to child failed", this)); if (mSentRedirect1Begin && NS_FAILED(result)) LOG(("RecvRedirect2Verify[%p]: Redirect failed", this)); if (mSentRedirect1Begin && NS_SUCCEEDED(result)) LOG(("RecvRedirect2Verify[%p]: Redirect succeeded", this)); if (!mRedirectChannel) LOG(("RecvRedirect2Verify[%p]: Missing redirect channel", this)); NS_ERROR("Unexpcted call to HttpChannelParent::RecvRedirect2Verify, " "mRedirectCallback null"); } mReceivedRedirect2Verify = true; if (mRedirectCallback) { LOG(("HttpChannelParent::RecvRedirect2Verify call OnRedirectVerifyCallback" " [this=%p result=%x, mRedirectCallback=%p]\n", this, result, mRedirectCallback.get())); mRedirectCallback->OnRedirectVerifyCallback(result); mRedirectCallback = nullptr; } return true; }
void HttpChannelChild::OnStartRequest(const nsHttpResponseHead& responseHead, const PRBool& useResponseHead, const RequestHeaderTuples& requestHeaders, const PRBool& isFromCache, const PRBool& cacheEntryAvailable, const PRUint32& cacheExpirationTime, const nsCString& cachedCharset, const nsCString& securityInfoSerialization, const PRNetAddr& selfAddr, const PRNetAddr& peerAddr) { LOG(("HttpChannelChild::RecvOnStartRequest [this=%x]\n", this)); if (useResponseHead && !mCanceled) mResponseHead = new nsHttpResponseHead(responseHead); if (!securityInfoSerialization.IsEmpty()) { NS_DeserializeObject(securityInfoSerialization, getter_AddRefs(mSecurityInfo)); } mIsFromCache = isFromCache; mCacheEntryAvailable = cacheEntryAvailable; mCacheExpirationTime = cacheExpirationTime; mCachedCharset = cachedCharset; AutoEventEnqueuer ensureSerialDispatch(this); // replace our request headers with what actually got sent in the parent mRequestHead.ClearHeaders(); for (PRUint32 i = 0; i < requestHeaders.Length(); i++) { mRequestHead.Headers().SetHeader(nsHttp::ResolveAtom(requestHeaders[i].mHeader), requestHeaders[i].mValue); } nsresult rv = mListener->OnStartRequest(this, mListenerContext); if (NS_FAILED(rv)) { Cancel(rv); return; } if (mResponseHead) SetCookie(mResponseHead->PeekHeader(nsHttp::Set_Cookie)); rv = ApplyContentConversions(); if (NS_FAILED(rv)) Cancel(rv); mSelfAddr = selfAddr; mPeerAddr = peerAddr; }
bool HttpChannelParent::RecvRedirect2Verify(const nsresult& result, const RequestHeaderTuples& changedHeaders) { if (NS_SUCCEEDED(result)) { nsCOMPtr<nsIHttpChannel> newHttpChannel = do_QueryInterface(mRedirectChannel); if (newHttpChannel) { for (PRUint32 i = 0; i < changedHeaders.Length(); i++) { newHttpChannel->SetRequestHeader(changedHeaders[i].mHeader, changedHeaders[i].mValue, changedHeaders[i].mMerge); } } } if (!mRedirectCallback) { // This should according the logic never happen, log the situation. if (mReceivedRedirect2Verify) LOG(("RecvRedirect2Verify[%p]: Duplicate fire", this)); if (mSentRedirect1BeginFailed) LOG(("RecvRedirect2Verify[%p]: Send to child failed", this)); if (mSentRedirect1Begin && NS_FAILED(result)) LOG(("RecvRedirect2Verify[%p]: Redirect failed", this)); if (mSentRedirect1Begin && NS_SUCCEEDED(result)) LOG(("RecvRedirect2Verify[%p]: Redirect succeeded", this)); if (!mRedirectChannel) LOG(("RecvRedirect2Verify[%p]: Missing redirect channel", this)); NS_ERROR("Unexpcted call to HttpChannelParent::RecvRedirect2Verify, " "mRedirectCallback null"); } mReceivedRedirect2Verify = true; if (mRedirectCallback) { mRedirectCallback->OnRedirectVerifyCallback(result); mRedirectCallback = nullptr; } return true; }
bool HttpChannelParent::RecvRedirect2Verify(const nsresult& result, const RequestHeaderTuples& changedHeaders) { if (NS_SUCCEEDED(result)) { nsCOMPtr<nsIHttpChannel> newHttpChannel = do_QueryInterface(mRedirectChannel); if (newHttpChannel) { for (PRUint32 i = 0; i < changedHeaders.Length(); i++) { newHttpChannel->SetRequestHeader(changedHeaders[i].mHeader, changedHeaders[i].mValue, changedHeaders[i].mMerge); } } } mRedirectCallback->OnRedirectVerifyCallback(result); mRedirectCallback = nsnull; return true; }
bool HttpChannelParent::RecvRedirect2Verify(const nsresult& result, const RequestHeaderTuples& changedHeaders) { if (NS_SUCCEEDED(result)) { nsCOMPtr<nsIHttpChannel> newHttpChannel = do_QueryInterface(mRedirectChannel); if (newHttpChannel) { for (PRUint32 i = 0; i < changedHeaders.Length(); i++) { newHttpChannel->SetRequestHeader(changedHeaders[i].mHeader, changedHeaders[i].mValue, changedHeaders[i].mMerge); } } } if (!mRedirectCallback) { // Bug 621446 investigation (optimization turned off above) if (mReceivedRedirect2Verify) NS_RUNTIMEABORT("Duplicate fire"); if (mSentRedirect1BeginFailed) NS_RUNTIMEABORT("Send to child failed"); if (mSentRedirect1Begin && NS_FAILED(result)) NS_RUNTIMEABORT("Redirect failed"); if (mSentRedirect1Begin && NS_SUCCEEDED(result)) NS_RUNTIMEABORT("Redirect succeeded"); if (!mRedirectChannel) NS_RUNTIMEABORT("Missing redirect channel"); } mReceivedRedirect2Verify = true; mRedirectCallback->OnRedirectVerifyCallback(result); mRedirectCallback = nsnull; return true; }
bool HttpChannelParent::DoAsyncOpen( const URIParams& aURI, const OptionalURIParams& aOriginalURI, const OptionalURIParams& aDocURI, const OptionalURIParams& aReferrerURI, const uint32_t& aReferrerPolicy, const OptionalURIParams& aAPIRedirectToURI, const OptionalURIParams& aTopWindowURI, const uint32_t& aLoadFlags, const RequestHeaderTuples& requestHeaders, const nsCString& requestMethod, const OptionalInputStreamParams& uploadStream, const bool& uploadStreamHasHeaders, const uint16_t& priority, const uint32_t& classOfService, const uint8_t& redirectionLimit, const bool& allowPipelining, const bool& allowSTS, const uint32_t& thirdPartyFlags, const bool& doResumeAt, const uint64_t& startPos, const nsCString& entityID, const bool& chooseApplicationCache, const nsCString& appCacheClientID, const bool& allowSpdy, const bool& allowAltSvc, const OptionalFileDescriptorSet& aFds, const OptionalLoadInfoArgs& aLoadInfoArgs, const OptionalHttpResponseHead& aSynthesizedResponseHead, const nsCString& aSecurityInfoSerialization, const uint32_t& aCacheKey, const nsCString& aSchedulingContextID) { nsCOMPtr<nsIURI> uri = DeserializeURI(aURI); if (!uri) { // URIParams does MOZ_ASSERT if null, but we need to protect opt builds from // null deref here. return false; } nsCOMPtr<nsIURI> originalUri = DeserializeURI(aOriginalURI); nsCOMPtr<nsIURI> docUri = DeserializeURI(aDocURI); nsCOMPtr<nsIURI> referrerUri = DeserializeURI(aReferrerURI); nsCOMPtr<nsIURI> apiRedirectToUri = DeserializeURI(aAPIRedirectToURI); nsCOMPtr<nsIURI> topWindowUri = DeserializeURI(aTopWindowURI); nsCString uriSpec; uri->GetSpec(uriSpec); LOG(("HttpChannelParent RecvAsyncOpen [this=%p uri=%s]\n", this, uriSpec.get())); nsresult rv; nsCOMPtr<nsIIOService> ios(do_GetIOService(&rv)); if (NS_FAILED(rv)) return SendFailedAsyncOpen(rv); bool appOffline = false; uint32_t appId = GetAppId(); if (appId != NECKO_UNKNOWN_APP_ID && appId != NECKO_NO_APP_ID) { gIOService->IsAppOffline(appId, &appOffline); } uint32_t loadFlags = aLoadFlags; if (appOffline) { loadFlags |= nsICachingChannel::LOAD_ONLY_FROM_CACHE; loadFlags |= nsIRequest::LOAD_FROM_CACHE; loadFlags |= nsICachingChannel::LOAD_NO_NETWORK_IO; } nsCOMPtr<nsILoadInfo> loadInfo; rv = mozilla::ipc::LoadInfoArgsToLoadInfo(aLoadInfoArgs, getter_AddRefs(loadInfo)); if (NS_FAILED(rv)) { return SendFailedAsyncOpen(rv); } nsCOMPtr<nsIChannel> channel; rv = NS_NewChannelInternal(getter_AddRefs(channel), uri, loadInfo, nullptr, nullptr, loadFlags, ios); if (NS_FAILED(rv)) return SendFailedAsyncOpen(rv); mChannel = static_cast<nsHttpChannel *>(channel.get()); mChannel->SetWarningReporter(this); mChannel->SetTimingEnabled(true); if (mPBOverride != kPBOverride_Unset) { mChannel->SetPrivate(mPBOverride == kPBOverride_Private ? true : false); } if (doResumeAt) mChannel->ResumeAt(startPos, entityID); if (originalUri) mChannel->SetOriginalURI(originalUri); if (docUri) mChannel->SetDocumentURI(docUri); if (referrerUri) mChannel->SetReferrerWithPolicyInternal(referrerUri, aReferrerPolicy); if (apiRedirectToUri) mChannel->RedirectTo(apiRedirectToUri); if (topWindowUri) mChannel->SetTopWindowURI(topWindowUri); if (loadFlags != nsIRequest::LOAD_NORMAL) mChannel->SetLoadFlags(loadFlags); for (uint32_t i = 0; i < requestHeaders.Length(); i++) { mChannel->SetRequestHeader(requestHeaders[i].mHeader, requestHeaders[i].mValue, requestHeaders[i].mMerge); } mParentListener = new HttpChannelParentListener(this); mChannel->SetNotificationCallbacks(mParentListener); mChannel->SetRequestMethod(nsDependentCString(requestMethod.get())); nsTArray<mozilla::ipc::FileDescriptor> fds; if (aFds.type() == OptionalFileDescriptorSet::TPFileDescriptorSetParent) { FileDescriptorSetParent* fdSetActor = static_cast<FileDescriptorSetParent*>(aFds.get_PFileDescriptorSetParent()); MOZ_ASSERT(fdSetActor); fdSetActor->ForgetFileDescriptors(fds); MOZ_ASSERT(!fds.IsEmpty()); unused << fdSetActor->Send__delete__(fdSetActor); } else if (aFds.type() == OptionalFileDescriptorSet::TArrayOfFileDescriptor) { const_cast<OptionalFileDescriptorSet&>(aFds). get_ArrayOfFileDescriptor().SwapElements(fds); } nsCOMPtr<nsIInputStream> stream = DeserializeInputStream(uploadStream, fds); if (stream) { mChannel->InternalSetUploadStream(stream); mChannel->SetUploadStreamHasHeaders(uploadStreamHasHeaders); } if (aSynthesizedResponseHead.type() == OptionalHttpResponseHead::TnsHttpResponseHead) { mSynthesizedResponseHead = new nsHttpResponseHead(aSynthesizedResponseHead.get_nsHttpResponseHead()); mShouldIntercept = true; if (!aSecurityInfoSerialization.IsEmpty()) { nsCOMPtr<nsISupports> secInfo; NS_DeserializeObject(aSecurityInfoSerialization, getter_AddRefs(secInfo)); mChannel->OverrideSecurityInfo(secInfo); } } else { mChannel->ForceNoIntercept(); } nsCOMPtr<nsISupportsPRUint32> cacheKey = do_CreateInstance(NS_SUPPORTS_PRUINT32_CONTRACTID, &rv); if (NS_FAILED(rv)) { return SendFailedAsyncOpen(rv); } rv = cacheKey->SetData(aCacheKey); if (NS_FAILED(rv)) { return SendFailedAsyncOpen(rv); } mChannel->SetCacheKey(cacheKey); if (priority != nsISupportsPriority::PRIORITY_NORMAL) { mChannel->SetPriority(priority); } if (classOfService) { mChannel->SetClassFlags(classOfService); } mChannel->SetRedirectionLimit(redirectionLimit); mChannel->SetAllowPipelining(allowPipelining); mChannel->SetAllowSTS(allowSTS); mChannel->SetThirdPartyFlags(thirdPartyFlags); mChannel->SetAllowSpdy(allowSpdy); mChannel->SetAllowAltSvc(allowAltSvc); nsCOMPtr<nsIApplicationCacheChannel> appCacheChan = do_QueryObject(mChannel); nsCOMPtr<nsIApplicationCacheService> appCacheService = do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID); bool setChooseApplicationCache = chooseApplicationCache; if (appCacheChan && appCacheService) { // We might potentially want to drop this flag (that is TRUE by default) // after we successfully associate the channel with an application cache // reported by the channel child. Dropping it here may be too early. appCacheChan->SetInheritApplicationCache(false); if (!appCacheClientID.IsEmpty()) { nsCOMPtr<nsIApplicationCache> appCache; rv = appCacheService->GetApplicationCache(appCacheClientID, getter_AddRefs(appCache)); if (NS_SUCCEEDED(rv)) { appCacheChan->SetApplicationCache(appCache); setChooseApplicationCache = false; } } if (setChooseApplicationCache) { bool inBrowser = false; if (mLoadContext) { mLoadContext->GetIsInBrowserElement(&inBrowser); } bool chooseAppCache = false; nsCOMPtr<nsIScriptSecurityManager> secMan = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID); if (secMan) { nsCOMPtr<nsIPrincipal> principal; secMan->GetAppCodebasePrincipal(uri, appId, inBrowser, getter_AddRefs(principal)); // This works because we've already called SetNotificationCallbacks and // done mPBOverride logic by this point. chooseAppCache = NS_ShouldCheckAppCache(principal, NS_UsePrivateBrowsing(mChannel)); } appCacheChan->SetChooseApplicationCache(chooseAppCache); } } nsID schedulingContextID; schedulingContextID.Parse(aSchedulingContextID.BeginReading()); mChannel->SetSchedulingContextID(schedulingContextID); if (loadInfo && loadInfo->GetEnforceSecurity()) { rv = mChannel->AsyncOpen2(mParentListener); } else { rv = mChannel->AsyncOpen(mParentListener, nullptr); } if (NS_FAILED(rv)) return SendFailedAsyncOpen(rv); return true; }
NS_IMETHODIMP HttpChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext) { LOG(("HttpChannelParent::OnStartRequest [this=%x]\n", this)); nsHttpChannel *chan = static_cast<nsHttpChannel *>(aRequest); nsHttpResponseHead *responseHead = chan->GetResponseHead(); nsHttpRequestHead *requestHead = chan->GetRequestHead(); PRBool isFromCache = false; chan->IsFromCache(&isFromCache); PRUint32 expirationTime = nsICache::NO_EXPIRATION_TIME; chan->GetCacheTokenExpirationTime(&expirationTime); nsCString cachedCharset; chan->GetCacheTokenCachedCharset(cachedCharset); PRBool loadedFromApplicationCache; chan->GetLoadedFromApplicationCache(&loadedFromApplicationCache); if (loadedFromApplicationCache) { nsCOMPtr<nsIApplicationCache> appCache; chan->GetApplicationCache(getter_AddRefs(appCache)); nsCString appCacheGroupId; nsCString appCacheClientId; appCache->GetGroupID(appCacheGroupId); appCache->GetClientID(appCacheClientId); if (mIPCClosed || !SendAssociateApplicationCache(appCacheGroupId, appCacheClientId)) { return NS_ERROR_UNEXPECTED; } } nsCOMPtr<nsIEncodedChannel> encodedChannel = do_QueryInterface(aRequest); if (encodedChannel) encodedChannel->SetApplyConversion(PR_FALSE); // Keep the cache entry for future use in RecvSetCacheTokenCachedCharset(). // It could be already released by nsHttpChannel at that time. chan->GetCacheToken(getter_AddRefs(mCacheDescriptor)); nsCString secInfoSerialization; nsCOMPtr<nsISupports> secInfoSupp; chan->GetSecurityInfo(getter_AddRefs(secInfoSupp)); if (secInfoSupp) { nsCOMPtr<nsISerializable> secInfoSer = do_QueryInterface(secInfoSupp); if (secInfoSer) NS_SerializeToString(secInfoSer, secInfoSerialization); } RequestHeaderTuples headers; nsHttpHeaderArray harray = requestHead->Headers(); for (PRUint32 i = 0; i < harray.Count(); i++) { RequestHeaderTuple* tuple = headers.AppendElement(); tuple->mHeader = harray.Headers()[i].header; tuple->mValue = harray.Headers()[i].value; tuple->mMerge = false; } if (mIPCClosed || !SendOnStartRequest(responseHead ? *responseHead : nsHttpResponseHead(), !!responseHead, headers, isFromCache, mCacheDescriptor ? PR_TRUE : PR_FALSE, expirationTime, cachedCharset, secInfoSerialization)) { return NS_ERROR_UNEXPECTED; } return NS_OK; }