зеркало из https://github.com/mozilla/pjs.git
Bug 459762 - 'Workers: Support synchronous XHR'. r+sr=sicking.
This commit is contained in:
Родитель
a1db6104cc
Коммит
582aee5932
|
@ -59,13 +59,14 @@
|
|||
#include "nsDOMThreadService.h"
|
||||
|
||||
// Macro to generate nsIClassInfo methods for these threadsafe DOM classes
|
||||
#define NS_IMPL_THREADSAFE_DOM_CI(_class) \
|
||||
#define NS_IMPL_THREADSAFE_DOM_CI_GETINTERFACES(_class) \
|
||||
NS_IMETHODIMP \
|
||||
_class::GetInterfaces(PRUint32* _count, nsIID*** _array) \
|
||||
{ \
|
||||
return NS_CI_INTERFACE_GETTER_NAME(_class)(_count, _array); \
|
||||
} \
|
||||
\
|
||||
|
||||
#define NS_IMPL_THREADSAFE_DOM_CI_ALL_THE_REST(_class) \
|
||||
NS_IMETHODIMP \
|
||||
_class::GetHelperForLanguage(PRUint32 _language, nsISupports** _retval) \
|
||||
{ \
|
||||
|
@ -114,6 +115,10 @@ _class::GetClassIDNoAlloc(nsCID* _classIDNoAlloc) \
|
|||
return NS_ERROR_NOT_AVAILABLE; \
|
||||
}
|
||||
|
||||
#define NS_IMPL_THREADSAFE_DOM_CI(_class) \
|
||||
NS_IMPL_THREADSAFE_DOM_CI_GETINTERFACES(_class) \
|
||||
NS_IMPL_THREADSAFE_DOM_CI_ALL_THE_REST(_class)
|
||||
|
||||
class nsDOMWorkerPool;
|
||||
class nsDOMWorkerScriptLoader;
|
||||
class nsDOMWorkerTimeout;
|
||||
|
|
|
@ -77,14 +77,6 @@ const char* const nsDOMWorkerXHREventTarget::sListenerTypes[] = {
|
|||
"readystatechange" /* LISTENER_TYPE_READYSTATECHANGE */
|
||||
};
|
||||
|
||||
// Convenience defines for event *indexes* in the sListenerTypes array.
|
||||
#define LISTENER_TYPE_ABORT 0
|
||||
#define LISTENER_TYPE_ERROR 1
|
||||
#define LISTENER_TYPE_LOAD 2
|
||||
#define LISTENER_TYPE_LOADSTART 3
|
||||
#define LISTENER_TYPE_PROGRESS 4
|
||||
#define LISTENER_TYPE_READYSTATECHANGE 5
|
||||
|
||||
// This should always be set to the length of sListenerTypes.
|
||||
const PRUint32 nsDOMWorkerXHREventTarget::sMaxXHREventTypes =
|
||||
NS_ARRAY_LENGTH(nsDOMWorkerXHREventTarget::sListenerTypes);
|
||||
|
@ -512,15 +504,17 @@ nsDOMWorkerXHR::GetOnXListener(PRUint32 aType)
|
|||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetChannel(nsIChannel** aChannel)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
NS_ENSURE_ARG_POINTER(aChannel);
|
||||
*aChannel = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetResponseXML(nsIDOMDocument** aResponseXML)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
NS_ENSURE_ARG_POINTER(aResponseXML);
|
||||
*aResponseXML = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -681,9 +675,6 @@ nsDOMWorkerXHR::Open(const nsACString& aMethod,
|
|||
JS_ValueToBoolean(cx, argv[2], &asyncBool);
|
||||
async = (PRBool)asyncBool;
|
||||
|
||||
// XXX Remove me once we support sync XHR
|
||||
NS_ENSURE_TRUE(async, NS_ERROR_INVALID_ARG);
|
||||
|
||||
if (argc < 4) {
|
||||
break;
|
||||
}
|
||||
|
@ -853,6 +844,7 @@ nsDOMWorkerXHR::Init(nsIPrincipal* aPrincipal,
|
|||
nsPIDOMWindow* aOwnerWindow)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_NOTREACHED("No one should be calling this!");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
@ -917,13 +909,31 @@ nsDOMWorkerXHR::SetOnreadystatechange(nsIDOMEventListener* aOnreadystatechange)
|
|||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetWithCredentials(PRBool* aWithCredentials)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aWithCredentials);
|
||||
*aWithCredentials = PR_FALSE;
|
||||
|
||||
nsresult rv = mXHRProxy->GetWithCredentials(aWithCredentials);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::SetWithCredentials(PRBool aWithCredentials)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->SetWithCredentials(aWithCredentials);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -54,6 +54,14 @@
|
|||
// DOMWorker includes
|
||||
#include "nsDOMWorkerThread.h"
|
||||
|
||||
// Convenience defines for event *indexes* in the sListenerTypes array.
|
||||
#define LISTENER_TYPE_ABORT 0
|
||||
#define LISTENER_TYPE_ERROR 1
|
||||
#define LISTENER_TYPE_LOAD 2
|
||||
#define LISTENER_TYPE_LOADSTART 3
|
||||
#define LISTENER_TYPE_PROGRESS 4
|
||||
#define LISTENER_TYPE_READYSTATECHANGE 5
|
||||
|
||||
class nsDOMWorkerXHR;
|
||||
class nsDOMWorkerXHREvent;
|
||||
class nsDOMWorkerXHRProxy;
|
||||
|
@ -125,6 +133,7 @@ class nsDOMWorkerXHR : public nsDOMWorkerXHREventTarget,
|
|||
public nsIClassInfo
|
||||
{
|
||||
friend class nsDOMWorkerXHREvent;
|
||||
friend class nsDOMWorkerXHRLastProgressOrLoadEvent;
|
||||
friend class nsDOMWorkerXHRProxy;
|
||||
friend class nsDOMWorkerXHRUpload;
|
||||
|
||||
|
|
|
@ -43,9 +43,6 @@
|
|||
class _name : public SyncEventCapturingRunnable \
|
||||
{ \
|
||||
public: \
|
||||
_name (nsDOMWorkerXHRProxy* aXHR, SyncEventQueue* aQueue) \
|
||||
: SyncEventCapturingRunnable(aXHR, aQueue) { } \
|
||||
\
|
||||
virtual nsresult RunInternal() \
|
||||
{ \
|
||||
nsCOMPtr<nsIXMLHttpRequest> xhr = mXHR->GetXMLHttpRequest(); \
|
||||
|
@ -60,8 +57,7 @@
|
|||
class _name : public SyncEventCapturingRunnable \
|
||||
{ \
|
||||
public: \
|
||||
_name (nsDOMWorkerXHRProxy* aXHR, SyncEventQueue* aQueue, _arg1 aArg1) \
|
||||
: SyncEventCapturingRunnable(aXHR, aQueue), mArg1(aArg1) { } \
|
||||
_name (_arg1 aArg1) : mArg1(aArg1) { } \
|
||||
\
|
||||
virtual nsresult RunInternal() \
|
||||
{ \
|
||||
|
@ -79,9 +75,7 @@
|
|||
class _name : public SyncEventCapturingRunnable \
|
||||
{ \
|
||||
public: \
|
||||
_name (nsDOMWorkerXHRProxy* aXHR, SyncEventQueue* aQueue, _arg1 aArg1, \
|
||||
_arg2 aArg2) \
|
||||
: SyncEventCapturingRunnable(aXHR, aQueue), mArg1(aArg1), mArg2(aArg2) { } \
|
||||
_name (_arg1 aArg1, _arg2 aArg2) : mArg1(aArg1), mArg2(aArg2) { } \
|
||||
\
|
||||
virtual nsresult RunInternal() \
|
||||
{ \
|
||||
|
@ -96,34 +90,6 @@
|
|||
_arg2 mArg2; \
|
||||
}
|
||||
|
||||
#define RUN_PROXIED_FUNCTION(_name, _args) \
|
||||
PR_BEGIN_MACRO \
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!"); \
|
||||
\
|
||||
if (mCanceled) { \
|
||||
return NS_ERROR_ABORT; \
|
||||
} \
|
||||
SyncEventQueue queue; \
|
||||
\
|
||||
nsCOMPtr<nsIRunnable> method = new :: _name _args; \
|
||||
NS_ENSURE_TRUE(method, NS_ERROR_OUT_OF_MEMORY); \
|
||||
\
|
||||
nsRefPtr<nsResultReturningRunnable> runnable = \
|
||||
new nsResultReturningRunnable(mMainThread, method, mWorkerXHR->mWorker); \
|
||||
NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY); \
|
||||
\
|
||||
nsresult _rv = runnable->Dispatch(); \
|
||||
\
|
||||
PRUint32 queueLength = queue.Length(); \
|
||||
for (PRUint32 index = 0; index < queueLength; index++) { \
|
||||
queue[index]->Run(); \
|
||||
} \
|
||||
\
|
||||
if (NS_FAILED(_rv)) { \
|
||||
return _rv; \
|
||||
} \
|
||||
PR_END_MACRO
|
||||
|
||||
namespace nsDOMWorkerProxiedXHRFunctions
|
||||
{
|
||||
typedef nsDOMWorkerXHRProxy::SyncEventQueue SyncEventQueue;
|
||||
|
@ -131,16 +97,23 @@ namespace nsDOMWorkerProxiedXHRFunctions
|
|||
class SyncEventCapturingRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
SyncEventCapturingRunnable(nsDOMWorkerXHRProxy* aXHR,
|
||||
SyncEventQueue* aQueue)
|
||||
: mXHR(aXHR), mQueue(aQueue) {
|
||||
SyncEventCapturingRunnable()
|
||||
: mXHR(nsnull), mQueue(nsnull) { }
|
||||
|
||||
void Init(nsDOMWorkerXHRProxy* aXHR,
|
||||
SyncEventQueue* aQueue) {
|
||||
NS_ASSERTION(aXHR, "Null pointer!");
|
||||
NS_ASSERTION(aQueue, "Null pointer!");
|
||||
|
||||
mXHR = aXHR;
|
||||
mQueue = aQueue;
|
||||
}
|
||||
|
||||
virtual nsresult RunInternal() = 0;
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
NS_ASSERTION(mXHR && mQueue, "Forgot to call Init!");
|
||||
|
||||
SyncEventQueue* oldQueue = mXHR->SetSyncEventQueue(mQueue);
|
||||
|
||||
nsresult rv = RunInternal();
|
||||
|
@ -158,9 +131,6 @@ namespace nsDOMWorkerProxiedXHRFunctions
|
|||
class Abort : public SyncEventCapturingRunnable
|
||||
{
|
||||
public:
|
||||
Abort (nsDOMWorkerXHRProxy* aXHR, SyncEventQueue* aQueue)
|
||||
: SyncEventCapturingRunnable(aXHR, aQueue) { }
|
||||
|
||||
virtual nsresult RunInternal() {
|
||||
return mXHR->Abort();
|
||||
}
|
||||
|
@ -169,12 +139,11 @@ namespace nsDOMWorkerProxiedXHRFunctions
|
|||
class OpenRequest : public SyncEventCapturingRunnable
|
||||
{
|
||||
public:
|
||||
OpenRequest(nsDOMWorkerXHRProxy* aXHR, SyncEventQueue* aQueue,
|
||||
const nsACString& aMethod, const nsACString& aUrl,
|
||||
OpenRequest(const nsACString& aMethod, const nsACString& aUrl,
|
||||
PRBool aAsync, const nsAString& aUser,
|
||||
const nsAString& aPassword)
|
||||
: SyncEventCapturingRunnable(aXHR, aQueue), mMethod(aMethod), mUrl(aUrl),
|
||||
mAsync(aAsync), mUser(aUser), mPassword(aPassword) { }
|
||||
: mMethod(aMethod), mUrl(aUrl), mAsync(aAsync), mUser(aUser),
|
||||
mPassword(aPassword) { }
|
||||
|
||||
virtual nsresult RunInternal() {
|
||||
return mXHR->OpenRequest(mMethod, mUrl, mAsync, mUser, mPassword);
|
||||
|
@ -204,6 +173,10 @@ namespace nsDOMWorkerProxiedXHRFunctions
|
|||
MAKE_PROXIED_FUNCTION1(SetMultipart, PRBool);
|
||||
|
||||
MAKE_PROXIED_FUNCTION1(GetMultipart, PRBool*);
|
||||
|
||||
MAKE_PROXIED_FUNCTION1(GetWithCredentials, PRBool*);
|
||||
|
||||
MAKE_PROXIED_FUNCTION1(SetWithCredentials, PRBool);
|
||||
}
|
||||
|
||||
#endif /* __NSDOMWORKERXHRPROXIEDFUNCTIONS_H__ */
|
||||
|
|
|
@ -40,7 +40,10 @@
|
|||
|
||||
// Interfaces
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsIDOMProgressEvent.h"
|
||||
#include "nsILoadGroup.h"
|
||||
#include "nsIRequest.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsIVariant.h"
|
||||
#include "nsIXMLHttpRequest.h"
|
||||
|
@ -63,11 +66,48 @@
|
|||
#define MAX_XHR_LISTENER_TYPE nsDOMWorkerXHREventTarget::sMaxXHREventTypes
|
||||
#define MAX_UPLOAD_LISTENER_TYPE nsDOMWorkerXHREventTarget::sMaxUploadEventTypes
|
||||
|
||||
#define RUN_PROXIED_FUNCTION(_name, _args) \
|
||||
PR_BEGIN_MACRO \
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!"); \
|
||||
\
|
||||
if (mCanceled) { \
|
||||
return NS_ERROR_ABORT; \
|
||||
} \
|
||||
\
|
||||
SyncEventQueue queue; \
|
||||
\
|
||||
nsRefPtr< :: _name> method = new :: _name _args; \
|
||||
NS_ENSURE_TRUE(method, NS_ERROR_OUT_OF_MEMORY); \
|
||||
\
|
||||
method->Init(this, &queue); \
|
||||
\
|
||||
nsRefPtr<nsResultReturningRunnable> runnable = \
|
||||
new nsResultReturningRunnable(mMainThread, method, mWorkerXHR->mWorker); \
|
||||
NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY); \
|
||||
\
|
||||
nsresult _rv = runnable->Dispatch(); \
|
||||
\
|
||||
if (mCanceled) { \
|
||||
return NS_ERROR_ABORT; \
|
||||
} \
|
||||
\
|
||||
PRUint32 queueLength = queue.Length(); \
|
||||
for (PRUint32 index = 0; index < queueLength; index++) { \
|
||||
queue[index]->Run(); \
|
||||
} \
|
||||
\
|
||||
if (NS_FAILED(_rv)) { \
|
||||
return _rv; \
|
||||
} \
|
||||
PR_END_MACRO
|
||||
|
||||
using namespace nsDOMWorkerProxiedXHRFunctions;
|
||||
|
||||
class nsResultReturningRunnable : public nsRunnable
|
||||
class nsResultReturningRunnable : public nsIRunnable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsResultReturningRunnable(nsIEventTarget* aTarget, nsIRunnable* aRunnable,
|
||||
nsDOMWorkerThread* aWorker)
|
||||
: mTarget(aTarget), mRunnable(aRunnable), mWorker(aWorker),
|
||||
|
@ -122,7 +162,9 @@ private:
|
|||
volatile PRBool mDone;
|
||||
};
|
||||
|
||||
class nsDOMWorkerXHREvent : public nsRunnable,
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsResultReturningRunnable, nsIRunnable)
|
||||
|
||||
class nsDOMWorkerXHREvent : public nsIRunnable,
|
||||
public nsIDOMProgressEvent,
|
||||
public nsIClassInfo
|
||||
{
|
||||
|
@ -138,7 +180,10 @@ public:
|
|||
|
||||
nsDOMWorkerXHREvent(nsDOMWorkerXHRProxy* aXHRProxy);
|
||||
|
||||
nsresult Init(nsIDOMEvent* aEvent);
|
||||
nsresult Init(PRUint32 aType,
|
||||
const nsAString& aTypeString,
|
||||
nsIDOMEvent* aEvent);
|
||||
|
||||
nsresult Init(nsIXMLHttpRequest* aXHR);
|
||||
|
||||
void EventHandled();
|
||||
|
@ -183,37 +228,55 @@ nsDOMWorkerXHREvent::nsDOMWorkerXHREvent(nsDOMWorkerXHRProxy* aXHRProxy)
|
|||
NS_ASSERTION(aXHRProxy, "Can't be null!");
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsDOMWorkerXHREvent, nsRunnable)
|
||||
NS_IMPL_RELEASE_INHERITED(nsDOMWorkerXHREvent, nsRunnable)
|
||||
NS_IMPL_THREADSAFE_ADDREF(nsDOMWorkerXHREvent)
|
||||
NS_IMPL_THREADSAFE_RELEASE(nsDOMWorkerXHREvent)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsDOMWorkerXHREvent)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMEvent)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIRunnable)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMEvent)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
|
||||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIDOMProgressEvent, mProgressEvent)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsRunnable)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CI_INTERFACE_GETTER1(nsDOMWorkerXHREvent, nsIDOMEvent)
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREvent::GetInterfaces(PRUint32* aCount,
|
||||
nsIID*** aArray)
|
||||
{
|
||||
PRUint32 count = *aCount = mProgressEvent ? 2 : 1;
|
||||
|
||||
NS_IMPL_THREADSAFE_DOM_CI(nsDOMWorkerXHREvent)
|
||||
*aArray = (nsIID**)nsMemory::Alloc(sizeof(nsIID*) * count);
|
||||
|
||||
if (mProgressEvent) {
|
||||
(*aArray)[--count] =
|
||||
(nsIID*)nsMemory::Clone(&NS_GET_IID(nsIDOMProgressEvent), sizeof(nsIID));
|
||||
}
|
||||
|
||||
(*aArray)[--count] =
|
||||
(nsIID *)nsMemory::Clone(&NS_GET_IID(nsIDOMEvent), sizeof(nsIID));
|
||||
|
||||
NS_ASSERTION(!count, "Bad math!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_DOM_CI_ALL_THE_REST(nsDOMWorkerXHREvent)
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHREvent::Init(nsIDOMEvent* aEvent)
|
||||
nsDOMWorkerXHREvent::Init(PRUint32 aType,
|
||||
const nsAString& aTypeString,
|
||||
nsIDOMEvent* aEvent)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aEvent, "Don't pass null here!");
|
||||
|
||||
nsresult rv;
|
||||
|
||||
mType = aType;
|
||||
mTypeString.Assign(aTypeString);
|
||||
|
||||
mChannelID = mXHRProxy->ChannelID();
|
||||
|
||||
nsresult rv = aEvent->GetType(mTypeString);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mType = nsDOMWorkerXHREventTarget::GetListenerTypeFromString(mTypeString);
|
||||
if (mType >= MAX_XHR_LISTENER_TYPE) {
|
||||
NS_ERROR("Shouldn't get this type of event!");
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMProgressEvent> progressEvent(do_QueryInterface(aEvent));
|
||||
if (progressEvent) {
|
||||
mProgressEvent = PR_TRUE;
|
||||
|
@ -288,6 +351,7 @@ nsDOMWorkerXHREvent::Init(nsIXMLHttpRequest* aXHR)
|
|||
void
|
||||
nsDOMWorkerXHREvent::EventHandled()
|
||||
{
|
||||
// Prevent reference cycles by releasing these here.
|
||||
mXHRProxy = nsnull;
|
||||
}
|
||||
|
||||
|
@ -416,6 +480,38 @@ nsDOMWorkerXHREvent::InitProgressEvent(const nsAString_internal& aTypeArg,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
class nsDOMWorkerXHRLastProgressOrLoadEvent : public nsIRunnable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsDOMWorkerXHRLastProgressOrLoadEvent(nsDOMWorkerXHRProxy* aProxy)
|
||||
: mProxy(aProxy) {
|
||||
NS_ASSERTION(aProxy, "Null pointer!");
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
nsRefPtr<nsDOMWorkerXHREvent> lastProgressOrLoadEvent;
|
||||
|
||||
if (!mProxy->mCanceled) {
|
||||
nsAutoLock lock(mProxy->mWorkerXHR->Lock());
|
||||
mProxy->mLastProgressOrLoadEvent.swap(lastProgressOrLoadEvent);
|
||||
}
|
||||
|
||||
if (lastProgressOrLoadEvent) {
|
||||
return lastProgressOrLoadEvent->Run();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<nsDOMWorkerXHRProxy> mProxy;
|
||||
};
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsDOMWorkerXHRLastProgressOrLoadEvent,
|
||||
nsIRunnable)
|
||||
|
||||
class nsDOMWorkerXHRWrappedListener : public nsIDOMEventListener
|
||||
{
|
||||
public:
|
||||
|
@ -441,19 +537,20 @@ private:
|
|||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsDOMWorkerXHRWrappedListener,
|
||||
nsIDOMEventListener)
|
||||
|
||||
class nsDOMWorkerXHRAttachUploadListenersRunnable : public nsRunnable
|
||||
class nsDOMWorkerXHRAttachUploadListenersRunnable : public nsIRunnable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsDOMWorkerXHRAttachUploadListenersRunnable(nsDOMWorkerXHRProxy* aProxy)
|
||||
: mProxy(aProxy) {
|
||||
NS_ASSERTION(aProxy, "Null pointer!");
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
if (!mProxy->mOwnedByXHR) {
|
||||
NS_ASSERTION(mProxy->mWantUploadListeners, "Inconsistent state!");
|
||||
return NS_OK;
|
||||
}
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
NS_ASSERTION(!mProxy->mWantUploadListeners, "Huh?!");
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> upload(do_QueryInterface(mProxy->mUpload));
|
||||
NS_ASSERTION(upload, "This shouldn't fail!");
|
||||
|
@ -464,6 +561,7 @@ public:
|
|||
upload->AddEventListener(eventName, mProxy, PR_FALSE);
|
||||
}
|
||||
|
||||
mProxy->mWantUploadListeners = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -471,6 +569,46 @@ private:
|
|||
nsRefPtr<nsDOMWorkerXHRProxy> mProxy;
|
||||
};
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsDOMWorkerXHRAttachUploadListenersRunnable,
|
||||
nsIRunnable)
|
||||
|
||||
class nsDOMWorkerXHRFinishSyncXHRRunnable : public nsIRunnable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsDOMWorkerXHRFinishSyncXHRRunnable(nsDOMWorkerXHRProxy* aProxy,
|
||||
nsIThread* aTarget)
|
||||
: mProxy(aProxy), mTarget(aTarget) {
|
||||
NS_ASSERTION(aProxy, "Null pointer!");
|
||||
NS_ASSERTION(aTarget, "Null pointer!");
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
nsCOMPtr<nsIThread> thread;
|
||||
mProxy->mSyncXHRThread.swap(thread);
|
||||
mProxy = nsnull;
|
||||
|
||||
NS_ASSERTION(thread, "Should have a thread here!");
|
||||
NS_ASSERTION(!NS_IsMainThread() && thread == NS_GetCurrentThread(),
|
||||
"Wrong thread?!");
|
||||
|
||||
return NS_ProcessPendingEvents(thread);
|
||||
}
|
||||
|
||||
nsresult Dispatch() {
|
||||
nsresult rv = mTarget->Dispatch(this, NS_DISPATCH_NORMAL);
|
||||
mTarget = nsnull;
|
||||
return rv;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<nsDOMWorkerXHRProxy> mProxy;
|
||||
nsCOMPtr<nsIThread> mTarget;
|
||||
};
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsDOMWorkerXHRFinishSyncXHRRunnable, nsIRunnable)
|
||||
|
||||
nsDOMWorkerXHRProxy::nsDOMWorkerXHRProxy(nsDOMWorkerXHR* aWorkerXHR)
|
||||
: mWorkerXHR(aWorkerXHR),
|
||||
mXHR(nsnull),
|
||||
|
@ -480,7 +618,8 @@ nsDOMWorkerXHRProxy::nsDOMWorkerXHRProxy(nsDOMWorkerXHR* aWorkerXHR)
|
|||
mChannelID(-1),
|
||||
mOwnedByXHR(PR_FALSE),
|
||||
mWantUploadListeners(PR_FALSE),
|
||||
mCanceled(PR_FALSE)
|
||||
mCanceled(PR_FALSE),
|
||||
mSyncRequest(PR_FALSE)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(MAX_XHR_LISTENER_TYPE >= MAX_UPLOAD_LISTENER_TYPE,
|
||||
|
@ -502,9 +641,9 @@ nsDOMWorkerXHRProxy::~nsDOMWorkerXHRProxy()
|
|||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED2(nsDOMWorkerXHRProxy, nsRunnable,
|
||||
nsIDOMEventListener,
|
||||
nsIRequestObserver)
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS3(nsDOMWorkerXHRProxy, nsIRunnable,
|
||||
nsIDOMEventListener,
|
||||
nsIRequestObserver)
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHRProxy::Init()
|
||||
|
@ -557,12 +696,18 @@ nsDOMWorkerXHRProxy::Destroy()
|
|||
mCanceled = PR_TRUE;
|
||||
|
||||
ClearEventListeners();
|
||||
mLastXHREvent = nsnull;
|
||||
|
||||
{
|
||||
nsAutoLock lock(mWorkerXHR->Lock());
|
||||
mLastProgressOrLoadEvent = nsnull;
|
||||
}
|
||||
|
||||
if (mXHR) {
|
||||
DestroyInternal();
|
||||
}
|
||||
|
||||
mLastXHREvent = nsnull;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -617,6 +762,8 @@ nsDOMWorkerXHRProxy::InitInternal()
|
|||
mUpload = upload;
|
||||
mConcreteXHR = xhrConcrete;
|
||||
|
||||
AddRemoveXHRListeners(PR_TRUE);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -625,38 +772,51 @@ nsDOMWorkerXHRProxy::DestroyInternal()
|
|||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsRefPtr<nsDOMWorkerXHRProxy> kungFuDeathGrip;
|
||||
nsRefPtr<nsDOMWorkerXHRProxy> kungFuDeathGrip(this);
|
||||
|
||||
if (mConcreteXHR) {
|
||||
mConcreteXHR->SetRequestObserver(nsnull);
|
||||
}
|
||||
|
||||
if (mOwnedByXHR) {
|
||||
kungFuDeathGrip = this;
|
||||
mXHR->Abort();
|
||||
}
|
||||
else {
|
||||
// There's a slight chance that Send was called yet we've canceled before
|
||||
// necko has fired its OnStartRequest notification. Guard against that here.
|
||||
nsRefPtr<nsDOMWorkerXHRFinishSyncXHRRunnable> syncFinishedRunnable;
|
||||
{
|
||||
nsAutoLock lock(mWorkerXHR->Lock());
|
||||
mSyncFinishedRunnable.swap(syncFinishedRunnable);
|
||||
}
|
||||
|
||||
if (syncFinishedRunnable) {
|
||||
syncFinishedRunnable->Dispatch();
|
||||
}
|
||||
}
|
||||
|
||||
NS_ASSERTION(!mOwnedByXHR, "Should have flipped already!");
|
||||
NS_ASSERTION(!mSyncFinishedRunnable, "Should have fired this already!");
|
||||
NS_ASSERTION(!mLastProgressOrLoadEvent, "Should have killed this already!");
|
||||
|
||||
// mXHR could be null if Init fails.
|
||||
if (mXHR) {
|
||||
mConcreteXHR->SetRequestObserver(nsnull);
|
||||
AddRemoveXHRListeners(PR_FALSE);
|
||||
|
||||
mXHR->Release();
|
||||
mXHR = nsnull;
|
||||
|
||||
mUpload = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerXHRProxy::FlipOwnership()
|
||||
nsDOMWorkerXHRProxy::AddRemoveXHRListeners(PRBool aAdd)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
// Flip!
|
||||
mOwnedByXHR = !mOwnedByXHR;
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> xhrTarget(do_QueryInterface(mXHR));
|
||||
NS_ASSERTION(xhrTarget, "This shouldn't fail!");
|
||||
|
||||
// If mWorkerXHR has no outstanding refs from JS then we are about to die.
|
||||
// Hold an extra ref here to make sure that we live through this call.
|
||||
nsRefPtr<nsDOMWorkerXHRProxy> kungFuDeathGrip(this);
|
||||
|
||||
EventListenerFunction function = mOwnedByXHR ?
|
||||
EventListenerFunction function = aAdd ?
|
||||
&nsIDOMEventTarget::AddEventListener :
|
||||
&nsIDOMEventTarget::RemoveEventListener;
|
||||
|
||||
|
@ -678,6 +838,19 @@ nsDOMWorkerXHRProxy::FlipOwnership()
|
|||
eventName.AssignASCII(nsDOMWorkerXHREventTarget::sListenerTypes[index]);
|
||||
(xhrTarget.get()->*function)(eventName, this, PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerXHRProxy::FlipOwnership()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
// Flip!
|
||||
mOwnedByXHR = !mOwnedByXHR;
|
||||
|
||||
// If mWorkerXHR has no outstanding refs from JS then we are about to die.
|
||||
// Hold an extra ref here to make sure that we live through this call.
|
||||
nsRefPtr<nsDOMWorkerXHRProxy> kungFuDeathGrip(this);
|
||||
|
||||
if (mOwnedByXHR) {
|
||||
mWorkerXHR->AddRef();
|
||||
|
@ -749,8 +922,6 @@ nsDOMWorkerXHRProxy::AddEventListener(PRUint32 aType,
|
|||
// If this is the first time we're setting an upload listener then we have to
|
||||
// hit the main thread to attach the upload listeners.
|
||||
if (aUploadListener && aListener && !mWantUploadListeners) {
|
||||
mWantUploadListeners = PR_TRUE;
|
||||
|
||||
nsRefPtr<nsDOMWorkerXHRAttachUploadListenersRunnable> attachRunnable =
|
||||
new nsDOMWorkerXHRAttachUploadListenersRunnable(this);
|
||||
NS_ENSURE_TRUE(attachRunnable, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
@ -764,6 +935,8 @@ nsDOMWorkerXHRProxy::AddEventListener(PRUint32 aType,
|
|||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mWantUploadListeners, "Should have set this!");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -827,16 +1000,14 @@ nsDOMWorkerXHRProxy::HandleWorkerEvent(nsDOMWorkerXHREvent* aEvent,
|
|||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aEvent, "Should not be null!");
|
||||
|
||||
if (aEvent->mChannelID != -1 && aEvent->mChannelID != mChannelID) {
|
||||
if (mCanceled ||
|
||||
(aEvent->mChannelID != -1 && aEvent->mChannelID != mChannelID)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mLastXHREvent = aEvent;
|
||||
|
||||
nsresult rv = HandleEventInternal(aEvent->mType, aEvent, aUploadEvent);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
return HandleEventInternal(aEvent->mType, aEvent, aUploadEvent);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -860,10 +1031,7 @@ nsDOMWorkerXHRProxy::HandleWorkerEvent(nsIDOMEvent* aEvent,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
rv = HandleEventInternal(type, aEvent, aUploadEvent);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
return HandleEventInternal(type, aEvent, aUploadEvent);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -956,66 +1124,113 @@ nsDOMWorkerXHRProxy::ClearEventListeners()
|
|||
// lock.
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDOMWorkerXHRProxy::HasListenersForType(PRUint32 aType,
|
||||
nsIDOMEvent* aEvent)
|
||||
{
|
||||
NS_ASSERTION(aType < MAX_XHR_LISTENER_TYPE, "Bad type!");
|
||||
|
||||
if (mXHRListeners[aType].Length()) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool checkUploadListeners = PR_FALSE;
|
||||
if (aEvent) {
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
if (NS_SUCCEEDED(aEvent->GetTarget(getter_AddRefs(target)))) {
|
||||
nsCOMPtr<nsIXMLHttpRequestUpload> upload(do_QueryInterface(target));
|
||||
checkUploadListeners = !!upload;
|
||||
}
|
||||
}
|
||||
else {
|
||||
checkUploadListeners = PR_TRUE;
|
||||
}
|
||||
|
||||
if (checkUploadListeners && mUploadListeners[aType].Length()) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// nsIDOMEventListener
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHRProxy::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aEvent);
|
||||
|
||||
nsAutoString typeString;
|
||||
nsresult rv = aEvent->GetType(typeString);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint32 type =
|
||||
nsDOMWorkerXHREventTarget::GetListenerTypeFromString(typeString);
|
||||
if (type >= MAX_XHR_LISTENER_TYPE) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// When Abort is called on nsXMLHttpRequest (either from a proxied Abort call
|
||||
// or from DestroyInternal) the OnStopRequest call is not run synchronously.
|
||||
// Thankfully an abort event *is* fired synchronously so we can flip our
|
||||
// ownership around and fire the sync finished runnable if we're running in
|
||||
// sync mode.
|
||||
if (type == LISTENER_TYPE_ABORT && mCanceled) {
|
||||
OnStopRequest(nsnull, nsnull, NS_ERROR_ABORT);
|
||||
}
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aEvent);
|
||||
if (!HasListenersForType(type, aEvent)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<nsDOMWorkerXHREvent> newEvent = new nsDOMWorkerXHREvent(this);
|
||||
NS_ENSURE_TRUE(newEvent, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsresult rv = newEvent->Init(aEvent);
|
||||
rv = newEvent->Init(type, typeString, aEvent);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// If we're supposed to be capturing events for synchronous execution then
|
||||
// place this event in the queue. Otherwise schedule it for the worker via
|
||||
// the thread service.
|
||||
if (mSyncEventQueue) {
|
||||
// Always run this event!
|
||||
newEvent->mChannelID = -1;
|
||||
nsCOMPtr<nsIRunnable> runnable(newEvent);
|
||||
|
||||
if (type == LISTENER_TYPE_LOAD || type == LISTENER_TYPE_PROGRESS) {
|
||||
runnable = new nsDOMWorkerXHRLastProgressOrLoadEvent(this);
|
||||
NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
{
|
||||
nsAutoLock lock(mWorkerXHR->Lock());
|
||||
mLastProgressOrLoadEvent.swap(newEvent);
|
||||
|
||||
if (newEvent) {
|
||||
// Already had a saved progress/load event so no need to generate
|
||||
// another. Bail out rather than dispatching runnable.
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mSyncEventQueue) {
|
||||
// If we're supposed to be capturing events for synchronous execution then
|
||||
// place this event in the queue.
|
||||
nsCOMPtr<nsIRunnable>* newElement =
|
||||
mSyncEventQueue->AppendElement(newEvent);
|
||||
mSyncEventQueue->AppendElement(runnable);
|
||||
NS_ENSURE_TRUE(newElement, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else {
|
||||
rv = nsDOMThreadService::get()->Dispatch(mWorkerXHR->mWorker, newEvent);
|
||||
else if (mSyncXHRThread) {
|
||||
// If we're running a sync XHR then schedule the event immediately for the
|
||||
// worker's thread.
|
||||
rv = mSyncXHRThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHRProxy::Abort()
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
RUN_PROXIED_FUNCTION(Abort, (this, &queue));
|
||||
return NS_OK;
|
||||
else {
|
||||
// Otherwise schedule it for the worker via the thread service.
|
||||
rv = nsDOMThreadService::get()->Dispatch(mWorkerXHR->mWorker, runnable);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIXMLHttpRequest> xhr = mXHR;
|
||||
if (mOwnedByXHR) {
|
||||
FlipOwnership();
|
||||
}
|
||||
|
||||
nsresult rv = xhr->Abort();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Don't allow further events from this channel.
|
||||
mChannelID++;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1027,8 +1242,11 @@ nsDOMWorkerXHRProxy::OpenRequest(const nsACString& aMethod,
|
|||
const nsAString& aPassword)
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
RUN_PROXIED_FUNCTION(OpenRequest, (this, &queue, aMethod, aUrl, aAsync,
|
||||
aUser, aPassword));
|
||||
mSyncRequest = !aAsync;
|
||||
|
||||
// Always do async behind the scenes!
|
||||
RUN_PROXIED_FUNCTION(OpenRequest,
|
||||
(aMethod, aUrl, PR_TRUE, aUser, aPassword));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1047,6 +1265,32 @@ nsDOMWorkerXHRProxy::OpenRequest(const nsACString& aMethod,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHRProxy::Abort()
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
RUN_PROXIED_FUNCTION(Abort, ());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIXMLHttpRequest> xhr = mXHR;
|
||||
|
||||
FlipOwnership();
|
||||
|
||||
nsresult rv = xhr->Abort();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Don't allow further events from this channel.
|
||||
mChannelID++;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsDOMWorkerXHRProxy::SyncEventQueue*
|
||||
nsDOMWorkerXHRProxy::SetSyncEventQueue(SyncEventQueue* aQueue)
|
||||
{
|
||||
|
@ -1059,7 +1303,7 @@ nsDOMWorkerXHRProxy::SetSyncEventQueue(SyncEventQueue* aQueue)
|
|||
nsresult
|
||||
nsDOMWorkerXHRProxy::GetAllResponseHeaders(char** _retval)
|
||||
{
|
||||
RUN_PROXIED_FUNCTION(GetAllResponseHeaders, (this, &queue, _retval));
|
||||
RUN_PROXIED_FUNCTION(GetAllResponseHeaders, (_retval));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1067,36 +1311,73 @@ nsresult
|
|||
nsDOMWorkerXHRProxy::GetResponseHeader(const nsACString& aHeader,
|
||||
nsACString& _retval)
|
||||
{
|
||||
RUN_PROXIED_FUNCTION(GetResponseHeader, (this, &queue, aHeader, _retval));
|
||||
RUN_PROXIED_FUNCTION(GetResponseHeader, (aHeader, _retval));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHRProxy::Send(nsIVariant* aBody)
|
||||
{
|
||||
RUN_PROXIED_FUNCTION(Send, (this, &queue, aBody));
|
||||
return NS_OK;
|
||||
NS_ASSERTION(!mSyncXHRThread, "Shouldn't reenter here!");
|
||||
|
||||
if (mSyncRequest) {
|
||||
|
||||
mSyncXHRThread = NS_GetCurrentThread();
|
||||
NS_ENSURE_TRUE(mSyncXHRThread, NS_ERROR_FAILURE);
|
||||
|
||||
nsAutoLock lock(mWorkerXHR->Lock());
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
mSyncFinishedRunnable =
|
||||
new nsDOMWorkerXHRFinishSyncXHRRunnable(this, mSyncXHRThread);
|
||||
NS_ENSURE_TRUE(mSyncFinishedRunnable, NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
RUN_PROXIED_FUNCTION(Send, (aBody));
|
||||
|
||||
return RunSyncEventLoop();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHRProxy::SendAsBinary(const nsAString& aBody)
|
||||
{
|
||||
RUN_PROXIED_FUNCTION(SendAsBinary, (this, &queue, aBody));
|
||||
return NS_OK;
|
||||
NS_ASSERTION(!mSyncXHRThread, "Shouldn't reenter here!");
|
||||
|
||||
if (mSyncRequest) {
|
||||
mSyncXHRThread = NS_GetCurrentThread();
|
||||
NS_ENSURE_TRUE(mSyncXHRThread, NS_ERROR_FAILURE);
|
||||
|
||||
nsAutoLock lock(mWorkerXHR->Lock());
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
mSyncFinishedRunnable =
|
||||
new nsDOMWorkerXHRFinishSyncXHRRunnable(this, mSyncXHRThread);
|
||||
NS_ENSURE_TRUE(mSyncFinishedRunnable, NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
RUN_PROXIED_FUNCTION(SendAsBinary, (aBody));
|
||||
|
||||
return RunSyncEventLoop();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHRProxy::SetRequestHeader(const nsACString& aHeader,
|
||||
const nsACString& aValue)
|
||||
{
|
||||
RUN_PROXIED_FUNCTION(SetRequestHeader, (this, &queue, aHeader, aValue));
|
||||
RUN_PROXIED_FUNCTION(SetRequestHeader, (aHeader, aValue));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHRProxy::OverrideMimeType(const nsACString& aMimetype)
|
||||
{
|
||||
RUN_PROXIED_FUNCTION(OverrideMimeType, (this, &queue, aMimetype));
|
||||
RUN_PROXIED_FUNCTION(OverrideMimeType, (aMimetype));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1109,14 +1390,28 @@ nsDOMWorkerXHRProxy::GetMultipart(PRBool* aMultipart)
|
|||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
RUN_PROXIED_FUNCTION(GetMultipart, (this, &queue, aMultipart));
|
||||
RUN_PROXIED_FUNCTION(GetMultipart, (aMultipart));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHRProxy::SetMultipart(PRBool aMultipart)
|
||||
{
|
||||
RUN_PROXIED_FUNCTION(SetMultipart, (this, &queue, aMultipart));
|
||||
RUN_PROXIED_FUNCTION(SetMultipart, (aMultipart));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHRProxy::GetWithCredentials(PRBool* aWithCredentials)
|
||||
{
|
||||
RUN_PROXIED_FUNCTION(GetWithCredentials, (aWithCredentials));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHRProxy::SetWithCredentials(PRBool aWithCredentials)
|
||||
{
|
||||
RUN_PROXIED_FUNCTION(SetWithCredentials, (aWithCredentials));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1168,6 +1463,30 @@ nsDOMWorkerXHRProxy::GetReadyState(PRInt32* _retval)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHRProxy::RunSyncEventLoop()
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (!mSyncRequest) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mSyncXHRThread == NS_GetCurrentThread(), "Wrong thread!");
|
||||
|
||||
while (mSyncXHRThread) {
|
||||
if (NS_UNLIKELY(!NS_ProcessNextEvent(mSyncXHRThread))) {
|
||||
NS_ERROR("Something wrong here, this shouldn't fail!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
|
||||
NS_ASSERTION(!NS_HasPendingEvents(NS_GetCurrentThread()),
|
||||
"Unprocessed events remaining!");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIRunnable
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHRProxy::Run()
|
||||
|
@ -1196,12 +1515,12 @@ nsDOMWorkerXHRProxy::OnStartRequest(nsIRequest* /* aRequest */,
|
|||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
NS_ASSERTION(!mOwnedByXHR, "Inconsistent state!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ASSERTION(!mOwnedByXHR, "Inconsistent state!");
|
||||
|
||||
FlipOwnership();
|
||||
|
||||
return NS_OK;
|
||||
|
@ -1215,13 +1534,20 @@ nsDOMWorkerXHRProxy::OnStopRequest(nsIRequest* /* aRequest */,
|
|||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mOwnedByXHR, "Inconsistent state!");
|
||||
|
||||
FlipOwnership();
|
||||
|
||||
nsRefPtr<nsDOMWorkerXHRFinishSyncXHRRunnable> syncFinishedRunnable;
|
||||
{
|
||||
nsAutoLock lock(mWorkerXHR->Lock());
|
||||
mSyncFinishedRunnable.swap(syncFinishedRunnable);
|
||||
}
|
||||
|
||||
if (syncFinishedRunnable) {
|
||||
nsresult rv = syncFinishedRunnable->Dispatch();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -57,15 +57,18 @@ class nsIThread;
|
|||
class nsIVariant;
|
||||
class nsIXMLHttpRequest;
|
||||
class nsDOMWorkerXHREvent;
|
||||
class nsDOMWorkerXHRFinishSyncXHRRunnable;
|
||||
class nsDOMWorkerXHRWrappedListener;
|
||||
class nsXMLHttpRequest;
|
||||
|
||||
class nsDOMWorkerXHRProxy : public nsRunnable,
|
||||
class nsDOMWorkerXHRProxy : public nsIRunnable,
|
||||
public nsIDOMEventListener,
|
||||
public nsIRequestObserver
|
||||
{
|
||||
friend class nsDOMWorkerXHRAttachUploadListenersRunnable;
|
||||
friend class nsDOMWorkerXHREvent;
|
||||
friend class nsDOMWorkerXHRFinishSyncXHRRunnable;
|
||||
friend class nsDOMWorkerXHRLastProgressOrLoadEvent;
|
||||
friend class nsDOMWorkerXHR;
|
||||
friend class nsDOMWorkerXHRUpload;
|
||||
|
||||
|
@ -80,7 +83,7 @@ class nsDOMWorkerXHRProxy : public nsRunnable,
|
|||
public:
|
||||
typedef nsAutoTArray<nsCOMPtr<nsIRunnable>, 5> SyncEventQueue;
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
NS_DECL_NSIRUNNABLE
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
|
@ -92,14 +95,14 @@ public:
|
|||
|
||||
nsIXMLHttpRequest* GetXMLHttpRequest();
|
||||
|
||||
nsresult Abort();
|
||||
|
||||
nsresult OpenRequest(const nsACString& aMethod,
|
||||
const nsACString& aUrl,
|
||||
PRBool aAsync,
|
||||
const nsAString& aUser,
|
||||
const nsAString& aPassword);
|
||||
|
||||
nsresult Abort();
|
||||
|
||||
SyncEventQueue* SetSyncEventQueue(SyncEventQueue* aQueue);
|
||||
|
||||
PRInt32 ChannelID() {
|
||||
|
@ -112,6 +115,7 @@ protected:
|
|||
|
||||
nsresult Destroy();
|
||||
|
||||
void AddRemoveXHRListeners(PRBool aAdd);
|
||||
void FlipOwnership();
|
||||
|
||||
nsresult AddEventListener(PRUint32 aType,
|
||||
|
@ -151,6 +155,14 @@ protected:
|
|||
nsresult OverrideMimeType(const nsACString& aMimetype);
|
||||
nsresult GetMultipart(PRBool* aMultipart);
|
||||
nsresult SetMultipart(PRBool aMultipart);
|
||||
nsresult GetWithCredentials(PRBool* aWithCredentials);
|
||||
nsresult SetWithCredentials(PRBool aWithCredentials);
|
||||
|
||||
nsresult RunSyncEventLoop();
|
||||
|
||||
// aEvent is used to see if we should check upload listeners as well. If left
|
||||
// unset we always check upload listeners.
|
||||
PRBool HasListenersForType(PRUint32 aType, nsIDOMEvent* aEvent = nsnull);
|
||||
|
||||
// May be weak or strong, check mOwnedByXHR.
|
||||
nsDOMWorkerXHR* mWorkerXHR;
|
||||
|
@ -165,6 +177,7 @@ protected:
|
|||
nsCOMPtr<nsIThread> mMainThread;
|
||||
|
||||
nsRefPtr<nsDOMWorkerXHREvent> mLastXHREvent;
|
||||
nsRefPtr<nsDOMWorkerXHREvent> mLastProgressOrLoadEvent;
|
||||
|
||||
nsTArray<ListenerArray> mXHRListeners;
|
||||
nsTArray<WrappedListener> mXHROnXListeners;
|
||||
|
@ -176,11 +189,19 @@ protected:
|
|||
|
||||
PRInt32 mChannelID;
|
||||
|
||||
// Only touched on the worker thread!
|
||||
nsCOMPtr<nsIThread> mSyncXHRThread;
|
||||
|
||||
// Touched on more than one thread, protected by the worker's lock.
|
||||
nsRefPtr<nsDOMWorkerXHRFinishSyncXHRRunnable> mSyncFinishedRunnable;
|
||||
|
||||
// Whether or not this object is owned by the real XHR object.
|
||||
PRPackedBool mOwnedByXHR;
|
||||
|
||||
PRPackedBool mWantUploadListeners;
|
||||
PRPackedBool mCanceled;
|
||||
|
||||
PRPackedBool mSyncRequest;
|
||||
};
|
||||
|
||||
#endif /* __NSDOMWORKERXHRPROXY_H__ */
|
||||
|
|
Загрузка…
Ссылка в новой задаче