From c0aaec5ffa3c09880b0d775ff47ebc9c3a26088a Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Fri, 19 Nov 2010 16:12:45 -0500 Subject: [PATCH] Bug 605327 - Add proper cancellation to e10s wyciwyg channels. r=dwitte a=blocking-fennec --- netwerk/protocol/wyciwyg/PWyciwygChannel.ipdl | 3 + .../protocol/wyciwyg/WyciwygChannelChild.cpp | 81 ++++++++++++++++--- .../protocol/wyciwyg/WyciwygChannelChild.h | 4 + .../protocol/wyciwyg/WyciwygChannelParent.cpp | 24 ++++-- .../protocol/wyciwyg/WyciwygChannelParent.h | 1 + 5 files changed, 94 insertions(+), 19 deletions(-) diff --git a/netwerk/protocol/wyciwyg/PWyciwygChannel.ipdl b/netwerk/protocol/wyciwyg/PWyciwygChannel.ipdl index 44e37003177..1c51eb1fb1f 100644 --- a/netwerk/protocol/wyciwyg/PWyciwygChannel.ipdl +++ b/netwerk/protocol/wyciwyg/PWyciwygChannel.ipdl @@ -61,6 +61,7 @@ parent: CloseCacheEntry(nsresult reason); SetCharsetAndSource(PRInt32 source, nsCString charset); SetSecurityInfo(nsCString securityInfo); + Cancel(nsresult status); child: OnStartRequest(nsresult statusCode, @@ -73,6 +74,8 @@ child: PRUint32 offset); OnStopRequest(nsresult statusCode); + + CancelEarly(nsresult statusCode); }; diff --git a/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp b/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp index 291b8db55e6..1ca78209d8e 100644 --- a/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp +++ b/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp @@ -60,6 +60,7 @@ WyciwygChannelChild::WyciwygChannelChild() : ChannelEventQueue(this) , mStatus(NS_OK) , mIsPending(PR_FALSE) + , mCanceled(false) , mLoadFlags(LOAD_NORMAL) , mContentLength(-1) , mCharsetSource(kCharsetUninitialized) @@ -169,12 +170,8 @@ WyciwygChannelChild::OnStartRequest(const nsresult& statusCode, AutoEventEnqueuer ensureSerialDispatch(this); nsresult rv = mListener->OnStartRequest(this, mListenerContext); - if (NS_FAILED(rv)) { - // TODO: Cancel request: - // - Send Cancel msg to parent - // - drop any in flight OnDataAvail msgs we receive - // - make sure we do call OnStopRequest eventually - } + if (NS_FAILED(rv)) + Cancel(rv); } class WyciwygDataAvailableEvent : public ChannelEvent @@ -209,6 +206,9 @@ WyciwygChannelChild::OnDataAvailable(const nsCString& data, { LOG(("WyciwygChannelChild::RecvOnDataAvailable [this=%x]\n", this)); + if (mCanceled) + return; + mState = WCC_ONDATA; // NOTE: the OnDataAvailable contract requires the client to read all the data @@ -222,16 +222,16 @@ WyciwygChannelChild::OnDataAvailable(const nsCString& data, data.Length(), NS_ASSIGNMENT_DEPEND); if (NS_FAILED(rv)) { - // TODO: what to do here? Cancel request? Very unlikely to fail. + Cancel(rv); + return; } AutoEventEnqueuer ensureSerialDispatch(this); rv = mListener->OnDataAvailable(this, mListenerContext, stringStream, offset, data.Length()); - if (NS_FAILED(rv)) { - // TODO: Cancel request: see notes in OnStartRequest - } + if (NS_FAILED(rv)) + Cancel(rv); if (mProgressSink && NS_SUCCEEDED(rv) && !(mLoadFlags & LOAD_BACKGROUND)) mProgressSink->OnProgress(this, nsnull, PRUint64(offset + data.Length()), @@ -274,7 +274,9 @@ WyciwygChannelChild::OnStopRequest(const nsresult& statusCode) mState = WCC_ONSTOP; mIsPending = PR_FALSE; - mStatus = statusCode; + + if (!mCanceled) + mStatus = statusCode; mListener->OnStopRequest(this, mListenerContext, statusCode); @@ -292,6 +294,54 @@ WyciwygChannelChild::OnStopRequest(const nsresult& statusCode) PWyciwygChannelChild::Send__delete__(this); } +class WyciwygCancelEvent : public ChannelEvent +{ + public: + WyciwygCancelEvent(WyciwygChannelChild* child, const nsresult& status) + : mChild(child) + , mStatus(status) {} + + void Run() { mChild->CancelEarly(mStatus); } + private: + WyciwygChannelChild* mChild; + nsresult mStatus; +}; + +bool +WyciwygChannelChild::RecvCancelEarly(const nsresult& statusCode) +{ + if (ShouldEnqueue()) { + EnqueueEvent(new WyciwygCancelEvent(this, statusCode)); + } else { + CancelEarly(statusCode); + } + return true; +} + +void WyciwygChannelChild::CancelEarly(const nsresult& statusCode) +{ + LOG(("WyciwygChannelChild::CancelEarly [this=%x]\n", this)); + + if (mCanceled) + return; + + mCanceled = true; + mStatus = statusCode; + + mIsPending = false; + if (mLoadGroup) + mLoadGroup->RemoveRequest(this, nsnull, mStatus); + + if (mListener) { + mListener->OnStartRequest(this, mListenerContext); + mListener->OnStopRequest(this, mListenerContext, mStatus); + } + mListener = nsnull; + mListenerContext = nsnull; + + if (mIPCOpen) + PWyciwygChannelChild::Send__delete__(this); +} //----------------------------------------------------------------------------- // nsIRequest @@ -324,7 +374,14 @@ WyciwygChannelChild::GetStatus(nsresult *aStatus) NS_IMETHODIMP WyciwygChannelChild::Cancel(nsresult aStatus) { - return NS_ERROR_NOT_IMPLEMENTED; + if (mCanceled) + return NS_OK; + + mCanceled = true; + mStatus = aStatus; + if (mIPCOpen) + SendCancel(aStatus); + return NS_OK; } /* void suspend (); */ diff --git a/netwerk/protocol/wyciwyg/WyciwygChannelChild.h b/netwerk/protocol/wyciwyg/WyciwygChannelChild.h index a4eeadbb612..e44a69f0daa 100644 --- a/netwerk/protocol/wyciwyg/WyciwygChannelChild.h +++ b/netwerk/protocol/wyciwyg/WyciwygChannelChild.h @@ -94,6 +94,7 @@ protected: bool RecvOnDataAvailable(const nsCString& data, const PRUint32& offset); bool RecvOnStopRequest(const nsresult& statusCode); + bool RecvCancelEarly(const nsresult& statusCode); void OnStartRequest(const nsresult& statusCode, const PRInt32& contentLength, @@ -103,10 +104,12 @@ protected: void OnDataAvailable(const nsCString& data, const PRUint32& offset); void OnStopRequest(const nsresult& statusCode); + void CancelEarly(const nsresult& statusCode); private: nsresult mStatus; PRBool mIsPending; + bool mCanceled; PRUint32 mLoadFlags; PRInt32 mContentLength; PRInt32 mCharsetSource; @@ -129,6 +132,7 @@ private: friend class WyciwygStartRequestEvent; friend class WyciwygDataAvailableEvent; friend class WyciwygStopRequestEvent; + friend class WyciwygCancelEvent; }; inline bool diff --git a/netwerk/protocol/wyciwyg/WyciwygChannelParent.cpp b/netwerk/protocol/wyciwyg/WyciwygChannelParent.cpp index 38e541f50df..f98e9cfe56e 100644 --- a/netwerk/protocol/wyciwyg/WyciwygChannelParent.cpp +++ b/netwerk/protocol/wyciwyg/WyciwygChannelParent.cpp @@ -90,21 +90,21 @@ WyciwygChannelParent::RecvInit(const IPC::URI& aURI) nsCString uriSpec; uri->GetSpec(uriSpec); - LOG(("WyciwygChannelParent RecvAsyncOpen [this=%x uri=%s]\n", + LOG(("WyciwygChannelParent RecvInit [this=%x uri=%s]\n", this, uriSpec.get())); nsCOMPtr ios(do_GetIOService(&rv)); if (NS_FAILED(rv)) - return false; // TODO: send fail msg to child, return true + return SendCancelEarly(rv); nsCOMPtr chan; rv = NS_NewChannel(getter_AddRefs(chan), uri, ios); if (NS_FAILED(rv)) - return false; // TODO: send fail msg to child, return true + return SendCancelEarly(rv); mChannel = do_QueryInterface(chan, &rv); if (NS_FAILED(rv)) - return false; // TODO: send fail msg to child, return true + return SendCancelEarly(rv); return true; } @@ -115,19 +115,21 @@ WyciwygChannelParent::RecvAsyncOpen(const IPC::URI& aOriginal, { nsCOMPtr original(aOriginal); + LOG(("WyciwygChannelParent RecvAsyncOpen [this=%x]\n", this)); + nsresult rv; rv = mChannel->SetOriginalURI(original); if (NS_FAILED(rv)) - return false; // TODO: send fail msg to child, return true + return SendCancelEarly(rv); rv = mChannel->SetLoadFlags(aLoadFlags); if (NS_FAILED(rv)) - return false; // TODO: send fail msg to child, return true + return SendCancelEarly(rv); rv = mChannel->AsyncOpen(this, nsnull); if (NS_FAILED(rv)) - return false; // TODO: send fail msg to child, return true + return SendCancelEarly(rv); return true; } @@ -163,6 +165,14 @@ WyciwygChannelParent::RecvSetSecurityInfo(const nsCString& aSecurityInfo) return true; } +bool +WyciwygChannelParent::RecvCancel(const nsresult& aStatusCode) +{ + if (mChannel) + mChannel->Cancel(aStatusCode); + return true; +} + //----------------------------------------------------------------------------- // WyciwygChannelParent::nsIRequestObserver //----------------------------------------------------------------------------- diff --git a/netwerk/protocol/wyciwyg/WyciwygChannelParent.h b/netwerk/protocol/wyciwyg/WyciwygChannelParent.h index 4d0cf967600..02776f435b9 100644 --- a/netwerk/protocol/wyciwyg/WyciwygChannelParent.h +++ b/netwerk/protocol/wyciwyg/WyciwygChannelParent.h @@ -67,6 +67,7 @@ protected: virtual bool RecvSetCharsetAndSource(const PRInt32& source, const nsCString& charset); virtual bool RecvSetSecurityInfo(const nsCString& securityInfo); + virtual bool RecvCancel(const nsresult& statusCode); virtual void ActorDestroy(ActorDestroyReason why);