Bug 605327 - Add proper cancellation to e10s wyciwyg channels. r=dwitte a=blocking-fennec

This commit is contained in:
Josh Matthews 2010-11-19 16:12:45 -05:00
Родитель a95966cc22
Коммит c0aaec5ffa
5 изменённых файлов: 94 добавлений и 19 удалений

Просмотреть файл

@ -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);
};

Просмотреть файл

@ -60,6 +60,7 @@ WyciwygChannelChild::WyciwygChannelChild()
: ChannelEventQueue<WyciwygChannelChild>(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 (); */

Просмотреть файл

@ -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

Просмотреть файл

@ -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<nsIIOService> ios(do_GetIOService(&rv));
if (NS_FAILED(rv))
return false; // TODO: send fail msg to child, return true
return SendCancelEarly(rv);
nsCOMPtr<nsIChannel> 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<nsIURI> 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
//-----------------------------------------------------------------------------

Просмотреть файл

@ -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);