NS_IMETHODIMP nsBaseChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult status) { // If both mStatus and status are failure codes, we keep mStatus as-is since // that is consistent with our GetStatus and Cancel methods. if (NS_SUCCEEDED(mStatus)) mStatus = status; // Cause IsPending to return false. mPump = nullptr; if (mListener) // null in case of redirect mListener->OnStopRequest(this, mListenerContext, mStatus); ChannelDone(); // No need to suspend pump in this scope since we will not be receiving // any more events from it. if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, mStatus); // Drop notification callbacks to prevent cycles. mCallbacks = nullptr; CallbacksChanged(); return NS_OK; }
NS_IMETHODIMP nsBaseChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt) { MOZ_ASSERT(!mLoadInfo || mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->GetInitialSecurityCheckDone() || (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL && nsContentUtils::IsSystemPrincipal(mLoadInfo->LoadingPrincipal())), "security flags in loadInfo but asyncOpen2() not called"); NS_ENSURE_TRUE(mURI, NS_ERROR_NOT_INITIALIZED); NS_ENSURE_TRUE(!mPump, NS_ERROR_IN_PROGRESS); NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED); NS_ENSURE_ARG(listener); // Skip checking for chrome:// sub-resources. nsAutoCString scheme; mURI->GetScheme(scheme); if (!scheme.EqualsLiteral("file")) { NS_CompareLoadInfoAndLoadContext(this); } // Ensure that this is an allowed port before proceeding. nsresult rv = NS_CheckPortSafety(mURI); if (NS_FAILED(rv)) { mCallbacks = nullptr; return rv; } // Store the listener and context early so that OpenContentStream and the // stream's AsyncWait method (called by AsyncRead) can have access to them // via PushStreamConverter and the StreamListener methods. However, since // this typically introduces a reference cycle between this and the listener, // we need to be sure to break the reference if this method does not succeed. mListener = listener; mListenerContext = ctxt; // This method assigns mPump as a side-effect. We need to clear mPump if // this method fails. rv = BeginPumpingData(); if (NS_FAILED(rv)) { mPump = nullptr; ChannelDone(); mCallbacks = nullptr; return rv; } // At this point, we are going to return success no matter what. mWasOpened = true; SUSPEND_PUMP_FOR_SCOPE(); if (mLoadGroup) mLoadGroup->AddRequest(this, nullptr); ClassifyURI(); return NS_OK; }
nsresult nsBaseChannel::ContinueRedirect() { // Backwards compat for non-internal redirects from a HTTP channel. // XXX Is our http channel implementation going to derive from nsBaseChannel? // If not, this code can be removed. if (!(mRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL)) { nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(); if (httpChannel) { nsCOMPtr<nsIHttpEventSink> httpEventSink; GetCallback(httpEventSink); if (httpEventSink) { nsresult rv = httpEventSink->OnRedirect(httpChannel, mRedirectChannel); if (NS_FAILED(rv)) { return rv; } } } } // Make sure to do this _after_ making all the OnChannelRedirect calls mRedirectChannel->SetOriginalURI(OriginalURI()); // If we fail to open the new channel, then we want to leave this channel // unaffected, so we defer tearing down our channel until we have succeeded // with the redirect. if (mOpenRedirectChannel) { nsresult rv = NS_OK; if (mLoadInfo && mLoadInfo->GetEnforceSecurity()) { MOZ_ASSERT(!mListenerContext, "mListenerContext should be null!"); rv = mRedirectChannel->AsyncOpen2(mListener); } else { rv = mRedirectChannel->AsyncOpen(mListener, mListenerContext); } NS_ENSURE_SUCCESS(rv, rv); } mRedirectChannel = nullptr; // close down this channel Cancel(NS_BINDING_REDIRECTED); ChannelDone(); return NS_OK; }
NS_IMETHODIMP nsBaseChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt) { NS_ENSURE_TRUE(mURI, NS_ERROR_NOT_INITIALIZED); NS_ENSURE_TRUE(!mPump, NS_ERROR_IN_PROGRESS); NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED); NS_ENSURE_ARG(listener); // Ensure that this is an allowed port before proceeding. nsresult rv = NS_CheckPortSafety(mURI); if (NS_FAILED(rv)) { mCallbacks = nullptr; return rv; } // Store the listener and context early so that OpenContentStream and the // stream's AsyncWait method (called by AsyncRead) can have access to them // via PushStreamConverter and the StreamListener methods. However, since // this typically introduces a reference cycle between this and the listener, // we need to be sure to break the reference if this method does not succeed. mListener = listener; mListenerContext = ctxt; // This method assigns mPump as a side-effect. We need to clear mPump if // this method fails. rv = BeginPumpingData(); if (NS_FAILED(rv)) { mPump = nullptr; ChannelDone(); mCallbacks = nullptr; return rv; } // At this point, we are going to return success no matter what. mWasOpened = true; SUSPEND_PUMP_FOR_SCOPE(); if (mLoadGroup) mLoadGroup->AddRequest(this, nullptr); ClassifyURI(); return NS_OK; }
void nsBaseChannel::ContinueHandleAsyncRedirect(nsresult result) { mWaitingOnAsyncRedirect = false; if (NS_FAILED(result)) Cancel(result); if (NS_FAILED(result) && mListener) { // Notify our consumer ourselves mListener->OnStartRequest(this, mListenerContext); mListener->OnStopRequest(this, mListenerContext, mStatus); ChannelDone(); } if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, mStatus); // Drop notification callbacks to prevent cycles. mCallbacks = nullptr; CallbacksChanged(); }