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;
}
Example #2
0
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;
}
Example #4
0
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;
}
Example #7
0
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;
}