already_AddRefed<nsIInputStream> CacheParent::DeserializeCacheStream(const PCacheReadStreamOrVoid& aStreamOrVoid) { if (aStreamOrVoid.type() == PCacheReadStreamOrVoid::Tvoid_t) { return nullptr; } const PCacheReadStream& readStream = aStreamOrVoid.get_PCacheReadStream(); nsCOMPtr<nsIInputStream> stream = ReadStream::Create(readStream); if (stream) { return stream.forget(); } nsAutoTArray<FileDescriptor, 4> fds; if (readStream.fds().type() == OptionalFileDescriptorSet::TPFileDescriptorSetChild) { FileDescriptorSetParent* fdSetActor = static_cast<FileDescriptorSetParent*>(readStream.fds().get_PFileDescriptorSetParent()); MOZ_ASSERT(fdSetActor); fdSetActor->ForgetFileDescriptors(fds); MOZ_ASSERT(!fds.IsEmpty()); if (!fdSetActor->Send__delete__(fdSetActor)) { // child process is gone, warn and allow actor to clean up normally NS_WARNING("Cache failed to delete fd set actor."); } } return DeserializeInputStream(readStream.params(), fds); }
already_AddRefed<nsIInputStream> CacheOpParent::DeserializeCacheStream(const CacheReadStreamOrVoid& aStreamOrVoid) { if (aStreamOrVoid.type() == CacheReadStreamOrVoid::Tvoid_t) { return nullptr; } nsCOMPtr<nsIInputStream> stream; const CacheReadStream& readStream = aStreamOrVoid.get_CacheReadStream(); // Option 1: A push stream actor was sent for nsPipe data if (readStream.pushStreamParent()) { MOZ_ASSERT(!readStream.controlParent()); CachePushStreamParent* pushStream = static_cast<CachePushStreamParent*>(readStream.pushStreamParent()); stream = pushStream->TakeReader(); MOZ_ASSERT(stream); return stream.forget(); } // Option 2: One of our own ReadStreams was passed back to us with a stream // control actor. stream = ReadStream::Create(readStream); if (stream) { return stream.forget(); } // Option 3: A stream was serialized using normal methods. nsAutoTArray<FileDescriptor, 4> fds; if (readStream.fds().type() == OptionalFileDescriptorSet::TPFileDescriptorSetChild) { FileDescriptorSetParent* fdSetActor = static_cast<FileDescriptorSetParent*>(readStream.fds().get_PFileDescriptorSetParent()); MOZ_ASSERT(fdSetActor); fdSetActor->ForgetFileDescriptors(fds); MOZ_ASSERT(!fds.IsEmpty()); if (!fdSetActor->Send__delete__(fdSetActor)) { // child process is gone, warn and allow actor to clean up normally NS_WARNING("Cache failed to delete fd set actor."); } } return DeserializeInputStream(readStream.params(), fds); }
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; }