mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 07:42:04 +00:00
Bug 561694: Optimize IPDL traffic for necko OnProgress/OnStatus. r=honzab
This commit is contained in:
parent
d5dde90b81
commit
0ffe868d6d
@ -273,66 +273,115 @@ HttpChannelChild::OnStartRequest(const nsHttpResponseHead& responseHead,
|
||||
Cancel(rv);
|
||||
}
|
||||
|
||||
class DataAvailableEvent : public ChannelEvent
|
||||
class TransportAndDataEvent : public ChannelEvent
|
||||
{
|
||||
public:
|
||||
DataAvailableEvent(HttpChannelChild* child,
|
||||
const nsCString& data,
|
||||
const PRUint32& offset,
|
||||
const PRUint32& count)
|
||||
TransportAndDataEvent(HttpChannelChild* child,
|
||||
const nsresult& status,
|
||||
const PRUint64& progress,
|
||||
const PRUint64& progressMax,
|
||||
const nsCString& data,
|
||||
const PRUint32& offset,
|
||||
const PRUint32& count)
|
||||
: mChild(child)
|
||||
, mStatus(status)
|
||||
, mProgress(progress)
|
||||
, mProgressMax(progressMax)
|
||||
, mData(data)
|
||||
, mOffset(offset)
|
||||
, mCount(count) {}
|
||||
|
||||
void Run() { mChild->OnDataAvailable(mData, mOffset, mCount); }
|
||||
void Run() { mChild->OnTransportAndData(mStatus, mProgress, mProgressMax,
|
||||
mData, mOffset, mCount); }
|
||||
private:
|
||||
HttpChannelChild* mChild;
|
||||
nsresult mStatus;
|
||||
PRUint64 mProgress;
|
||||
PRUint64 mProgressMax;
|
||||
nsCString mData;
|
||||
PRUint32 mOffset;
|
||||
PRUint32 mCount;
|
||||
};
|
||||
|
||||
bool
|
||||
HttpChannelChild::RecvOnDataAvailable(const nsCString& data,
|
||||
const PRUint32& offset,
|
||||
const PRUint32& count)
|
||||
bool
|
||||
HttpChannelChild::RecvOnTransportAndData(const nsresult& status,
|
||||
const PRUint64& progress,
|
||||
const PRUint64& progressMax,
|
||||
const nsCString& data,
|
||||
const PRUint32& offset,
|
||||
const PRUint32& count)
|
||||
{
|
||||
if (ShouldEnqueue()) {
|
||||
EnqueueEvent(new DataAvailableEvent(this, data, offset, count));
|
||||
EnqueueEvent(new TransportAndDataEvent(this, status, progress, progressMax,
|
||||
data, offset, count));
|
||||
} else {
|
||||
OnDataAvailable(data, offset, count);
|
||||
OnTransportAndData(status, progress, progressMax, data, offset, count);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
HttpChannelChild::OnDataAvailable(const nsCString& data,
|
||||
const PRUint32& offset,
|
||||
const PRUint32& count)
|
||||
void
|
||||
HttpChannelChild::OnTransportAndData(const nsresult& status,
|
||||
const PRUint64 progress,
|
||||
const PRUint64& progressMax,
|
||||
const nsCString& data,
|
||||
const PRUint32& offset,
|
||||
const PRUint32& count)
|
||||
{
|
||||
LOG(("HttpChannelChild::OnDataAvailable [this=%x]\n", this));
|
||||
LOG(("HttpChannelChild::OnTransportAndData [this=%x]\n", this));
|
||||
|
||||
if (mCanceled)
|
||||
return;
|
||||
|
||||
// cache the progress sink so we don't have to query for it each time.
|
||||
if (!mProgressSink)
|
||||
GetCallback(mProgressSink);
|
||||
|
||||
// Hold queue lock throughout all three calls, else we might process a later
|
||||
// necko msg in between them.
|
||||
AutoEventEnqueuer ensureSerialDispatch(this);
|
||||
|
||||
// block status/progress after Cancel or OnStopRequest has been called,
|
||||
// or if channel has LOAD_BACKGROUND set.
|
||||
// - JDUELL: may not need mStatus/mIsPending checks, given this is always called
|
||||
// during OnDataAvailable, and we've already checked mCanceled. Code
|
||||
// dupe'd from nsHttpChannel
|
||||
if (mProgressSink && NS_SUCCEEDED(mStatus) && mIsPending &&
|
||||
!(mLoadFlags & LOAD_BACKGROUND))
|
||||
{
|
||||
// OnStatus
|
||||
//
|
||||
NS_ASSERTION(status == nsISocketTransport::STATUS_RECEIVING_FROM ||
|
||||
status == nsITransport::STATUS_READING,
|
||||
"unexpected status code");
|
||||
|
||||
nsCAutoString host;
|
||||
mURI->GetHost(host);
|
||||
mProgressSink->OnStatus(this, nsnull, status,
|
||||
NS_ConvertUTF8toUTF16(host).get());
|
||||
// OnProgress
|
||||
//
|
||||
if (progress > 0) {
|
||||
NS_ASSERTION(progress <= progressMax, "unexpected progress values");
|
||||
mProgressSink->OnProgress(this, nsnull, progress, progressMax);
|
||||
}
|
||||
}
|
||||
|
||||
// OnDataAvailable
|
||||
//
|
||||
// NOTE: the OnDataAvailable contract requires the client to read all the data
|
||||
// in the inputstream. This code relies on that ('data' will go away after
|
||||
// this function). Apparently the previous, non-e10s behavior was to actually
|
||||
// support only reading part of the data, allowing later calls to read the
|
||||
// rest.
|
||||
nsCOMPtr<nsIInputStream> stringStream;
|
||||
nsresult rv = NS_NewByteInputStream(getter_AddRefs(stringStream),
|
||||
data.get(),
|
||||
count,
|
||||
NS_ASSIGNMENT_DEPEND);
|
||||
nsresult rv = NS_NewByteInputStream(getter_AddRefs(stringStream), data.get(),
|
||||
count, NS_ASSIGNMENT_DEPEND);
|
||||
if (NS_FAILED(rv)) {
|
||||
Cancel(rv);
|
||||
return;
|
||||
}
|
||||
|
||||
AutoEventEnqueuer ensureSerialDispatch(this);
|
||||
|
||||
rv = mListener->OnDataAvailable(this, mListenerContext,
|
||||
stringStream, offset, count);
|
||||
stringStream->Close();
|
||||
@ -447,7 +496,8 @@ HttpChannelChild::OnProgress(const PRUint64& progress,
|
||||
|
||||
AutoEventEnqueuer ensureSerialDispatch(this);
|
||||
|
||||
// block socket status event after Cancel or OnStopRequest has been called.
|
||||
// block socket status event after Cancel or OnStopRequest has been called,
|
||||
// or if channel has LOAD_BACKGROUND set
|
||||
if (mProgressSink && NS_SUCCEEDED(mStatus) && mIsPending &&
|
||||
!(mLoadFlags & LOAD_BACKGROUND))
|
||||
{
|
||||
@ -462,34 +512,29 @@ class StatusEvent : public ChannelEvent
|
||||
{
|
||||
public:
|
||||
StatusEvent(HttpChannelChild* child,
|
||||
const nsresult& status,
|
||||
const nsString& statusArg)
|
||||
const nsresult& status)
|
||||
: mChild(child)
|
||||
, mStatus(status)
|
||||
, mStatusArg(statusArg) {}
|
||||
, mStatus(status) {}
|
||||
|
||||
void Run() { mChild->OnStatus(mStatus, mStatusArg); }
|
||||
void Run() { mChild->OnStatus(mStatus); }
|
||||
private:
|
||||
HttpChannelChild* mChild;
|
||||
nsresult mStatus;
|
||||
nsString mStatusArg;
|
||||
};
|
||||
|
||||
bool
|
||||
HttpChannelChild::RecvOnStatus(const nsresult& status,
|
||||
const nsString& statusArg)
|
||||
HttpChannelChild::RecvOnStatus(const nsresult& status)
|
||||
{
|
||||
if (ShouldEnqueue()) {
|
||||
EnqueueEvent(new StatusEvent(this, status, statusArg));
|
||||
EnqueueEvent(new StatusEvent(this, status));
|
||||
} else {
|
||||
OnStatus(status, statusArg);
|
||||
OnStatus(status);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
HttpChannelChild::OnStatus(const nsresult& status,
|
||||
const nsString& statusArg)
|
||||
HttpChannelChild::OnStatus(const nsresult& status)
|
||||
{
|
||||
LOG(("HttpChannelChild::OnStatus [this=%p status=%x]\n", this, status));
|
||||
|
||||
@ -501,12 +546,16 @@ HttpChannelChild::OnStatus(const nsresult& status,
|
||||
GetCallback(mProgressSink);
|
||||
|
||||
AutoEventEnqueuer ensureSerialDispatch(this);
|
||||
|
||||
// block socket status event after Cancel or OnStopRequest has been called.
|
||||
|
||||
// block socket status event after Cancel or OnStopRequest has been called,
|
||||
// or if channel has LOAD_BACKGROUND set
|
||||
if (mProgressSink && NS_SUCCEEDED(mStatus) && mIsPending &&
|
||||
!(mLoadFlags & LOAD_BACKGROUND))
|
||||
{
|
||||
mProgressSink->OnStatus(this, nsnull, status, statusArg.get());
|
||||
nsCAutoString host;
|
||||
mURI->GetHost(host);
|
||||
mProgressSink->OnStatus(this, nsnull, status,
|
||||
NS_ConvertUTF8toUTF16(host).get());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,12 +131,15 @@ protected:
|
||||
const PRUint32& cacheExpirationTime,
|
||||
const nsCString& cachedCharset,
|
||||
const nsCString& securityInfoSerialization);
|
||||
bool RecvOnDataAvailable(const nsCString& data,
|
||||
const PRUint32& offset,
|
||||
const PRUint32& count);
|
||||
bool RecvOnTransportAndData(const nsresult& status,
|
||||
const PRUint64& progress,
|
||||
const PRUint64& progressMax,
|
||||
const nsCString& data,
|
||||
const PRUint32& offset,
|
||||
const PRUint32& count);
|
||||
bool RecvOnStopRequest(const nsresult& statusCode);
|
||||
bool RecvOnProgress(const PRUint64& progress, const PRUint64& progressMax);
|
||||
bool RecvOnStatus(const nsresult& status, const nsString& statusArg);
|
||||
bool RecvOnStatus(const nsresult& status);
|
||||
bool RecvCancelEarly(const nsresult& status);
|
||||
bool RecvRedirect1Begin(const PRUint32& newChannel,
|
||||
const URI& newURI,
|
||||
@ -169,19 +172,22 @@ private:
|
||||
bool mKeptAlive;
|
||||
|
||||
void 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);
|
||||
void OnDataAvailable(const nsCString& data,
|
||||
const PRUint32& offset,
|
||||
const PRUint32& count);
|
||||
const PRBool& useResponseHead,
|
||||
const RequestHeaderTuples& requestHeaders,
|
||||
const PRBool& isFromCache,
|
||||
const PRBool& cacheEntryAvailable,
|
||||
const PRUint32& cacheExpirationTime,
|
||||
const nsCString& cachedCharset,
|
||||
const nsCString& securityInfoSerialization);
|
||||
void OnTransportAndData(const nsresult& status,
|
||||
const PRUint64 progress,
|
||||
const PRUint64& progressMax,
|
||||
const nsCString& data,
|
||||
const PRUint32& offset,
|
||||
const PRUint32& count);
|
||||
void OnStopRequest(const nsresult& statusCode);
|
||||
void OnProgress(const PRUint64& progress, const PRUint64& progressMax);
|
||||
void OnStatus(const nsresult& status, const nsString& statusArg);
|
||||
void OnStatus(const nsresult& status);
|
||||
void OnCancel(const nsresult& status);
|
||||
void Redirect1Begin(const PRUint32& newChannelId,
|
||||
const URI& newUri,
|
||||
@ -192,7 +198,7 @@ private:
|
||||
|
||||
friend class StartRequestEvent;
|
||||
friend class StopRequestEvent;
|
||||
friend class DataAvailableEvent;
|
||||
friend class TransportAndDataEvent;
|
||||
friend class ProgressEvent;
|
||||
friend class StatusEvent;
|
||||
friend class CancelEvent;
|
||||
|
@ -62,7 +62,10 @@ namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
HttpChannelParent::HttpChannelParent(PBrowserParent* iframeEmbedding)
|
||||
: mIPCClosed(false)
|
||||
: mIPCClosed(false)
|
||||
, mStoredStatus(0)
|
||||
, mStoredProgress(0)
|
||||
, mStoredProgressMax(0)
|
||||
{
|
||||
// Ensure gHttpHandler is initialized: we need the atom table up and running.
|
||||
nsIHttpProtocolHandler* handler;
|
||||
@ -465,15 +468,21 @@ HttpChannelParent::OnDataAvailable(nsIRequest *aRequest,
|
||||
PRUint32 aCount)
|
||||
{
|
||||
LOG(("HttpChannelParent::OnDataAvailable [this=%x]\n", this));
|
||||
|
||||
|
||||
nsCString data;
|
||||
nsresult rv = NS_ReadInputStreamToString(aInputStream, data, aCount);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if (mIPCClosed || !SendOnDataAvailable(data, aOffset, aCount))
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
@ -487,8 +496,21 @@ HttpChannelParent::OnProgress(nsIRequest *aRequest,
|
||||
PRUint64 aProgress,
|
||||
PRUint64 aProgressMax)
|
||||
{
|
||||
if (mIPCClosed || !SendOnProgress(aProgress, aProgressMax))
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
// OnStatus has always just set mStoredStatus. If it indicates this precedes
|
||||
// OnDataAvailable, store and ODA will send to child.
|
||||
if (mStoredStatus == nsISocketTransport::STATUS_RECEIVING_FROM ||
|
||||
mStoredStatus == nsITransport::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 == nsISocketTransport::STATUS_SENDING_TO)
|
||||
if (mIPCClosed || !SendOnProgress(aProgress, aProgressMax))
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -498,7 +520,15 @@ HttpChannelParent::OnStatus(nsIRequest *aRequest,
|
||||
nsresult aStatus,
|
||||
const PRUnichar *aStatusArg)
|
||||
{
|
||||
if (mIPCClosed || !SendOnStatus(aStatus, nsString(aStatusArg)))
|
||||
// If this precedes OnDataAvailable, store and ODA will send to child.
|
||||
if (aStatus == nsISocketTransport::STATUS_RECEIVING_FROM ||
|
||||
aStatus == nsITransport::STATUS_READING)
|
||||
{
|
||||
mStoredStatus = aStatus;
|
||||
return NS_OK;
|
||||
}
|
||||
// Otherwise, send to child now
|
||||
if (mIPCClosed || !SendOnStatus(aStatus))
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -124,6 +124,12 @@ private:
|
||||
|
||||
nsCOMPtr<nsIChannel> mRedirectChannel;
|
||||
nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
|
||||
|
||||
// state for combining OnStatus/OnProgress with OnDataAvailable
|
||||
// into one IPDL call to child.
|
||||
nsresult mStoredStatus;
|
||||
PRUint64 mStoredProgress;
|
||||
PRUint64 mStoredProgressMax;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
|
@ -81,6 +81,8 @@ parent:
|
||||
bool chooseApplicationCache,
|
||||
nsCString appCacheClientID);
|
||||
|
||||
// Used to connect redirected-to channel on the parent with redirected-to
|
||||
// channel on the child.
|
||||
ConnectChannel(PRUint32 channelId);
|
||||
|
||||
SetPriority(PRUint16 priority);
|
||||
@ -131,15 +133,20 @@ child:
|
||||
nsCString cachedCharset,
|
||||
nsCString securityInfoSerialization);
|
||||
|
||||
OnDataAvailable(nsCString data,
|
||||
PRUint32 offset,
|
||||
PRUint32 count);
|
||||
// Combines a single OnDataAvailable and its associated OnProgress &
|
||||
// OnStatus calls into one IPDL message
|
||||
OnTransportAndData(nsresult status,
|
||||
PRUint64 progress,
|
||||
PRUint64 progressMax,
|
||||
nsCString data,
|
||||
PRUint32 offset,
|
||||
PRUint32 count);
|
||||
|
||||
OnStopRequest(nsresult statusCode);
|
||||
|
||||
OnProgress(PRUint64 progress, PRUint64 progressMax);
|
||||
|
||||
OnStatus(nsresult status, nsString statusArg);
|
||||
OnStatus(nsresult status);
|
||||
|
||||
// Used to cancel child channel if we hit errors during creating and
|
||||
// AsyncOpen of nsHttpChannel on the parent.
|
||||
|
Loading…
Reference in New Issue
Block a user