mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
c4c18521be
This is probably the worst patch that I have ever written! We add a setPrivate method to nsIPrivateBrowsingChannel which will be implemented by channels who care about private browsing. This allows the client to explicitly override the private bit on the channel. NS_UsePrivateBrowsing is also taught about this override bit using the internal nsIPrivateBrowsingChannel::IsPrivateModeOverriden API. This patch implements the new API for HTTP, FTP and wyciwyg channels. This also modifies the IPC implementations of these channels to correctly transfer that bit to the parent process if it has been set in the child process channel.
613 lines
21 KiB
C++
613 lines
21 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set sw=2 ts=8 et tw=80 : */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "mozilla/net/HttpChannelParent.h"
|
|
#include "mozilla/dom/TabParent.h"
|
|
#include "mozilla/net/NeckoParent.h"
|
|
#include "mozilla/unused.h"
|
|
#include "HttpChannelParentListener.h"
|
|
#include "nsHttpHandler.h"
|
|
#include "nsNetUtil.h"
|
|
#include "nsISupportsPriority.h"
|
|
#include "nsIAuthPromptProvider.h"
|
|
#include "nsIDocShellTreeItem.h"
|
|
#include "nsIBadCertListener2.h"
|
|
#include "nsICacheEntryDescriptor.h"
|
|
#include "nsSerializationHelper.h"
|
|
#include "nsISerializable.h"
|
|
#include "nsIAssociatedContentSecurity.h"
|
|
#include "nsIApplicationCacheService.h"
|
|
#include "nsIOfflineCacheUpdate.h"
|
|
#include "nsIRedirectChannelRegistrar.h"
|
|
#include "mozilla/LoadContext.h"
|
|
#include "prinit.h"
|
|
#include "mozilla/ipc/InputStreamUtils.h"
|
|
#include "mozilla/ipc/URIUtils.h"
|
|
|
|
using namespace mozilla::dom;
|
|
using namespace mozilla::ipc;
|
|
|
|
namespace mozilla {
|
|
namespace net {
|
|
|
|
HttpChannelParent::HttpChannelParent(PBrowserParent* iframeEmbedding)
|
|
: mIPCClosed(false)
|
|
, mStoredStatus(NS_OK)
|
|
, mStoredProgress(0)
|
|
, mStoredProgressMax(0)
|
|
, mSentRedirect1Begin(false)
|
|
, mSentRedirect1BeginFailed(false)
|
|
, mReceivedRedirect2Verify(false)
|
|
{
|
|
// Ensure gHttpHandler is initialized: we need the atom table up and running.
|
|
nsIHttpProtocolHandler* handler;
|
|
CallGetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &handler);
|
|
NS_ASSERTION(handler, "no http handler");
|
|
|
|
mTabParent = static_cast<mozilla::dom::TabParent*>(iframeEmbedding);
|
|
}
|
|
|
|
HttpChannelParent::~HttpChannelParent()
|
|
{
|
|
gHttpHandler->Release();
|
|
}
|
|
|
|
void
|
|
HttpChannelParent::ActorDestroy(ActorDestroyReason why)
|
|
{
|
|
// We may still have refcount>0 if nsHttpChannel hasn't called OnStopRequest
|
|
// yet, but child process has crashed. We must not try to send any more msgs
|
|
// to child, or IPDL will kill chrome process, too.
|
|
mIPCClosed = true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// HttpChannelParent::nsISupports
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NS_IMPL_ISUPPORTS6(HttpChannelParent,
|
|
nsIInterfaceRequestor,
|
|
nsIProgressEventSink,
|
|
nsIRequestObserver,
|
|
nsIStreamListener,
|
|
nsIParentChannel,
|
|
nsIParentRedirectingChannel)
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// HttpChannelParent::nsIInterfaceRequestor
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NS_IMETHODIMP
|
|
HttpChannelParent::GetInterface(const nsIID& aIID, void **result)
|
|
{
|
|
if (aIID.Equals(NS_GET_IID(nsIAuthPromptProvider)) ||
|
|
aIID.Equals(NS_GET_IID(nsISecureBrowserUI))) {
|
|
if (!mTabParent)
|
|
return NS_NOINTERFACE;
|
|
|
|
return mTabParent->QueryInterface(aIID, result);
|
|
}
|
|
|
|
// Only support nsILoadContext if child channel's callbacks did too
|
|
if (aIID.Equals(NS_GET_IID(nsILoadContext)) && mLoadContext) {
|
|
NS_ADDREF(mLoadContext);
|
|
*result = static_cast<nsILoadContext*>(mLoadContext);
|
|
return NS_OK;
|
|
}
|
|
|
|
return QueryInterface(aIID, result);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// HttpChannelParent::PHttpChannelParent
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool
|
|
HttpChannelParent::RecvAsyncOpen(const URIParams& aURI,
|
|
const OptionalURIParams& aOriginalURI,
|
|
const OptionalURIParams& aDocURI,
|
|
const OptionalURIParams& aReferrerURI,
|
|
const uint32_t& loadFlags,
|
|
const RequestHeaderTuples& requestHeaders,
|
|
const nsHttpAtom& requestMethod,
|
|
const OptionalInputStreamParams& uploadStream,
|
|
const bool& uploadStreamHasHeaders,
|
|
const uint16_t& priority,
|
|
const uint8_t& redirectionLimit,
|
|
const bool& allowPipelining,
|
|
const bool& forceAllowThirdPartyCookie,
|
|
const bool& doResumeAt,
|
|
const uint64_t& startPos,
|
|
const nsCString& entityID,
|
|
const bool& chooseApplicationCache,
|
|
const nsCString& appCacheClientID,
|
|
const bool& allowSpdy,
|
|
const IPC::SerializedLoadContext& loadContext)
|
|
{
|
|
nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
|
|
nsCOMPtr<nsIURI> originalUri = DeserializeURI(aOriginalURI);
|
|
nsCOMPtr<nsIURI> docUri = DeserializeURI(aDocURI);
|
|
nsCOMPtr<nsIURI> referrerUri = DeserializeURI(aReferrerURI);
|
|
|
|
nsCString uriSpec;
|
|
uri->GetSpec(uriSpec);
|
|
LOG(("HttpChannelParent RecvAsyncOpen [this=%x uri=%s]\n",
|
|
this, uriSpec.get()));
|
|
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIIOService> ios(do_GetIOService(&rv));
|
|
if (NS_FAILED(rv))
|
|
return SendFailedAsyncOpen(rv);
|
|
|
|
rv = NS_NewChannel(getter_AddRefs(mChannel), uri, ios, nullptr, nullptr, loadFlags);
|
|
if (NS_FAILED(rv))
|
|
return SendFailedAsyncOpen(rv);
|
|
|
|
if (loadContext.IsNotNull()) {
|
|
if (mTabParent)
|
|
mLoadContext = new LoadContext(loadContext, mTabParent->GetOwnerElement());
|
|
else
|
|
mLoadContext = new LoadContext(loadContext);
|
|
} else if (loadContext.IsPrivateBitValid()) {
|
|
nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel = do_QueryInterface(mChannel);
|
|
if (pbChannel)
|
|
pbChannel->SetPrivate(loadContext.mUsePrivateBrowsing);
|
|
}
|
|
|
|
nsHttpChannel *httpChan = static_cast<nsHttpChannel *>(mChannel.get());
|
|
|
|
if (doResumeAt)
|
|
httpChan->ResumeAt(startPos, entityID);
|
|
|
|
if (originalUri)
|
|
httpChan->SetOriginalURI(originalUri);
|
|
if (docUri)
|
|
httpChan->SetDocumentURI(docUri);
|
|
if (referrerUri)
|
|
httpChan->SetReferrerInternal(referrerUri);
|
|
if (loadFlags != nsIRequest::LOAD_NORMAL)
|
|
httpChan->SetLoadFlags(loadFlags);
|
|
|
|
for (uint32_t i = 0; i < requestHeaders.Length(); i++) {
|
|
httpChan->SetRequestHeader(requestHeaders[i].mHeader,
|
|
requestHeaders[i].mValue,
|
|
requestHeaders[i].mMerge);
|
|
}
|
|
|
|
nsRefPtr<HttpChannelParentListener> channelListener =
|
|
new HttpChannelParentListener(this);
|
|
|
|
httpChan->SetNotificationCallbacks(channelListener);
|
|
|
|
httpChan->SetRequestMethod(nsDependentCString(requestMethod.get()));
|
|
|
|
nsCOMPtr<nsIInputStream> stream = DeserializeInputStream(uploadStream);
|
|
if (stream) {
|
|
httpChan->InternalSetUploadStream(stream);
|
|
httpChan->SetUploadStreamHasHeaders(uploadStreamHasHeaders);
|
|
}
|
|
|
|
if (priority != nsISupportsPriority::PRIORITY_NORMAL)
|
|
httpChan->SetPriority(priority);
|
|
httpChan->SetRedirectionLimit(redirectionLimit);
|
|
httpChan->SetAllowPipelining(allowPipelining);
|
|
httpChan->SetForceAllowThirdPartyCookie(forceAllowThirdPartyCookie);
|
|
httpChan->SetAllowSpdy(allowSpdy);
|
|
|
|
nsCOMPtr<nsIApplicationCacheChannel> appCacheChan =
|
|
do_QueryInterface(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 succefully 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) {
|
|
nsCOMPtr<nsIOfflineCacheUpdateService> offlineUpdateService =
|
|
do_GetService("@mozilla.org/offlinecacheupdate-service;1", &rv);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
rv = offlineUpdateService->OfflineAppAllowedForURI(uri,
|
|
nullptr,
|
|
&setChooseApplicationCache);
|
|
|
|
if (setChooseApplicationCache && NS_SUCCEEDED(rv))
|
|
appCacheChan->SetChooseApplicationCache(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
rv = httpChan->AsyncOpen(channelListener, nullptr);
|
|
if (NS_FAILED(rv))
|
|
return SendFailedAsyncOpen(rv);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
HttpChannelParent::RecvConnectChannel(const uint32_t& channelId)
|
|
{
|
|
nsresult rv;
|
|
|
|
LOG(("Looking for a registered channel [this=%p, id=%d]", this, channelId));
|
|
rv = NS_LinkRedirectChannels(channelId, this, getter_AddRefs(mChannel));
|
|
LOG((" found channel %p, rv=%08x", mChannel.get(), rv));
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
HttpChannelParent::RecvSetPriority(const uint16_t& priority)
|
|
{
|
|
if (mChannel) {
|
|
nsHttpChannel *httpChan = static_cast<nsHttpChannel *>(mChannel.get());
|
|
httpChan->SetPriority(priority);
|
|
}
|
|
|
|
nsCOMPtr<nsISupportsPriority> priorityRedirectChannel =
|
|
do_QueryInterface(mRedirectChannel);
|
|
if (priorityRedirectChannel)
|
|
priorityRedirectChannel->SetPriority(priority);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
HttpChannelParent::RecvSuspend()
|
|
{
|
|
if (mChannel) {
|
|
mChannel->Suspend();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
HttpChannelParent::RecvResume()
|
|
{
|
|
if (mChannel) {
|
|
mChannel->Resume();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
HttpChannelParent::RecvCancel(const nsresult& status)
|
|
{
|
|
// May receive cancel before channel has been constructed!
|
|
if (mChannel) {
|
|
nsHttpChannel *httpChan = static_cast<nsHttpChannel *>(mChannel.get());
|
|
httpChan->Cancel(status);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
bool
|
|
HttpChannelParent::RecvSetCacheTokenCachedCharset(const nsCString& charset)
|
|
{
|
|
if (mCacheDescriptor)
|
|
mCacheDescriptor->SetMetaDataElement("charset", charset.get());
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
HttpChannelParent::RecvUpdateAssociatedContentSecurity(const int32_t& high,
|
|
const int32_t& low,
|
|
const int32_t& broken,
|
|
const int32_t& no)
|
|
{
|
|
if (mAssociatedContentSecurity) {
|
|
mAssociatedContentSecurity->SetCountSubRequestsHighSecurity(high);
|
|
mAssociatedContentSecurity->SetCountSubRequestsLowSecurity(low);
|
|
mAssociatedContentSecurity->SetCountSubRequestsBrokenSecurity(broken);
|
|
mAssociatedContentSecurity->SetCountSubRequestsNoSecurity(no);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
HttpChannelParent::RecvRedirect2Verify(const nsresult& result,
|
|
const RequestHeaderTuples& changedHeaders)
|
|
{
|
|
if (NS_SUCCEEDED(result)) {
|
|
nsCOMPtr<nsIHttpChannel> newHttpChannel =
|
|
do_QueryInterface(mRedirectChannel);
|
|
|
|
if (newHttpChannel) {
|
|
for (uint32_t 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::RecvDocumentChannelCleanup()
|
|
{
|
|
// From now on only using mAssociatedContentSecurity. Free everything else.
|
|
mChannel = 0; // Reclaim some memory sooner.
|
|
mCacheDescriptor = 0; // Else we'll block other channels reading same URI
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
HttpChannelParent::RecvMarkOfflineCacheEntryAsForeign()
|
|
{
|
|
if (mOfflineForeignMarker) {
|
|
mOfflineForeignMarker->MarkAsForeign();
|
|
mOfflineForeignMarker = 0;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// HttpChannelParent::nsIRequestObserver
|
|
//-----------------------------------------------------------------------------
|
|
|
|
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();
|
|
bool isFromCache = false;
|
|
chan->IsFromCache(&isFromCache);
|
|
uint32_t expirationTime = nsICache::NO_EXPIRATION_TIME;
|
|
chan->GetCacheTokenExpirationTime(&expirationTime);
|
|
nsCString cachedCharset;
|
|
chan->GetCacheTokenCachedCharset(cachedCharset);
|
|
|
|
bool loadedFromApplicationCache;
|
|
chan->GetLoadedFromApplicationCache(&loadedFromApplicationCache);
|
|
if (loadedFromApplicationCache) {
|
|
mOfflineForeignMarker = chan->GetOfflineCacheEntryAsForeignMarker();
|
|
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(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) {
|
|
mAssociatedContentSecurity = do_QueryInterface(secInfoSupp);
|
|
nsCOMPtr<nsISerializable> secInfoSer = do_QueryInterface(secInfoSupp);
|
|
if (secInfoSer)
|
|
NS_SerializeToString(secInfoSer, secInfoSerialization);
|
|
}
|
|
|
|
nsHttpChannel *httpChan = static_cast<nsHttpChannel *>(mChannel.get());
|
|
if (mIPCClosed ||
|
|
!SendOnStartRequest(responseHead ? *responseHead : nsHttpResponseHead(),
|
|
!!responseHead,
|
|
requestHead->Headers(),
|
|
isFromCache,
|
|
mCacheDescriptor ? true : false,
|
|
expirationTime, cachedCharset, secInfoSerialization,
|
|
httpChan->GetSelfAddr(), httpChan->GetPeerAddr()))
|
|
{
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
HttpChannelParent::OnStopRequest(nsIRequest *aRequest,
|
|
nsISupports *aContext,
|
|
nsresult aStatusCode)
|
|
{
|
|
LOG(("HttpChannelParent::OnStopRequest: [this=%x status=%ul]\n",
|
|
this, aStatusCode));
|
|
|
|
if (mIPCClosed || !SendOnStopRequest(aStatusCode))
|
|
return NS_ERROR_UNEXPECTED;
|
|
return NS_OK;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// HttpChannelParent::nsIStreamListener
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NS_IMETHODIMP
|
|
HttpChannelParent::OnDataAvailable(nsIRequest *aRequest,
|
|
nsISupports *aContext,
|
|
nsIInputStream *aInputStream,
|
|
uint64_t aOffset,
|
|
uint32_t aCount)
|
|
{
|
|
LOG(("HttpChannelParent::OnDataAvailable [this=%x]\n", this));
|
|
|
|
nsCString data;
|
|
nsresult rv = NS_ReadInputStreamToString(aInputStream, data, aCount);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
// OnDataAvailable is always preceded by OnStatus/OnProgress calls that set
|
|
// mStoredStatus/mStoredProgress(Max) to appropriate values, unless
|
|
// LOAD_BACKGROUND set. In that case, they'll have garbage values, but
|
|
// child doesn't use them.
|
|
if (mIPCClosed || !SendOnTransportAndData(mStoredStatus, mStoredProgress,
|
|
mStoredProgressMax, data, aOffset,
|
|
aCount)) {
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// HttpChannelParent::nsIProgressEventSink
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NS_IMETHODIMP
|
|
HttpChannelParent::OnProgress(nsIRequest *aRequest,
|
|
nsISupports *aContext,
|
|
uint64_t aProgress,
|
|
uint64_t aProgressMax)
|
|
{
|
|
// OnStatus has always just set mStoredStatus. If it indicates this precedes
|
|
// OnDataAvailable, store and ODA will send to child.
|
|
if (mStoredStatus == NS_NET_STATUS_RECEIVING_FROM ||
|
|
mStoredStatus == NS_NET_STATUS_READING)
|
|
{
|
|
mStoredProgress = aProgress;
|
|
mStoredProgressMax = aProgressMax;
|
|
} else {
|
|
// Send to child now. The only case I've observed that this handles (i.e.
|
|
// non-ODA status with progress > 0) is data upload progress notification
|
|
// (status == NS_NET_STATUS_SENDING_TO)
|
|
if (mIPCClosed || !SendOnProgress(aProgress, aProgressMax))
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
HttpChannelParent::OnStatus(nsIRequest *aRequest,
|
|
nsISupports *aContext,
|
|
nsresult aStatus,
|
|
const PRUnichar *aStatusArg)
|
|
{
|
|
// If this precedes OnDataAvailable, store and ODA will send to child.
|
|
if (aStatus == NS_NET_STATUS_RECEIVING_FROM ||
|
|
aStatus == NS_NET_STATUS_READING)
|
|
{
|
|
mStoredStatus = aStatus;
|
|
return NS_OK;
|
|
}
|
|
// Otherwise, send to child now
|
|
if (mIPCClosed || !SendOnStatus(aStatus))
|
|
return NS_ERROR_UNEXPECTED;
|
|
return NS_OK;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// HttpChannelParent::nsIParentChannel
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NS_IMETHODIMP
|
|
HttpChannelParent::Delete()
|
|
{
|
|
if (!mIPCClosed)
|
|
unused << SendDeleteSelf();
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// HttpChannelParent::nsIParentRedirectingChannel
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NS_IMETHODIMP
|
|
HttpChannelParent::StartRedirect(uint32_t newChannelId,
|
|
nsIChannel* newChannel,
|
|
uint32_t redirectFlags,
|
|
nsIAsyncVerifyRedirectCallback* callback)
|
|
{
|
|
if (mIPCClosed)
|
|
return NS_BINDING_ABORTED;
|
|
|
|
nsCOMPtr<nsIURI> newURI;
|
|
newChannel->GetURI(getter_AddRefs(newURI));
|
|
|
|
URIParams uriParams;
|
|
SerializeURI(newURI, uriParams);
|
|
|
|
nsHttpChannel *httpChan = static_cast<nsHttpChannel *>(mChannel.get());
|
|
nsHttpResponseHead *responseHead = httpChan->GetResponseHead();
|
|
bool result = SendRedirect1Begin(newChannelId, uriParams, redirectFlags,
|
|
responseHead ? *responseHead
|
|
: nsHttpResponseHead());
|
|
if (!result) {
|
|
// Bug 621446 investigation
|
|
mSentRedirect1BeginFailed = true;
|
|
return NS_BINDING_ABORTED;
|
|
}
|
|
|
|
// Bug 621446 investigation
|
|
mSentRedirect1Begin = true;
|
|
|
|
// Result is handled in RecvRedirect2Verify above
|
|
|
|
mRedirectChannel = newChannel;
|
|
mRedirectCallback = callback;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
HttpChannelParent::CompleteRedirect(bool succeeded)
|
|
{
|
|
if (succeeded && !mIPCClosed) {
|
|
// TODO: check return value: assume child dead if failed
|
|
unused << SendRedirect3Complete();
|
|
}
|
|
|
|
mRedirectChannel = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
}} // mozilla::net
|