NS_IMETHODIMP nsBaseChannel::GetOriginalURI(nsIURI **aURI) { *aURI = OriginalURI(); NS_ADDREF(*aURI); 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; }
nsresult nsBaseChannel::Redirect(nsIChannel *newChannel, PRUint32 redirectFlags) { SUSPEND_PUMP_FOR_SCOPE(); // Transfer properties newChannel->SetOriginalURI(OriginalURI()); newChannel->SetLoadGroup(mLoadGroup); newChannel->SetNotificationCallbacks(mCallbacks); newChannel->SetLoadFlags(mLoadFlags | LOAD_REPLACE); nsCOMPtr<nsIWritablePropertyBag> bag = ::do_QueryInterface(newChannel); if (bag) mPropertyHash.EnumerateRead(CopyProperties, bag.get()); // Notify consumer, giving chance to cancel redirect. For backwards compat, // we support nsIHttpEventSink if we are an HTTP channel and if this is not // an internal redirect. // Global observers. These come first so that other observers don't see // redirects that get aborted for security reasons anyway. NS_ASSERTION(gIOService, "Must have an IO service"); nsresult rv = gIOService->OnChannelRedirect(this, newChannel, redirectFlags); if (NS_FAILED(rv)) return rv; // Backwards compat for non-internal redirects from a HTTP channel. if (!(redirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL)) { nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(); if (httpChannel) { nsCOMPtr<nsIHttpEventSink> httpEventSink; GetCallback(httpEventSink); if (httpEventSink) { rv = httpEventSink->OnRedirect(httpChannel, newChannel); if (NS_FAILED(rv)) return rv; } } } nsCOMPtr<nsIChannelEventSink> channelEventSink; // Give our consumer a chance to observe/block this redirect. GetCallback(channelEventSink); if (channelEventSink) { rv = channelEventSink->OnChannelRedirect(this, newChannel, redirectFlags); if (NS_FAILED(rv)) return rv; } // 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. rv = newChannel->AsyncOpen(mListener, mListenerContext); if (NS_FAILED(rv)) return rv; // close down this channel Cancel(NS_BINDING_REDIRECTED); mListener = nsnull; mListenerContext = nsnull; return NS_OK; }