michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "mozilla/DebugOnly.h" michael@0: michael@0: #include "nscore.h" michael@0: #include "nsRequestObserverProxy.h" michael@0: #include "nsIRequest.h" michael@0: #include "nsAutoPtr.h" michael@0: #include "prlog.h" michael@0: michael@0: using namespace mozilla; michael@0: michael@0: #if defined(PR_LOGGING) michael@0: static PRLogModuleInfo *gRequestObserverProxyLog; michael@0: #endif michael@0: michael@0: #undef LOG michael@0: #define LOG(args) PR_LOG(gRequestObserverProxyLog, PR_LOG_DEBUG, args) michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // nsARequestObserverEvent internal class... michael@0: //----------------------------------------------------------------------------- michael@0: michael@0: nsARequestObserverEvent::nsARequestObserverEvent(nsIRequest *request) michael@0: : mRequest(request) michael@0: { michael@0: NS_PRECONDITION(mRequest, "null pointer"); michael@0: } michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // nsOnStartRequestEvent internal class... michael@0: //----------------------------------------------------------------------------- michael@0: michael@0: class nsOnStartRequestEvent : public nsARequestObserverEvent michael@0: { michael@0: nsRefPtr mProxy; michael@0: public: michael@0: nsOnStartRequestEvent(nsRequestObserverProxy *proxy, michael@0: nsIRequest *request) michael@0: : nsARequestObserverEvent(request) michael@0: , mProxy(proxy) michael@0: { michael@0: NS_PRECONDITION(mProxy, "null pointer"); michael@0: } michael@0: michael@0: virtual ~nsOnStartRequestEvent() {} michael@0: michael@0: NS_IMETHOD Run() michael@0: { michael@0: LOG(("nsOnStartRequestEvent::HandleEvent [req=%x]\n", mRequest.get())); michael@0: michael@0: if (!mProxy->mObserver) { michael@0: NS_NOTREACHED("already handled onStopRequest event (observer is null)"); michael@0: return NS_OK; michael@0: } michael@0: michael@0: LOG(("handle startevent=%p\n", this)); michael@0: nsresult rv = mProxy->mObserver->OnStartRequest(mRequest, mProxy->mContext); michael@0: if (NS_FAILED(rv)) { michael@0: LOG(("OnStartRequest failed [rv=%x] canceling request!\n", rv)); michael@0: rv = mRequest->Cancel(rv); michael@0: NS_ASSERTION(NS_SUCCEEDED(rv), "Cancel failed for request!"); michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: }; michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // nsOnStopRequestEvent internal class... michael@0: //----------------------------------------------------------------------------- michael@0: michael@0: class nsOnStopRequestEvent : public nsARequestObserverEvent michael@0: { michael@0: nsRefPtr mProxy; michael@0: public: michael@0: nsOnStopRequestEvent(nsRequestObserverProxy *proxy, michael@0: nsIRequest *request) michael@0: : nsARequestObserverEvent(request) michael@0: , mProxy(proxy) michael@0: { michael@0: NS_PRECONDITION(mProxy, "null pointer"); michael@0: } michael@0: michael@0: virtual ~nsOnStopRequestEvent() {} michael@0: michael@0: NS_IMETHOD Run() michael@0: { michael@0: LOG(("nsOnStopRequestEvent::HandleEvent [req=%x]\n", mRequest.get())); michael@0: michael@0: nsMainThreadPtrHandle observer = mProxy->mObserver; michael@0: if (!observer) { michael@0: NS_NOTREACHED("already handled onStopRequest event (observer is null)"); michael@0: return NS_OK; michael@0: } michael@0: // Do not allow any more events to be handled after OnStopRequest michael@0: mProxy->mObserver = 0; michael@0: michael@0: nsresult status = NS_OK; michael@0: DebugOnly rv = mRequest->GetStatus(&status); michael@0: NS_ASSERTION(NS_SUCCEEDED(rv), "GetStatus failed for request!"); michael@0: michael@0: LOG(("handle stopevent=%p\n", this)); michael@0: (void) observer->OnStopRequest(mRequest, mProxy->mContext, status); michael@0: michael@0: return NS_OK; michael@0: } michael@0: }; michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // nsRequestObserverProxy::nsISupports implementation... michael@0: //----------------------------------------------------------------------------- michael@0: michael@0: NS_IMPL_ISUPPORTS(nsRequestObserverProxy, michael@0: nsIRequestObserver, michael@0: nsIRequestObserverProxy) michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // nsRequestObserverProxy::nsIRequestObserver implementation... michael@0: //----------------------------------------------------------------------------- michael@0: michael@0: NS_IMETHODIMP michael@0: nsRequestObserverProxy::OnStartRequest(nsIRequest *request, michael@0: nsISupports *context) michael@0: { michael@0: MOZ_ASSERT(!context || context == mContext); michael@0: LOG(("nsRequestObserverProxy::OnStartRequest [this=%p req=%x]\n", this, request)); michael@0: michael@0: nsOnStartRequestEvent *ev = michael@0: new nsOnStartRequestEvent(this, request); michael@0: if (!ev) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: LOG(("post startevent=%p\n", ev)); michael@0: nsresult rv = FireEvent(ev); michael@0: if (NS_FAILED(rv)) michael@0: delete ev; michael@0: return rv; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsRequestObserverProxy::OnStopRequest(nsIRequest *request, michael@0: nsISupports *context, michael@0: nsresult status) michael@0: { michael@0: MOZ_ASSERT(!context || context == mContext); michael@0: LOG(("nsRequestObserverProxy: OnStopRequest [this=%p req=%x status=%x]\n", michael@0: this, request, status)); michael@0: michael@0: // The status argument is ignored because, by the time the OnStopRequestEvent michael@0: // is actually processed, the status of the request may have changed :-( michael@0: // To make sure that an accurate status code is always used, GetStatus() is michael@0: // called when the OnStopRequestEvent is actually processed (see above). michael@0: michael@0: nsOnStopRequestEvent *ev = michael@0: new nsOnStopRequestEvent(this, request); michael@0: if (!ev) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: LOG(("post stopevent=%p\n", ev)); michael@0: nsresult rv = FireEvent(ev); michael@0: if (NS_FAILED(rv)) michael@0: delete ev; michael@0: return rv; michael@0: } michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // nsRequestObserverProxy::nsIRequestObserverProxy implementation... michael@0: //----------------------------------------------------------------------------- michael@0: michael@0: NS_IMETHODIMP michael@0: nsRequestObserverProxy::Init(nsIRequestObserver *observer, nsISupports *context) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(observer); michael@0: michael@0: #if defined(PR_LOGGING) michael@0: if (!gRequestObserverProxyLog) michael@0: gRequestObserverProxyLog = PR_NewLogModule("nsRequestObserverProxy"); michael@0: #endif michael@0: michael@0: mObserver = new nsMainThreadPtrHolder(observer); michael@0: mContext = new nsMainThreadPtrHolder(context); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // nsRequestObserverProxy implementation... michael@0: //----------------------------------------------------------------------------- michael@0: michael@0: nsresult michael@0: nsRequestObserverProxy::FireEvent(nsARequestObserverEvent *event) michael@0: { michael@0: nsCOMPtr mainThread(do_GetMainThread()); michael@0: return mainThread->Dispatch(event, NS_DISPATCH_NORMAL); michael@0: }