зеркало из https://github.com/mozilla/pjs.git
Bug 450452 - "Implement XHR ('minus X') for worker threads". r+sr=jst.
This commit is contained in:
Родитель
a04e2e37a1
Коммит
4f737aafd3
|
@ -101,7 +101,7 @@ interface nsIXMLHttpRequestUpload : nsIXMLHttpRequestEventTarget {
|
|||
* you're aware of all the security implications. And then think twice about
|
||||
* it.
|
||||
*/
|
||||
[scriptable, uuid(acda85ab-d06c-4176-b834-6d129ca97ca3)]
|
||||
[scriptable, uuid(ae8f1468-cd7f-4aea-9c40-a3f085db9369)]
|
||||
interface nsIXMLHttpRequest : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -334,78 +334,11 @@ interface nsIXMLHttpRequest : nsISupports
|
|||
[noscript] void init(in nsIPrincipal principal,
|
||||
in nsIScriptContext scriptContext,
|
||||
in nsPIDOMWindow ownerWindow);
|
||||
};
|
||||
|
||||
[scriptable, uuid(6e127bd2-b4c1-4a82-be0d-012bd24efb37)]
|
||||
interface nsIXMLHttpRequestUploadGetter : nsISupports {
|
||||
/**
|
||||
* Upload process can be tracked by adding event listener to |upload|.
|
||||
*/
|
||||
readonly attribute nsIXMLHttpRequestUpload upload;
|
||||
};
|
||||
|
||||
[scriptable, uuid(261676b4-d508-43bf-b099-74635a0ee2e9)]
|
||||
interface nsIJSXMLHttpRequest : nsISupports {
|
||||
/**
|
||||
* Meant to be a script-only mechanism for setting a load event listener.
|
||||
* The attribute is expected to be JavaScript function object. When
|
||||
* the load event occurs, the function is invoked.
|
||||
* This attribute should not be used from native code!!
|
||||
*
|
||||
* After the initial response, all event listeners will be cleared.
|
||||
* // XXXbz what does that mean, exactly?
|
||||
*
|
||||
* Call open() before setting an onload listener.
|
||||
*
|
||||
* Mozilla only.
|
||||
*/
|
||||
attribute nsIDOMEventListener onload;
|
||||
|
||||
/**
|
||||
* Meant to be a script-only mechanism for setting an error event listener.
|
||||
* The attribute is expected to be JavaScript function object. When
|
||||
* the error event occurs, the function is invoked.
|
||||
* This attribute should not be used from native code!!
|
||||
*
|
||||
* After the initial response, all event listeners will be cleared.
|
||||
* // XXXbz what does that mean, exactly?
|
||||
*
|
||||
* Call open() before setting an onerror listener.
|
||||
*
|
||||
* Mozilla only.
|
||||
*/
|
||||
attribute nsIDOMEventListener onerror;
|
||||
|
||||
/**
|
||||
* Meant to be a script-only mechanism for setting a progress event listener.
|
||||
* The attribute is expected to be JavaScript function object. When
|
||||
* the error event occurs, the function is invoked.
|
||||
* This attribute should not be used from native code!!
|
||||
* This event listener may be called multiple times during the open request.
|
||||
*
|
||||
* After the initial response, all event listeners will be cleared.
|
||||
* // XXXbz what does that mean, exactly?
|
||||
*
|
||||
* This event listener must be set BEFORE calling open().
|
||||
*
|
||||
* Mozilla only.
|
||||
*/
|
||||
attribute nsIDOMEventListener onprogress;
|
||||
|
||||
/**
|
||||
* Meant to be a script-only mechanism for setting an upload progress event
|
||||
* listener.
|
||||
* This attribute should not be used from native code!!
|
||||
* This event listener may be called multiple times during the upload..
|
||||
*
|
||||
* After the initial response, all event listeners will be cleared.
|
||||
* // XXXbz what does that mean, exactly?
|
||||
*
|
||||
* This event listener must be set BEFORE calling open().
|
||||
*
|
||||
* Mozilla only.
|
||||
*/
|
||||
attribute nsIDOMEventListener onuploadprogress;
|
||||
|
||||
/**
|
||||
* Meant to be a script-only mechanism for setting a callback function.
|
||||
|
@ -421,6 +354,27 @@ interface nsIJSXMLHttpRequest : nsISupports {
|
|||
attribute nsIDOMEventListener onreadystatechange;
|
||||
};
|
||||
|
||||
/**
|
||||
* DEPRECATED.
|
||||
*/
|
||||
[scriptable, uuid(261676b4-d508-43bf-b099-74635a0ee2e9)]
|
||||
interface nsIJSXMLHttpRequest : nsISupports {
|
||||
/**
|
||||
* Meant to be a script-only mechanism for setting an upload progress event
|
||||
* listener.
|
||||
* This attribute should not be used from native code!!
|
||||
* This event listener may be called multiple times during the upload..
|
||||
*
|
||||
* After the initial response, all event listeners will be cleared.
|
||||
* // XXXbz what does that mean, exactly?
|
||||
*
|
||||
* This event listener must be set BEFORE calling open().
|
||||
*
|
||||
* Mozilla only.
|
||||
*/
|
||||
attribute nsIDOMEventListener onuploadprogress;
|
||||
};
|
||||
|
||||
%{ C++
|
||||
#define NS_XMLHTTPREQUEST_CID \
|
||||
{ /* d164e770-4157-11d4-9a42-000064657374 */ \
|
||||
|
|
|
@ -611,8 +611,9 @@ nsXMLHttpRequestUpload::GetContextForEventHandlers(nsIScriptContext** aContext)
|
|||
/////////////////////////////////////////////
|
||||
|
||||
nsXMLHttpRequest::nsXMLHttpRequest()
|
||||
: mState(XML_HTTP_REQUEST_UNINITIALIZED), mUploadTransferred(0),
|
||||
mUploadTotal(0), mUploadComplete(PR_TRUE), mErrorLoad(PR_FALSE)
|
||||
: mRequestObserver(nsnull), mState(XML_HTTP_REQUEST_UNINITIALIZED),
|
||||
mUploadTransferred(0), mUploadTotal(0), mUploadComplete(PR_TRUE),
|
||||
mErrorLoad(PR_FALSE), mFirstStartRequestSeen(PR_FALSE)
|
||||
{
|
||||
nsLayoutStatics::AddRef();
|
||||
}
|
||||
|
@ -727,6 +728,12 @@ nsXMLHttpRequest::Initialize(nsISupports* aOwner, JSContext* cx, JSObject* obj,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsXMLHttpRequest::SetRequestObserver(nsIRequestObserver* aObserver)
|
||||
{
|
||||
mRequestObserver = aObserver;
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLHttpRequest)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXMLHttpRequest,
|
||||
|
@ -776,7 +783,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsXMLHttpRequest)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIXMLHttpRequest)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIJSXMLHttpRequest)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIXMLHttpRequestUploadGetter)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMLoadListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
|
||||
|
@ -1565,6 +1571,11 @@ IsSameOrBaseChannel(nsIRequest* aPossibleBase, nsIChannel* aChannel)
|
|||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
|
||||
{
|
||||
if (!mFirstStartRequestSeen && mRequestObserver) {
|
||||
mFirstStartRequestSeen = PR_TRUE;
|
||||
mRequestObserver->OnStartRequest(request, ctxt);
|
||||
}
|
||||
|
||||
if (!IsSameOrBaseChannel(request, mChannel)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1785,6 +1796,12 @@ nsXMLHttpRequest::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult
|
|||
|
||||
mState &= ~XML_HTTP_REQUEST_SYNCLOOPING;
|
||||
|
||||
if (mRequestObserver && mState & XML_HTTP_REQUEST_GOT_FINAL_STOP) {
|
||||
NS_ASSERTION(mFirstStartRequestSeen, "Inconsistent state!");
|
||||
mFirstStartRequestSeen = PR_FALSE;
|
||||
mRequestObserver->OnStopRequest(request, ctxt, status);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -165,8 +165,7 @@ class nsXMLHttpRequest : public nsXHREventTarget,
|
|||
public nsIProgressEventSink,
|
||||
public nsIInterfaceRequestor,
|
||||
public nsSupportsWeakReference,
|
||||
public nsIJSNativeInitializer,
|
||||
public nsIXMLHttpRequestUploadGetter
|
||||
public nsIJSNativeInitializer
|
||||
{
|
||||
public:
|
||||
nsXMLHttpRequest();
|
||||
|
@ -180,17 +179,12 @@ public:
|
|||
// nsIJSXMLHttpRequest
|
||||
NS_IMETHOD GetOnuploadprogress(nsIDOMEventListener** aOnuploadprogress);
|
||||
NS_IMETHOD SetOnuploadprogress(nsIDOMEventListener* aOnuploadprogress);
|
||||
NS_IMETHOD GetOnreadystatechange(nsIDOMEventListener** aOnreadystatechange);
|
||||
NS_IMETHOD SetOnreadystatechange(nsIDOMEventListener* aOnreadystatechange);
|
||||
|
||||
NS_FORWARD_NSIXMLHTTPREQUESTEVENTTARGET(nsXHREventTarget::)
|
||||
|
||||
// nsIDOMEventListener
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
|
||||
// nsIXMLHttpRequestUploadGetter
|
||||
NS_DECL_NSIXMLHTTPREQUESTUPLOADGETTER
|
||||
|
||||
// nsIDOMLoadListener
|
||||
NS_IMETHOD Load(nsIDOMEvent* aEvent);
|
||||
NS_IMETHOD BeforeUnload(nsIDOMEvent* aEvent);
|
||||
|
@ -250,6 +244,8 @@ public:
|
|||
// This is called by the factory constructor.
|
||||
nsresult Init();
|
||||
|
||||
void SetRequestObserver(nsIRequestObserver* aObserver);
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXMLHttpRequest,
|
||||
nsXHREventTarget)
|
||||
|
||||
|
@ -345,6 +341,8 @@ protected:
|
|||
nsCOMPtr<nsIChannelEventSink> mChannelEventSink;
|
||||
nsCOMPtr<nsIProgressEventSink> mProgressEventSink;
|
||||
|
||||
nsIRequestObserver* mRequestObserver;
|
||||
|
||||
PRUint32 mState;
|
||||
|
||||
// List of potentially dangerous headers explicitly set using
|
||||
|
@ -357,6 +355,8 @@ protected:
|
|||
PRPackedBool mUploadComplete;
|
||||
|
||||
PRPackedBool mErrorLoad;
|
||||
|
||||
PRPackedBool mFirstStartRequestSeen;
|
||||
};
|
||||
|
||||
// helper class to expose a progress DOM Event
|
||||
|
|
|
@ -3385,7 +3385,6 @@ nsDOMClassInfo::Init()
|
|||
DOM_CLASSINFO_MAP_ENTRY(nsIXMLHttpRequest)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIJSXMLHttpRequest)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIXMLHttpRequestEventTarget)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIXMLHttpRequestUploadGetter)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIInterfaceRequestor)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
|
|
@ -68,6 +68,8 @@
|
|||
|
||||
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
||||
|
||||
nsIExceptionProvider* gExceptionProvider = nsnull;
|
||||
|
||||
nsDOMScriptObjectFactory::nsDOMScriptObjectFactory() :
|
||||
mLoadedAllLanguages(PR_FALSE)
|
||||
{
|
||||
|
@ -78,18 +80,25 @@ nsDOMScriptObjectFactory::nsDOMScriptObjectFactory() :
|
|||
observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIExceptionService> xs =
|
||||
do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID);
|
||||
nsCOMPtr<nsIExceptionProvider> provider(new nsDOMExceptionProvider());
|
||||
if (provider) {
|
||||
nsCOMPtr<nsIExceptionService> xs =
|
||||
do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID);
|
||||
|
||||
if (xs) {
|
||||
xs->RegisterExceptionProvider(this, NS_ERROR_MODULE_DOM);
|
||||
xs->RegisterExceptionProvider(this, NS_ERROR_MODULE_DOM_RANGE);
|
||||
if (xs) {
|
||||
xs->RegisterExceptionProvider(provider, NS_ERROR_MODULE_DOM);
|
||||
xs->RegisterExceptionProvider(provider, NS_ERROR_MODULE_DOM_RANGE);
|
||||
#ifdef MOZ_SVG
|
||||
xs->RegisterExceptionProvider(this, NS_ERROR_MODULE_SVG);
|
||||
xs->RegisterExceptionProvider(provider, NS_ERROR_MODULE_SVG);
|
||||
#endif
|
||||
xs->RegisterExceptionProvider(this, NS_ERROR_MODULE_DOM_XPATH);
|
||||
xs->RegisterExceptionProvider(this, NS_ERROR_MODULE_XPCONNECT);
|
||||
xs->RegisterExceptionProvider(provider, NS_ERROR_MODULE_DOM_XPATH);
|
||||
xs->RegisterExceptionProvider(provider, NS_ERROR_MODULE_XPCONNECT);
|
||||
}
|
||||
|
||||
NS_ASSERTION(!gExceptionProvider, "Registered twice?!");
|
||||
provider.swap(gExceptionProvider);
|
||||
}
|
||||
|
||||
// And pre-create the javascript language.
|
||||
NS_CreateJSRuntime(getter_AddRefs(mLanguageArray[NS_STID_INDEX(nsIProgrammingLanguage::JAVASCRIPT)]));
|
||||
}
|
||||
|
@ -97,7 +106,6 @@ nsDOMScriptObjectFactory::nsDOMScriptObjectFactory() :
|
|||
NS_INTERFACE_MAP_BEGIN(nsDOMScriptObjectFactory)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMScriptObjectFactory)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIExceptionProvider)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMScriptObjectFactory)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
|
@ -287,17 +295,26 @@ nsDOMScriptObjectFactory::Observe(nsISupports *aSubject,
|
|||
nsGlobalWindow::ShutDown();
|
||||
nsDOMClassInfo::ShutDown();
|
||||
|
||||
nsCOMPtr<nsIExceptionService> xs =
|
||||
do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID);
|
||||
if (gExceptionProvider) {
|
||||
nsCOMPtr<nsIExceptionService> xs =
|
||||
do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID);
|
||||
|
||||
if (xs) {
|
||||
xs->UnregisterExceptionProvider(this, NS_ERROR_MODULE_DOM);
|
||||
xs->UnregisterExceptionProvider(this, NS_ERROR_MODULE_DOM_RANGE);
|
||||
if (xs) {
|
||||
xs->UnregisterExceptionProvider(gExceptionProvider,
|
||||
NS_ERROR_MODULE_DOM);
|
||||
xs->UnregisterExceptionProvider(gExceptionProvider,
|
||||
NS_ERROR_MODULE_DOM_RANGE);
|
||||
#ifdef MOZ_SVG
|
||||
xs->UnregisterExceptionProvider(this, NS_ERROR_MODULE_SVG);
|
||||
xs->UnregisterExceptionProvider(gExceptionProvider,
|
||||
NS_ERROR_MODULE_SVG);
|
||||
#endif
|
||||
xs->UnregisterExceptionProvider(this, NS_ERROR_MODULE_DOM_XPATH);
|
||||
xs->UnregisterExceptionProvider(this, NS_ERROR_MODULE_XPCONNECT);
|
||||
xs->UnregisterExceptionProvider(gExceptionProvider,
|
||||
NS_ERROR_MODULE_DOM_XPATH);
|
||||
xs->UnregisterExceptionProvider(gExceptionProvider,
|
||||
NS_ERROR_MODULE_XPCONNECT);
|
||||
}
|
||||
|
||||
NS_RELEASE(gExceptionProvider);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -325,30 +342,6 @@ CreateXPConnectException(nsresult aResult, nsIException *aDefaultException,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMScriptObjectFactory::GetException(nsresult result,
|
||||
nsIException *aDefaultException,
|
||||
nsIException **_retval)
|
||||
{
|
||||
switch (NS_ERROR_GET_MODULE(result))
|
||||
{
|
||||
case NS_ERROR_MODULE_DOM_RANGE:
|
||||
return NS_NewRangeException(result, aDefaultException, _retval);
|
||||
#ifdef MOZ_SVG
|
||||
case NS_ERROR_MODULE_SVG:
|
||||
return NS_NewSVGException(result, aDefaultException, _retval);
|
||||
#endif
|
||||
case NS_ERROR_MODULE_DOM_XPATH:
|
||||
return NS_NewXPathException(result, aDefaultException, _retval);
|
||||
case NS_ERROR_MODULE_XPCONNECT:
|
||||
return CreateXPConnectException(result, aDefaultException, _retval);
|
||||
case NS_ERROR_MODULE_DOM_FILE:
|
||||
return NS_NewFileException(result, aDefaultException, _retval);
|
||||
default:
|
||||
return NS_NewDOMException(result, aDefaultException, _retval);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMScriptObjectFactory::RegisterDOMClassInfo(const char *aName,
|
||||
nsDOMClassInfoExternalConstructorFnc aConstructorFptr,
|
||||
|
@ -394,3 +387,31 @@ nsresult NS_GetScriptRuntimeByID(PRUint32 aScriptTypeID,
|
|||
return rv;
|
||||
return factory->GetScriptRuntimeByID(aScriptTypeID, aLanguage);
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsDOMExceptionProvider, nsIExceptionProvider)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMExceptionProvider::GetException(nsresult result,
|
||||
nsIException *aDefaultException,
|
||||
nsIException **_retval)
|
||||
{
|
||||
switch (NS_ERROR_GET_MODULE(result))
|
||||
{
|
||||
case NS_ERROR_MODULE_DOM_RANGE:
|
||||
return NS_NewRangeException(result, aDefaultException, _retval);
|
||||
#ifdef MOZ_SVG
|
||||
case NS_ERROR_MODULE_SVG:
|
||||
return NS_NewSVGException(result, aDefaultException, _retval);
|
||||
#endif
|
||||
case NS_ERROR_MODULE_DOM_XPATH:
|
||||
return NS_NewXPathException(result, aDefaultException, _retval);
|
||||
case NS_ERROR_MODULE_XPCONNECT:
|
||||
return CreateXPConnectException(result, aDefaultException, _retval);
|
||||
case NS_ERROR_MODULE_DOM_FILE:
|
||||
return NS_NewFileException(result, aDefaultException, _retval);
|
||||
default:
|
||||
return NS_NewDOMException(result, aDefaultException, _retval);
|
||||
}
|
||||
NS_NOTREACHED("Not reached");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
|
|
@ -57,8 +57,7 @@
|
|||
#include "nsIScriptGlobalObject.h" // for misplaced NS_STID_ macros.
|
||||
|
||||
class nsDOMScriptObjectFactory : public nsIDOMScriptObjectFactory,
|
||||
public nsIObserver,
|
||||
public nsIExceptionProvider
|
||||
public nsIObserver
|
||||
{
|
||||
public:
|
||||
nsDOMScriptObjectFactory();
|
||||
|
@ -68,9 +67,6 @@ public:
|
|||
// nsIObserver
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
// nsIExceptionProvider
|
||||
NS_DECL_NSIEXCEPTIONPROVIDER
|
||||
|
||||
// nsIDOMScriptObjectFactory
|
||||
NS_IMETHOD GetScriptRuntime(const nsAString &aLanguageName,
|
||||
nsIScriptRuntime **aLanguage);
|
||||
|
@ -100,3 +96,10 @@ protected:
|
|||
PRBool mLoadedAllLanguages;
|
||||
nsCOMPtr<nsIScriptRuntime> mLanguageArray[NS_STID_ARRAY_UBOUND];
|
||||
};
|
||||
|
||||
class nsDOMExceptionProvider : public nsIExceptionProvider
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIEXCEPTIONPROVIDER
|
||||
};
|
||||
|
|
|
@ -867,6 +867,14 @@ nsGlobalWindow::FreeInnerObjects(PRBool aClearScope)
|
|||
// Kill all of the workers for this window.
|
||||
nsDOMThreadService* dts = nsDOMThreadService::get();
|
||||
if (dts) {
|
||||
nsIScriptContext *scx = GetContextInternal();
|
||||
|
||||
JSContext *cx = scx ? (JSContext *)scx->GetNativeContext() : nsnull;
|
||||
|
||||
// Have to suspend this request here because CancelWorkersForGlobal will
|
||||
// lock until the worker has died and that could cause a deadlock.
|
||||
JSAutoSuspendRequest asr(cx);
|
||||
|
||||
dts->CancelWorkersForGlobal(static_cast<nsIScriptGlobalObject*>(this));
|
||||
}
|
||||
|
||||
|
|
|
@ -51,11 +51,14 @@ FORCE_STATIC_LIB = 1
|
|||
REQUIRES = \
|
||||
caps \
|
||||
content \
|
||||
gfx \
|
||||
js \
|
||||
layout \
|
||||
locale \
|
||||
necko \
|
||||
pref \
|
||||
string \
|
||||
thebes \
|
||||
widget \
|
||||
xpcom \
|
||||
xpconnect \
|
||||
|
@ -69,10 +72,14 @@ CPPSRCS = \
|
|||
nsDOMWorkerSecurityManager.cpp \
|
||||
nsDOMWorkerThread.cpp \
|
||||
nsDOMWorkerTimeout.cpp \
|
||||
nsDOMWorkerXHR.cpp \
|
||||
nsDOMWorkerXHRProxy.cpp \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
-I$(topsrcdir)/dom/src/base \
|
||||
-I$(topsrcdir)/content/base/src \
|
||||
-I$(topsrcdir)/content/events/src \
|
||||
$(NULL)
|
||||
|
||||
ifdef ENABLE_TESTS
|
||||
|
@ -80,3 +87,5 @@ DIRS += test
|
|||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
#CXXFLAGS += $(WARNINGS_AS_ERRORS)
|
||||
|
|
|
@ -478,6 +478,13 @@ DOMWorkerErrorReporter(JSContext* aCx,
|
|||
|
||||
nsDOMWorkerThread* worker = (nsDOMWorkerThread*)JS_GetContextPrivate(aCx);
|
||||
|
||||
if (worker->IsCanceled()) {
|
||||
// We don't want to report errors from canceled workers. It's very likely
|
||||
// that we only returned an error in the first place because the worker was
|
||||
// already canceled.
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIScriptError> errorObject =
|
||||
do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
|
||||
|
|
|
@ -78,6 +78,8 @@ class nsDOMThreadService : public nsIEventTarget,
|
|||
friend class nsDOMWorkerRunnable;
|
||||
friend class nsDOMWorkerThread;
|
||||
friend class nsDOMWorkerTimeout;
|
||||
friend class nsDOMWorkerXHR;
|
||||
friend class nsDOMWorkerXHRProxy;
|
||||
friend class nsLayoutStatics;
|
||||
|
||||
public:
|
||||
|
|
|
@ -92,12 +92,16 @@ public:
|
|||
getter_AddRefs(targetIsPool));
|
||||
#endif
|
||||
|
||||
LOG(("Posting message '%s' from %s [0x%p] to %s [0x%p]",
|
||||
utf8Message.get(), sourceIsPool ? poolStr : workerStr,
|
||||
static_cast<void*>(mSource.get()), targetIsPool ? poolStr : workerStr,
|
||||
static_cast<void*>(mTarget.get())));
|
||||
if (!(mTarget->IsCanceled() || mSource->IsCanceled())) {
|
||||
LOG(("Posting message '%s' from %s [0x%p] to %s [0x%p]",
|
||||
utf8Message.get(),
|
||||
sourceIsPool ? poolStr : workerStr,
|
||||
static_cast<void*>(mSource.get()),
|
||||
targetIsPool ? poolStr : workerStr,
|
||||
static_cast<void*>(mTarget.get())));
|
||||
|
||||
mTarget->HandleMessage(mMessage, mSource);
|
||||
mTarget->HandleMessage(mMessage, mSource);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "nsDOMWorkerPool.h"
|
||||
|
||||
// Interfaces
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMClassInfo.h"
|
||||
#include "nsIJSContextStack.h"
|
||||
#include "nsIScriptContext.h"
|
||||
|
@ -102,15 +103,8 @@ nsDOMWorkerPool::Init()
|
|||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
// GetCurrentJSContext () can return a null context... We shouldn't
|
||||
// ever see that here.
|
||||
JSContext* cx = nsContentUtils::GetCurrentJSContext();
|
||||
NS_ENSURE_TRUE(cx, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsIScriptContext* scriptContext = GetScriptContextFromJSContext(cx);
|
||||
NS_ENSURE_STATE(scriptContext);
|
||||
|
||||
nsIScriptGlobalObject* globalObject = scriptContext->GetGlobalObject();
|
||||
nsIScriptGlobalObject* globalObject =
|
||||
mParentDocument->GetScriptGlobalObject();
|
||||
NS_ENSURE_STATE(globalObject);
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> domWindow(do_QueryInterface(globalObject));
|
||||
|
@ -237,13 +231,22 @@ nsDOMWorkerPool::ResumeWorkersForGlobal(nsIScriptGlobalObject* aGlobalObject)
|
|||
}
|
||||
|
||||
nsIDocument*
|
||||
nsDOMWorkerPool::GetParentDocument()
|
||||
nsDOMWorkerPool::ParentDocument()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(),
|
||||
"Don't touch the non-threadsafe document off the main thread!");
|
||||
return mParentDocument;
|
||||
}
|
||||
|
||||
nsIScriptContext*
|
||||
nsDOMWorkerPool::ScriptContext()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(),
|
||||
"Don't touch the non-threadsafe script context off the main "
|
||||
"thread!");
|
||||
return mParentDocument->GetScriptGlobalObject()->GetContext();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerPool::PostMessage(const nsAString& aMessage)
|
||||
{
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
|
||||
class nsDOMWorkerThread;
|
||||
class nsIDocument;
|
||||
class nsIScriptContext;
|
||||
class nsIScriptError;
|
||||
class nsIScriptGlobalObject;
|
||||
|
||||
|
@ -84,6 +85,9 @@ public:
|
|||
return this;
|
||||
}
|
||||
|
||||
nsIDocument* ParentDocument();
|
||||
nsIScriptContext* ScriptContext();
|
||||
|
||||
private:
|
||||
virtual ~nsDOMWorkerPool();
|
||||
|
||||
|
@ -109,8 +113,6 @@ private:
|
|||
return mMonitor;
|
||||
}
|
||||
|
||||
nsIDocument* GetParentDocument();
|
||||
|
||||
// Weak reference to the window that created and owns this pool.
|
||||
nsISupports* mParentGlobal;
|
||||
|
||||
|
|
|
@ -126,7 +126,13 @@ nsDOMWorkerScriptLoader::LoadScripts(nsDOMWorkerThread* aWorker,
|
|||
|
||||
{
|
||||
JSAutoSuspendRequest asr(aCx);
|
||||
|
||||
nsAutoLock lock(mWorker->Lock());
|
||||
|
||||
if (mWorker->IsCanceled()) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
mTrackedByWorker = nsnull != mWorker->mScriptLoaders.AppendElement(this);
|
||||
NS_ASSERTION(mTrackedByWorker, "Failed to add loader to worker's array!");
|
||||
}
|
||||
|
@ -442,7 +448,7 @@ nsDOMWorkerScriptLoader::RunInternal()
|
|||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
// Things we need to make all this work...
|
||||
nsIDocument* parentDoc = mWorker->Pool()->GetParentDocument();
|
||||
nsIDocument* parentDoc = mWorker->Pool()->ParentDocument();
|
||||
NS_ASSERTION(parentDoc, "Null parent document?!");
|
||||
|
||||
// All of these can potentially be null, but that should be ok. We'll either
|
||||
|
@ -578,7 +584,7 @@ nsDOMWorkerScriptLoader::OnStreamCompleteInternal(nsIStreamLoader* aLoader,
|
|||
return rv = NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
nsIDocument* parentDoc = mWorker->Pool()->GetParentDocument();
|
||||
nsIDocument* parentDoc = mWorker->Pool()->ParentDocument();
|
||||
NS_ASSERTION(parentDoc, "Null parent document?!");
|
||||
|
||||
// Use the regular nsScriptLoader for this grunt work! Should be just fine
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
#include "nsDOMWorkerSecurityManager.h"
|
||||
#include "nsDOMThreadService.h"
|
||||
#include "nsDOMWorkerTimeout.h"
|
||||
#include "nsDOMWorkerXHR.h"
|
||||
|
||||
#define LOG(_args) PR_LOG(gDOMThreadsLog, PR_LOG_DEBUG, _args)
|
||||
|
||||
|
@ -100,6 +101,9 @@ public:
|
|||
static JSBool LoadScripts(JSContext* aCx, JSObject* aObj, uintN aArgc,
|
||||
jsval* aArgv, jsval* aRval);
|
||||
|
||||
static JSBool NewXMLHttpRequest(JSContext* aCx, JSObject* aObj, uintN aArgc,
|
||||
jsval* aArgv, jsval* aRval);
|
||||
|
||||
private:
|
||||
// Internal helper for SetTimeout and SetInterval.
|
||||
static JSBool MakeTimeout(JSContext* aCx, JSObject* aObj, uintN aArgc,
|
||||
|
@ -303,6 +307,63 @@ nsDOMWorkerFunctions::LoadScripts(JSContext* aCx,
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
nsDOMWorkerFunctions::NewXMLHttpRequest(JSContext* aCx,
|
||||
JSObject* aObj,
|
||||
uintN aArgc,
|
||||
jsval* /* aArgv */,
|
||||
jsval* aRval)
|
||||
{
|
||||
nsDOMWorkerThread* worker =
|
||||
static_cast<nsDOMWorkerThread*>(JS_GetContextPrivate(aCx));
|
||||
NS_ASSERTION(worker, "This should be set by the DOM thread service!");
|
||||
|
||||
if (worker->IsCanceled()) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (aArgc) {
|
||||
JS_ReportError(aCx, "Constructor takes no arguments!");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
nsRefPtr<nsDOMWorkerXHR> xhr = new nsDOMWorkerXHR(worker);
|
||||
if (!xhr) {
|
||||
JS_ReportOutOfMemory(aCx);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
nsresult rv = xhr->Init();
|
||||
if (NS_FAILED(rv)) {
|
||||
JS_ReportError(aCx, "Failed to construct XHR!");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> xhrSupports;
|
||||
xhr->QueryInterface(NS_GET_IID(nsISupports), getter_AddRefs(xhrSupports));
|
||||
NS_ASSERTION(xhrSupports, "Impossible!");
|
||||
|
||||
nsIXPConnect* xpc = nsContentUtils::XPConnect();
|
||||
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> xhrWrapped;
|
||||
rv = xpc->WrapNative(aCx, aObj, xhrSupports, NS_GET_IID(nsIXMLHttpRequest),
|
||||
getter_AddRefs(xhrWrapped));
|
||||
if (NS_FAILED(rv)) {
|
||||
JS_ReportError(aCx, "Failed to wrap XHR!");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSObject* xhrJSObj;
|
||||
rv = xhrWrapped->GetJSObject(&xhrJSObj);
|
||||
if (NS_FAILED(rv)) {
|
||||
JS_ReportError(aCx, "Failed to get JSObject!");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
*aRval = OBJECT_TO_JSVAL(xhrJSObj);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSFunctionSpec gDOMWorkerFunctions[] = {
|
||||
{ "dump", nsDOMWorkerFunctions::Dump, 1, 0, 0 },
|
||||
{ "debug", nsDOMWorkerFunctions::DebugDump, 1, 0, 0 },
|
||||
|
@ -312,6 +373,7 @@ JSFunctionSpec gDOMWorkerFunctions[] = {
|
|||
{ "setInterval", nsDOMWorkerFunctions::SetInterval, 1, 0, 0 },
|
||||
{ "clearInterval", nsDOMWorkerFunctions::KillTimeout, 1, 0, 0 },
|
||||
{ "loadScripts", nsDOMWorkerFunctions::LoadScripts, 1, 0, 0 },
|
||||
{ "XMLHttpRequest", nsDOMWorkerFunctions::NewXMLHttpRequest, 0, 0, 0 },
|
||||
#ifdef MOZ_SHARK
|
||||
{ "startShark", js_StartShark, 0, 0, 0 },
|
||||
{ "stopShark", js_StopShark, 0, 0, 0 },
|
||||
|
@ -551,6 +613,7 @@ nsDOMWorkerThread::Cancel()
|
|||
|
||||
// Do this before waiting on the thread service below!
|
||||
CancelScriptLoaders();
|
||||
CancelXHRs();
|
||||
|
||||
// If we're suspended there's a good chance that we're already paused waiting
|
||||
// on the pool's monitor. Waiting on the thread service's lock will deadlock.
|
||||
|
@ -717,7 +780,7 @@ nsDOMWorkerThread::NextTimeout(nsDOMWorkerTimeout* aTimeout)
|
|||
return next == &mTimeouts ? nsnull : next;
|
||||
}
|
||||
|
||||
void
|
||||
PRBool
|
||||
nsDOMWorkerThread::AddTimeout(nsDOMWorkerTimeout* aTimeout)
|
||||
{
|
||||
// This should only ever be called on the worker thread... but there's no way
|
||||
|
@ -733,6 +796,10 @@ nsDOMWorkerThread::AddTimeout(nsDOMWorkerTimeout* aTimeout)
|
|||
|
||||
nsAutoLock lock(mLock);
|
||||
|
||||
if (IsCanceled()) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// XXX Currently stored in the order that they should execute (like the window
|
||||
// timeouts are) but we don't flush all expired timeouts the same way that
|
||||
// the window does... Either we should or this is unnecessary.
|
||||
|
@ -741,11 +808,12 @@ nsDOMWorkerThread::AddTimeout(nsDOMWorkerTimeout* aTimeout)
|
|||
timeout = NextTimeout(timeout)) {
|
||||
if (timeout->GetInterval() > newInterval) {
|
||||
PR_INSERT_BEFORE(aTimeout, timeout);
|
||||
return;
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
PR_APPEND_LINK(aTimeout, &mTimeouts);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -859,6 +927,54 @@ nsDOMWorkerThread::CancelScriptLoaders()
|
|||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDOMWorkerThread::AddXHR(nsDOMWorkerXHR* aXHR)
|
||||
{
|
||||
nsAutoLock lock(mLock);
|
||||
|
||||
if (IsCanceled()) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
PRBool contains = mXHRs.Contains(aXHR);
|
||||
NS_ASSERTION(!contains, "Adding an XHR twice!");
|
||||
#endif
|
||||
|
||||
nsDOMWorkerXHR** newElement = mXHRs.AppendElement(aXHR);
|
||||
NS_ENSURE_TRUE(newElement, PR_FALSE);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerThread::RemoveXHR(nsDOMWorkerXHR* aXHR)
|
||||
{
|
||||
nsAutoLock lock(mLock);
|
||||
#ifdef DEBUG
|
||||
PRBool removed =
|
||||
#endif
|
||||
mXHRs.RemoveElement(aXHR);
|
||||
NS_WARN_IF_FALSE(removed, "Removed an XHR that was never added?!");
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerThread::CancelXHRs()
|
||||
{
|
||||
nsAutoTArray<nsDOMWorkerXHR*, 20> xhrs;
|
||||
|
||||
// Must call Cancel outside the lock!
|
||||
{
|
||||
nsAutoLock lock(mLock);
|
||||
xhrs.AppendElements(mXHRs);
|
||||
}
|
||||
|
||||
PRUint32 xhrCount = xhrs.Length();
|
||||
for (PRUint32 index = 0; index < xhrCount; index++) {
|
||||
xhrs[index]->Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerThread::PostMessage(const nsAString& aMessage)
|
||||
{
|
||||
|
|
|
@ -117,6 +117,7 @@ _class::GetClassIDNoAlloc(nsCID* _classIDNoAlloc) \
|
|||
class nsDOMWorkerPool;
|
||||
class nsDOMWorkerScriptLoader;
|
||||
class nsDOMWorkerTimeout;
|
||||
class nsDOMWorkerXHR;
|
||||
|
||||
class nsDOMWorkerThread : public nsDOMWorkerBase,
|
||||
public nsIDOMWorkerThread,
|
||||
|
@ -128,6 +129,7 @@ class nsDOMWorkerThread : public nsDOMWorkerBase,
|
|||
friend class nsDOMWorkerRunnable;
|
||||
friend class nsDOMWorkerScriptLoader;
|
||||
friend class nsDOMWorkerTimeout;
|
||||
friend class nsDOMWorkerXHR;
|
||||
|
||||
friend JSBool DOMWorkerOperationCallback(JSContext* aCx);
|
||||
|
||||
|
@ -167,7 +169,7 @@ private:
|
|||
inline nsDOMWorkerTimeout* FirstTimeout();
|
||||
inline nsDOMWorkerTimeout* NextTimeout(nsDOMWorkerTimeout* aTimeout);
|
||||
|
||||
void AddTimeout(nsDOMWorkerTimeout* aTimeout);
|
||||
PRBool AddTimeout(nsDOMWorkerTimeout* aTimeout);
|
||||
void RemoveTimeout(nsDOMWorkerTimeout* aTimeout);
|
||||
void ClearTimeouts();
|
||||
void CancelTimeout(PRUint32 aId);
|
||||
|
@ -176,6 +178,10 @@ private:
|
|||
|
||||
void CancelScriptLoaders();
|
||||
|
||||
PRBool AddXHR(nsDOMWorkerXHR* aXHR);
|
||||
void RemoveXHR(nsDOMWorkerXHR* aXHR);
|
||||
void CancelXHRs();
|
||||
|
||||
PRLock* Lock() {
|
||||
return mLock;
|
||||
}
|
||||
|
@ -195,6 +201,7 @@ private:
|
|||
PRCList mTimeouts;
|
||||
|
||||
nsTArray<nsDOMWorkerScriptLoader*> mScriptLoaders;
|
||||
nsTArray<nsDOMWorkerXHR*> mXHRs;
|
||||
};
|
||||
|
||||
#endif /* __NSDOMWORKERTHREAD_H__ */
|
||||
|
|
|
@ -329,19 +329,26 @@ nsDOMWorkerTimeout::Init(JSContext* aCx, PRUint32 aArgc, jsval* aArgv,
|
|||
}
|
||||
mIsInterval = aIsInterval;
|
||||
|
||||
mTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
|
||||
nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsIEventTarget* target =
|
||||
static_cast<nsIEventTarget*>(nsDOMThreadService::get());
|
||||
|
||||
rv = mTimer->SetTarget(target);
|
||||
rv = timer->SetTarget(target);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mTimer->InitWithCallback(this, interval, type);
|
||||
rv = timer->InitWithCallback(this, interval, type);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mWorker->AddTimeout(this);
|
||||
mTimer.swap(timer);
|
||||
|
||||
if (!mWorker->AddTimeout(this)) {
|
||||
// Must have been canceled.
|
||||
mTimer->Cancel();
|
||||
mTimer = nsnull;
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,915 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsDOMWorkerXHR.h"
|
||||
|
||||
// Interfaces
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsIXPConnect.h"
|
||||
|
||||
// Other includes
|
||||
#include "nsAutoLock.h"
|
||||
#include "nsAXPCNativeCallContext.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIClassInfoImpl.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
// DOMWorker includes
|
||||
#include "nsDOMThreadService.h"
|
||||
#include "nsDOMWorkerPool.h"
|
||||
#include "nsDOMWorkerXHRProxy.h"
|
||||
|
||||
// The list of event types that we support. This list and the defines based on
|
||||
// it determine the sizes of the listener arrays in nsDOMWorkerXHRProxy. Make
|
||||
// sure that any event types shared by both the XHR and Upload objects are
|
||||
// together at the beginning of the list. Any changes made to this list may
|
||||
// affect sMaxUploadEventTypes, so make sure that it is adjusted accordingly or
|
||||
// things will break!
|
||||
const char* const nsDOMWorkerXHREventTarget::sListenerTypes[] = {
|
||||
// nsIXMLHttpRequestEventTarget listeners.
|
||||
"abort", /* LISTENER_TYPE_ABORT */
|
||||
"error", /* LISTENER_TYPE_ERROR */
|
||||
"load", /* LISTENER_TYPE_LOAD */
|
||||
"loadstart", /* LISTENER_TYPE_LOADSTART */
|
||||
"progress", /* LISTENER_TYPE_PROGRESS */
|
||||
|
||||
// nsIXMLHttpRequest listeners.
|
||||
"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);
|
||||
|
||||
// This should be set to the index of the first event type that is *not*
|
||||
// supported by the Upload object.
|
||||
const PRUint32 nsDOMWorkerXHREventTarget::sMaxUploadEventTypes =
|
||||
LISTENER_TYPE_READYSTATECHANGE;
|
||||
|
||||
// Enforce the invariant that the upload object supports no more event types
|
||||
// than the xhr object.
|
||||
PR_STATIC_ASSERT(nsDOMWorkerXHREventTarget::sMaxXHREventTypes >=
|
||||
nsDOMWorkerXHREventTarget::sMaxUploadEventTypes);
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS2(nsDOMWorkerXHREventTarget,
|
||||
nsIDOMEventTarget,
|
||||
nsIXMLHttpRequestEventTarget)
|
||||
|
||||
PRUint32
|
||||
nsDOMWorkerXHREventTarget::GetListenerTypeFromString(const nsAString& aString)
|
||||
{
|
||||
for (PRUint32 index = 0; index < sMaxXHREventTypes; index++) {
|
||||
if (aString.EqualsASCII(sListenerTypes[index])) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return PR_UINT32_MAX;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::GetOnabort(nsIDOMEventListener** aOnabort)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aOnabort);
|
||||
|
||||
nsCOMPtr<nsIDOMEventListener> listener = GetOnXListener(LISTENER_TYPE_ABORT);
|
||||
listener.forget(aOnabort);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::SetOnabort(nsIDOMEventListener* aOnabort)
|
||||
{
|
||||
return SetEventListener(LISTENER_TYPE_ABORT, aOnabort, PR_TRUE);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::GetOnerror(nsIDOMEventListener** aOnerror)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aOnerror);
|
||||
|
||||
nsCOMPtr<nsIDOMEventListener> listener = GetOnXListener(LISTENER_TYPE_ERROR);
|
||||
listener.forget(aOnerror);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::SetOnerror(nsIDOMEventListener* aOnerror)
|
||||
{
|
||||
return SetEventListener(LISTENER_TYPE_ERROR, aOnerror, PR_TRUE);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::GetOnload(nsIDOMEventListener** aOnload)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aOnload);
|
||||
|
||||
nsCOMPtr<nsIDOMEventListener> listener = GetOnXListener(LISTENER_TYPE_LOAD);
|
||||
listener.forget(aOnload);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::SetOnload(nsIDOMEventListener* aOnload)
|
||||
{
|
||||
return SetEventListener(LISTENER_TYPE_LOAD, aOnload, PR_TRUE);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::GetOnloadstart(nsIDOMEventListener** aOnloadstart)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aOnloadstart);
|
||||
|
||||
nsCOMPtr<nsIDOMEventListener> listener =
|
||||
GetOnXListener(LISTENER_TYPE_LOADSTART);
|
||||
listener.forget(aOnloadstart);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::SetOnloadstart(nsIDOMEventListener* aOnloadstart)
|
||||
{
|
||||
return SetEventListener(LISTENER_TYPE_LOADSTART, aOnloadstart, PR_TRUE);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::GetOnprogress(nsIDOMEventListener** aOnprogress)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aOnprogress);
|
||||
|
||||
nsCOMPtr<nsIDOMEventListener> listener =
|
||||
GetOnXListener(LISTENER_TYPE_PROGRESS);
|
||||
listener.forget(aOnprogress);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::SetOnprogress(nsIDOMEventListener* aOnprogress)
|
||||
{
|
||||
return SetEventListener(LISTENER_TYPE_PROGRESS, aOnprogress, PR_TRUE);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::AddEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aUseCapture)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aListener);
|
||||
|
||||
PRUint32 type = GetListenerTypeFromString(aType);
|
||||
if (type > sMaxXHREventTypes) {
|
||||
// Silently ignore junk events.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return SetEventListener(type, aListener, PR_FALSE);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::RemoveEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aUseCapture)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aListener);
|
||||
|
||||
PRUint32 type = GetListenerTypeFromString(aType);
|
||||
if (type > sMaxXHREventTypes) {
|
||||
// Silently ignore junk events.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return UnsetEventListener(type, aListener);
|
||||
}
|
||||
|
||||
/* ec702b78-c30f-439f-9a9b-a5dae17ee0fc */
|
||||
#define NS_IPRIVATEWORKERXHREVENT_IID \
|
||||
{ \
|
||||
0xec702b78, \
|
||||
0xc30f, \
|
||||
0x439f, \
|
||||
{ 0x9a, 0x9b, 0xa5, 0xda, 0xe1, 0x7e, 0xe0, 0xfc } \
|
||||
}
|
||||
|
||||
class nsIPrivateWorkerXHREvent : public nsIDOMEvent
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IPRIVATEWORKERXHREVENT_IID)
|
||||
virtual PRBool PreventDefaultCalled() = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIPrivateWorkerXHREvent,
|
||||
NS_IPRIVATEWORKERXHREVENT_IID)
|
||||
|
||||
#define NS_FORWARD_NSIDOMEVENT_SPECIAL \
|
||||
NS_IMETHOD GetType(nsAString& aType) \
|
||||
{ return mEvent->GetType(aType); } \
|
||||
NS_IMETHOD GetTarget(nsIDOMEventTarget** aTarget) \
|
||||
{ return mEvent->GetTarget(aTarget); } \
|
||||
NS_IMETHOD GetCurrentTarget(nsIDOMEventTarget** aCurrentTarget) \
|
||||
{ return mEvent->GetCurrentTarget(aCurrentTarget); } \
|
||||
NS_IMETHOD GetEventPhase(PRUint16* aEventPhase) \
|
||||
{ return mEvent->GetEventPhase(aEventPhase); } \
|
||||
NS_IMETHOD GetBubbles(PRBool* aBubbles) \
|
||||
{ return mEvent->GetBubbles(aBubbles); } \
|
||||
NS_IMETHOD GetCancelable(PRBool* aCancelable) \
|
||||
{ return mEvent->GetCancelable(aCancelable); } \
|
||||
NS_IMETHOD GetTimeStamp(DOMTimeStamp* aTimeStamp) \
|
||||
{ return mEvent->GetTimeStamp(aTimeStamp); } \
|
||||
NS_IMETHOD StopPropagation() \
|
||||
{ return mEvent->StopPropagation(); }
|
||||
|
||||
class nsDOMWorkerXHREventWrapper : public nsIPrivateWorkerXHREvent
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_FORWARD_NSIDOMEVENT_SPECIAL
|
||||
|
||||
nsDOMWorkerXHREventWrapper(nsIDOMEvent* aEvent)
|
||||
: mEvent(aEvent), mPreventDefaultCalled(PR_FALSE) {
|
||||
NS_ASSERTION(aEvent, "Null pointer!");
|
||||
}
|
||||
|
||||
NS_IMETHOD PreventDefault() {
|
||||
mPreventDefaultCalled = PR_TRUE;
|
||||
return mEvent->PreventDefault();
|
||||
}
|
||||
|
||||
NS_IMETHOD InitEvent(const nsAString& aEventType, PRBool aCanBubble,
|
||||
PRBool aCancelable) {
|
||||
mPreventDefaultCalled = PR_FALSE;
|
||||
return mEvent->InitEvent(aEventType, aCanBubble, aCancelable);
|
||||
}
|
||||
|
||||
// nsIPrivateWorkerXHREvent
|
||||
virtual PRBool PreventDefaultCalled() {
|
||||
return mPreventDefaultCalled;
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIDOMEvent> mEvent;
|
||||
PRBool mPreventDefaultCalled;
|
||||
};
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS2(nsDOMWorkerXHREventWrapper,
|
||||
nsIDOMEvent,
|
||||
nsIPrivateWorkerXHREvent)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHREventTarget::DispatchEvent(nsIDOMEvent* aEvent,
|
||||
PRBool* _retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aEvent);
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
|
||||
nsCOMPtr<nsIPrivateWorkerXHREvent> wrapper(do_QueryInterface(aEvent));
|
||||
if (!wrapper) {
|
||||
wrapper = new nsDOMWorkerXHREventWrapper(aEvent);
|
||||
NS_ENSURE_TRUE(wrapper, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
nsresult rv = HandleWorkerEvent(wrapper);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*_retval = wrapper->PreventDefaultCalled();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsDOMWorkerXHRUpload::nsDOMWorkerXHRUpload(nsDOMWorkerXHR* aWorkerXHR)
|
||||
: mWorkerXHR(aWorkerXHR)
|
||||
{
|
||||
NS_ASSERTION(aWorkerXHR, "Must have a worker XHR!");
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED2(nsDOMWorkerXHRUpload, nsDOMWorkerXHREventTarget,
|
||||
nsIXMLHttpRequestUpload,
|
||||
nsIClassInfo)
|
||||
|
||||
NS_IMPL_CI_INTERFACE_GETTER3(nsDOMWorkerXHRUpload, nsIDOMEventTarget,
|
||||
nsIXMLHttpRequestEventTarget,
|
||||
nsIXMLHttpRequestUpload)
|
||||
|
||||
NS_IMPL_THREADSAFE_CI(nsDOMWorkerXHRUpload)
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHRUpload::SetEventListener(PRUint32 aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aOnXListener)
|
||||
{
|
||||
if (mWorkerXHR->mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
return mWorkerXHR->mXHRProxy->AddEventListener(aType, aListener, aOnXListener,
|
||||
PR_TRUE);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHRUpload::UnsetEventListener(PRUint32 aType,
|
||||
nsIDOMEventListener* aListener)
|
||||
{
|
||||
if (mWorkerXHR->mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
return mWorkerXHR->mXHRProxy->RemoveEventListener(aType, aListener, PR_TRUE);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHRUpload::HandleWorkerEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
if (mWorkerXHR->mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
return mWorkerXHR->mXHRProxy->HandleWorkerEvent(aEvent, PR_TRUE);
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDOMEventListener>
|
||||
nsDOMWorkerXHRUpload::GetOnXListener(PRUint32 aType)
|
||||
{
|
||||
if (mWorkerXHR->mCanceled) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return mWorkerXHR->mXHRProxy->GetOnXListener(aType, PR_TRUE);
|
||||
}
|
||||
|
||||
nsDOMWorkerXHR::nsDOMWorkerXHR(nsDOMWorkerThread* aWorker)
|
||||
: mWorker(aWorker),
|
||||
mCanceled(PR_TRUE)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aWorker, "Must have a worker!");
|
||||
}
|
||||
|
||||
nsDOMWorkerXHR::~nsDOMWorkerXHR()
|
||||
{
|
||||
if (!mCanceled) {
|
||||
mWorker->RemoveXHR(this);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED2(nsDOMWorkerXHR, nsDOMWorkerXHREventTarget,
|
||||
nsIXMLHttpRequest,
|
||||
nsIClassInfo)
|
||||
|
||||
NS_IMPL_CI_INTERFACE_GETTER3(nsDOMWorkerXHR, nsIDOMEventTarget,
|
||||
nsIXMLHttpRequestEventTarget,
|
||||
nsIXMLHttpRequest)
|
||||
|
||||
NS_IMPL_THREADSAFE_CI(nsDOMWorkerXHR)
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHR::Init()
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (!mWorker->AddXHR(this)) {
|
||||
// Must have been canceled.
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
mCanceled = PR_FALSE;
|
||||
|
||||
nsRefPtr<nsDOMWorkerXHRProxy> proxy = new nsDOMWorkerXHRProxy(this);
|
||||
NS_ENSURE_TRUE(proxy, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsresult rv = proxy->Init();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
proxy.swap(mXHRProxy);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMWorkerXHR::Cancel()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
// Just in case mUpload holds the only ref to this object we make sure to stay
|
||||
// alive through this call.
|
||||
nsRefPtr<nsDOMWorkerXHR> kungFuDeathGrip(this);
|
||||
|
||||
{
|
||||
// This lock is here to prevent a race between Cancel and GetUpload, not to
|
||||
// protect mCanceled.
|
||||
nsAutoLock lock(mWorker->Lock());
|
||||
|
||||
mCanceled = PR_TRUE;
|
||||
mUpload = nsnull;
|
||||
}
|
||||
|
||||
if (mXHRProxy) {
|
||||
mXHRProxy->Destroy();
|
||||
}
|
||||
|
||||
mWorker->RemoveXHR(this);
|
||||
mWorker = nsnull;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHR::SetEventListener(PRUint32 aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aOnXListener)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
return mXHRProxy->AddEventListener(aType, aListener, aOnXListener, PR_FALSE);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHR::UnsetEventListener(PRUint32 aType,
|
||||
nsIDOMEventListener* aListener)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
return mXHRProxy->RemoveEventListener(aType, aListener, PR_FALSE);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerXHR::HandleWorkerEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
return mXHRProxy->HandleWorkerEvent(aEvent, PR_FALSE);
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDOMEventListener>
|
||||
nsDOMWorkerXHR::GetOnXListener(PRUint32 aType)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return mXHRProxy->GetOnXListener(aType, PR_FALSE);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetChannel(nsIChannel** aChannel)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetResponseXML(nsIDOMDocument** aResponseXML)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetResponseText(nsAString& aResponseText)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->GetResponseText(aResponseText);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetStatus(PRUint32* aStatus)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ENSURE_ARG_POINTER(aStatus);
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->GetStatus(aStatus);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetStatusText(nsACString& aStatusText)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->GetStatusText(aStatusText);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::Abort()
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->Abort();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetAllResponseHeaders(char** _retval)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->GetAllResponseHeaders(_retval);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetResponseHeader(const nsACString& aHeader,
|
||||
nsACString& _retval)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->GetResponseHeader(aHeader, _retval);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::OpenRequest(const nsACString& aMethod,
|
||||
const nsACString& aUrl,
|
||||
PRBool aAsync,
|
||||
const nsAString& aUser,
|
||||
const nsAString& aPassword)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->OpenRequest(aMethod, aUrl, aAsync, aUser, aPassword);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::Open(const nsACString& aMethod,
|
||||
const nsACString& aUrl)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
PRBool async = PR_TRUE;
|
||||
nsAutoString user, password;
|
||||
|
||||
nsIXPConnect* xpc = nsContentUtils::XPConnect();
|
||||
NS_ENSURE_TRUE(xpc, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsAXPCNativeCallContext* cc;
|
||||
nsresult rv = xpc->GetCurrentNativeCallContext(&cc);
|
||||
|
||||
do {
|
||||
if (NS_FAILED(rv) || !cc) {
|
||||
break;
|
||||
}
|
||||
|
||||
PRUint32 argc;
|
||||
rv = cc->GetArgc(&argc);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (argc < 3) {
|
||||
break;
|
||||
}
|
||||
|
||||
jsval* argv;
|
||||
rv = cc->GetArgvPtr(&argv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JSContext* cx;
|
||||
rv = cc->GetJSContext(&cx);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
JSBool asyncBool;
|
||||
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;
|
||||
}
|
||||
|
||||
JSString* argStr;
|
||||
if (!JSVAL_IS_NULL(argv[3]) && !JSVAL_IS_VOID(argv[3])) {
|
||||
argStr = JS_ValueToString(cx, argv[3]);
|
||||
if (argStr) {
|
||||
user.Assign(nsDependentJSString(argStr));
|
||||
}
|
||||
}
|
||||
|
||||
if (argc < 5) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!JSVAL_IS_NULL(argv[4]) && !JSVAL_IS_VOID(argv[4])) {
|
||||
argStr = JS_ValueToString(cx, argv[4]);
|
||||
if (argStr) {
|
||||
password.Assign(nsDependentJSString(argStr));
|
||||
}
|
||||
}
|
||||
} while (PR_FALSE);
|
||||
|
||||
return OpenRequest(aMethod, aUrl, async, user, password);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::Send(nsIVariant* aBody)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->Send(aBody);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::SendAsBinary(const nsAString& aBody)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->SendAsBinary(aBody);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::SetRequestHeader(const nsACString& aHeader,
|
||||
const nsACString& aValue)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->SetRequestHeader(aHeader, aValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetReadyState(PRInt32* aReadyState)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aReadyState);
|
||||
|
||||
nsresult rv = mXHRProxy->GetReadyState(aReadyState);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::OverrideMimeType(const nsACString& aMimetype)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->OverrideMimeType(aMimetype);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetMultipart(PRBool* aMultipart)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aMultipart);
|
||||
|
||||
nsresult rv = mXHRProxy->GetMultipart(aMultipart);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::SetMultipart(PRBool aMultipart)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsresult rv = mXHRProxy->SetMultipart(aMultipart);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetMozBackgroundRequest(PRBool* aMozBackgroundRequest)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aMozBackgroundRequest);
|
||||
|
||||
*aMozBackgroundRequest = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::SetMozBackgroundRequest(PRBool aMozBackgroundRequest)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (aMozBackgroundRequest) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::Init(nsIPrincipal* aPrincipal,
|
||||
nsIScriptContext* aScriptContext,
|
||||
nsPIDOMWindow* aOwnerWindow)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetUpload(nsIXMLHttpRequestUpload** aUpload)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsRefPtr<nsDOMWorkerThread> worker = mWorker;
|
||||
if (!worker) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsAutoLock lock(worker->Lock());
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aUpload);
|
||||
|
||||
if (!mUpload) {
|
||||
mUpload = new nsDOMWorkerXHRUpload(this);
|
||||
NS_ENSURE_TRUE(mUpload, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
NS_ADDREF(*aUpload = mUpload);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::GetOnreadystatechange(nsIDOMEventListener** aOnreadystatechange)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aOnreadystatechange);
|
||||
|
||||
nsCOMPtr<nsIDOMEventListener> listener =
|
||||
mXHRProxy->GetOnXListener(LISTENER_TYPE_READYSTATECHANGE, PR_FALSE);
|
||||
|
||||
listener.forget(aOnreadystatechange);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWorkerXHR::SetOnreadystatechange(nsIDOMEventListener* aOnreadystatechange)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mCanceled) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
return mXHRProxy->AddEventListener(LISTENER_TYPE_READYSTATECHANGE,
|
||||
aOnreadystatechange, PR_TRUE, PR_FALSE);
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NSDOMWORKERXHR_H__
|
||||
#define __NSDOMWORKERXHR_H__
|
||||
|
||||
// Bases
|
||||
#include "nsIXMLHttpRequest.h"
|
||||
#include "nsIClassInfo.h"
|
||||
|
||||
// Interfaces
|
||||
|
||||
// Other includes
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsTArray.h"
|
||||
#include "prlock.h"
|
||||
|
||||
// DOMWorker includes
|
||||
#include "nsDOMWorkerThread.h"
|
||||
|
||||
class nsDOMWorkerXHRProxy;
|
||||
|
||||
class nsDOMWorkerXHREventTarget : public nsIXMLHttpRequestEventTarget
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMEVENTTARGET
|
||||
NS_DECL_NSIXMLHTTPREQUESTEVENTTARGET
|
||||
|
||||
static const char* const sListenerTypes[];
|
||||
static const PRUint32 sMaxXHREventTypes;
|
||||
static const PRUint32 sMaxUploadEventTypes;
|
||||
|
||||
static PRUint32 GetListenerTypeFromString(const nsAString& aString);
|
||||
|
||||
virtual nsresult SetEventListener(PRUint32 aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aOnXListener) = 0;
|
||||
|
||||
virtual nsresult UnsetEventListener(PRUint32 aType,
|
||||
nsIDOMEventListener* aListener) = 0;
|
||||
|
||||
virtual nsresult HandleWorkerEvent(nsIDOMEvent* aEvent) = 0;
|
||||
|
||||
virtual already_AddRefed<nsIDOMEventListener>
|
||||
GetOnXListener(PRUint32 aType) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~nsDOMWorkerXHREventTarget() { }
|
||||
};
|
||||
|
||||
class nsDOMWorkerXHR;
|
||||
|
||||
class nsDOMWorkerXHRUpload : public nsDOMWorkerXHREventTarget,
|
||||
public nsIXMLHttpRequestUpload,
|
||||
public nsIClassInfo
|
||||
{
|
||||
friend class nsDOMWorkerXHR;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_FORWARD_NSIDOMEVENTTARGET(nsDOMWorkerXHREventTarget::)
|
||||
NS_FORWARD_NSIXMLHTTPREQUESTEVENTTARGET(nsDOMWorkerXHREventTarget::)
|
||||
NS_DECL_NSIXMLHTTPREQUESTUPLOAD
|
||||
NS_DECL_NSICLASSINFO
|
||||
|
||||
nsDOMWorkerXHRUpload(nsDOMWorkerXHR* aWorkerXHR);
|
||||
|
||||
virtual nsresult SetEventListener(PRUint32 aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aOnXListener);
|
||||
|
||||
virtual nsresult UnsetEventListener(PRUint32 aType,
|
||||
nsIDOMEventListener* aListener);
|
||||
|
||||
virtual nsresult HandleWorkerEvent(nsIDOMEvent* aEvent);
|
||||
|
||||
virtual already_AddRefed<nsIDOMEventListener>
|
||||
GetOnXListener(PRUint32 aType);
|
||||
|
||||
protected:
|
||||
virtual ~nsDOMWorkerXHRUpload() { }
|
||||
|
||||
nsRefPtr<nsDOMWorkerXHR> mWorkerXHR;
|
||||
};
|
||||
|
||||
class nsDOMWorkerXHR : public nsDOMWorkerXHREventTarget,
|
||||
public nsIXMLHttpRequest,
|
||||
public nsIClassInfo
|
||||
{
|
||||
friend class nsDOMWorkerXHRProxy;
|
||||
friend class nsDOMWorkerXHRUpload;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIXMLHTTPREQUEST
|
||||
NS_DECL_NSICLASSINFO
|
||||
|
||||
nsDOMWorkerXHR(nsDOMWorkerThread* aWorker);
|
||||
|
||||
nsresult Init();
|
||||
|
||||
void Cancel();
|
||||
|
||||
virtual nsresult SetEventListener(PRUint32 aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aOnXListener);
|
||||
|
||||
virtual nsresult UnsetEventListener(PRUint32 aType,
|
||||
nsIDOMEventListener* aListener);
|
||||
|
||||
virtual nsresult HandleWorkerEvent(nsIDOMEvent* aEvent);
|
||||
|
||||
virtual already_AddRefed<nsIDOMEventListener>
|
||||
GetOnXListener(PRUint32 aType);
|
||||
|
||||
protected:
|
||||
virtual ~nsDOMWorkerXHR();
|
||||
|
||||
PRLock* Lock() {
|
||||
return mWorker->Lock();
|
||||
}
|
||||
|
||||
nsRefPtr<nsDOMWorkerThread> mWorker;
|
||||
nsRefPtr<nsDOMWorkerXHRProxy> mXHRProxy;
|
||||
nsRefPtr<nsDOMWorkerXHRUpload> mUpload;
|
||||
|
||||
volatile PRBool mCanceled;
|
||||
};
|
||||
|
||||
#endif /* __NSDOMWORKERXHR_H__ */
|
|
@ -0,0 +1,248 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NSDOMWORKERXHRPROXIEDFUNCTIONS_H__
|
||||
#define __NSDOMWORKERXHRPROXIEDFUNCTIONS_H__
|
||||
|
||||
#define MAKE_PROXIED_FUNCTION0(_name) \
|
||||
class _name : public nsRunnable \
|
||||
{ \
|
||||
public: \
|
||||
_name (nsDOMWorkerXHRProxy* aXHR) \
|
||||
: mXHR(aXHR) \
|
||||
{ \
|
||||
NS_ASSERTION(aXHR, "Null pointer!"); \
|
||||
} \
|
||||
\
|
||||
NS_IMETHOD Run() \
|
||||
{ \
|
||||
nsCOMPtr<nsIXMLHttpRequest> xhr = mXHR->GetXMLHttpRequest(); \
|
||||
if (xhr) { \
|
||||
return xhr-> _name (); \
|
||||
} \
|
||||
return NS_OK; \
|
||||
} \
|
||||
private: \
|
||||
nsRefPtr<nsDOMWorkerXHRProxy> mXHR; \
|
||||
}
|
||||
|
||||
#define MAKE_PROXIED_FUNCTION1(_name, _arg1) \
|
||||
class _name : public nsRunnable \
|
||||
{ \
|
||||
public: \
|
||||
_name (nsDOMWorkerXHRProxy* aXHR, _arg1 aArg1) \
|
||||
: mXHR(aXHR), mArg1(aArg1) \
|
||||
{ \
|
||||
NS_ASSERTION(aXHR, "Null pointer!"); \
|
||||
} \
|
||||
\
|
||||
NS_IMETHOD Run() \
|
||||
{ \
|
||||
nsCOMPtr<nsIXMLHttpRequest> xhr = mXHR->GetXMLHttpRequest(); \
|
||||
if (xhr) { \
|
||||
return xhr-> _name (mArg1); \
|
||||
} \
|
||||
return NS_OK; \
|
||||
} \
|
||||
private: \
|
||||
nsRefPtr<nsDOMWorkerXHRProxy> mXHR; \
|
||||
_arg1 mArg1; \
|
||||
}
|
||||
|
||||
#define MAKE_PROXIED_FUNCTION2(_name, _arg1, _arg2) \
|
||||
class _name : public nsRunnable \
|
||||
{ \
|
||||
public: \
|
||||
_name (nsDOMWorkerXHRProxy* aXHR, _arg1 aArg1, _arg2 aArg2) \
|
||||
: mXHR(aXHR), mArg1(aArg1), mArg2(aArg2) \
|
||||
{ \
|
||||
NS_ASSERTION(aXHR, "Null pointer!"); \
|
||||
} \
|
||||
\
|
||||
NS_IMETHOD Run() \
|
||||
{ \
|
||||
nsCOMPtr<nsIXMLHttpRequest> xhr = mXHR->GetXMLHttpRequest(); \
|
||||
if (xhr) { \
|
||||
return xhr-> _name (mArg1, mArg2); \
|
||||
} \
|
||||
return NS_OK; \
|
||||
} \
|
||||
private: \
|
||||
nsRefPtr<nsDOMWorkerXHRProxy> mXHR; \
|
||||
_arg1 mArg1; \
|
||||
_arg2 mArg2; \
|
||||
}
|
||||
|
||||
#define MAKE_PROXIED_FUNCTION3(_name, _arg1, _arg2, _arg3) \
|
||||
class _name : public nsRunnable \
|
||||
{ \
|
||||
public: \
|
||||
_name (nsDOMWorkerXHRProxy* aXHR, _arg1 aArg1, _arg2 aArg2, _arg3 aArg3) \
|
||||
: mXHR(aXHR), mArg1(aArg1), mArg2(aArg2), mArg3(aArg3) \
|
||||
{ \
|
||||
NS_ASSERTION(aXHR, "Null pointer!"); \
|
||||
} \
|
||||
\
|
||||
NS_IMETHOD Run() \
|
||||
{ \
|
||||
nsCOMPtr<nsIXMLHttpRequest> xhr = mXHR->GetXMLHttpRequest(); \
|
||||
if (xhr) { \
|
||||
return xhr-> _name (mArg1, mArg2, mArg3); \
|
||||
} \
|
||||
return NS_OK; \
|
||||
} \
|
||||
private: \
|
||||
nsRefPtr<nsDOMWorkerXHRProxy> mXHR; \
|
||||
_arg1 mArg1; \
|
||||
_arg2 mArg2; \
|
||||
_arg3 mArg3; \
|
||||
}
|
||||
|
||||
#define MAKE_PROXIED_FUNCTION4(_name, _arg1, _arg2, _arg3, _arg4) \
|
||||
class _name : public nsRunnable \
|
||||
{ \
|
||||
public: \
|
||||
_name (nsDOMWorkerXHRProxy* aXHR, _arg1 aArg1, _arg2 aArg2, _arg3 aArg3, \
|
||||
_arg4 aArg4) \
|
||||
: mXHR(aXHR), mArg1(aArg1), mArg2(aArg2), mArg3(aArg3), mArg4(aArg4) \
|
||||
{ \
|
||||
NS_ASSERTION(aXHR, "Null pointer!"); \
|
||||
} \
|
||||
\
|
||||
NS_IMETHOD Run() \
|
||||
{ \
|
||||
nsCOMPtr<nsIXMLHttpRequest> xhr = mXHR->GetXMLHttpRequest(); \
|
||||
if (xhr) { \
|
||||
return xhr-> _name (mArg1, mArg2, mArg3, mArg4); \
|
||||
} \
|
||||
return NS_OK; \
|
||||
} \
|
||||
private: \
|
||||
nsRefPtr<nsDOMWorkerXHRProxy> mXHR; \
|
||||
_arg1 mArg1; \
|
||||
_arg2 mArg2; \
|
||||
_arg3 mArg3; \
|
||||
_arg4 mArg4; \
|
||||
}
|
||||
|
||||
#define MAKE_PROXIED_FUNCTION5(_name, _arg1, _arg2, _arg3, _arg4, _arg5) \
|
||||
class _name : public nsRunnable \
|
||||
{ \
|
||||
public: \
|
||||
_name (nsDOMWorkerXHRProxy* aXHR, _arg1 aArg1, _arg2 aArg2, _arg3 aArg3, \
|
||||
_arg4 aArg4, _arg5 aArg5) \
|
||||
: mXHR(aXHR), mArg1(aArg1), mArg2(aArg2), mArg3(aArg3), mArg4(aArg4), \
|
||||
mArg5(aArg5) \
|
||||
{ \
|
||||
NS_ASSERTION(aXHR, "Null pointer!"); \
|
||||
} \
|
||||
\
|
||||
NS_IMETHOD Run() \
|
||||
{ \
|
||||
nsCOMPtr<nsIXMLHttpRequest> xhr = mXHR->GetXMLHttpRequest(); \
|
||||
if (xhr) { \
|
||||
return xhr-> _name (mArg1, mArg2, mArg3, mArg4, mArg5); \
|
||||
} \
|
||||
return NS_OK; \
|
||||
} \
|
||||
private: \
|
||||
nsRefPtr<nsDOMWorkerXHRProxy> mXHR; \
|
||||
_arg1 mArg1; \
|
||||
_arg2 mArg2; \
|
||||
_arg3 mArg3; \
|
||||
_arg4 mArg4; \
|
||||
_arg5 mArg5; \
|
||||
}
|
||||
|
||||
#define RUN_PROXIED_FUNCTION(_name, _args) \
|
||||
PR_BEGIN_MACRO \
|
||||
if (mCanceled) { \
|
||||
return NS_ERROR_ABORT; \
|
||||
} \
|
||||
\
|
||||
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(); \
|
||||
if (NS_FAILED(_rv)) { \
|
||||
return _rv; \
|
||||
} \
|
||||
PR_END_MACRO
|
||||
|
||||
namespace nsDOMWorkerProxiedXHRFunctions
|
||||
{
|
||||
class Abort : public nsRunnable
|
||||
{
|
||||
public:
|
||||
Abort (nsDOMWorkerXHRProxy* aXHR)
|
||||
: mXHR(aXHR)
|
||||
{
|
||||
NS_ASSERTION(aXHR, "Null pointer!");
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
return mXHR->Abort();
|
||||
}
|
||||
private:
|
||||
nsRefPtr<nsDOMWorkerXHRProxy> mXHR;
|
||||
};
|
||||
|
||||
MAKE_PROXIED_FUNCTION1(GetAllResponseHeaders, char**);
|
||||
|
||||
MAKE_PROXIED_FUNCTION2(GetResponseHeader, const nsACString&, nsACString&);
|
||||
|
||||
MAKE_PROXIED_FUNCTION5(OpenRequest, const nsACString&, const nsACString&,
|
||||
PRBool, const nsAString&, const nsAString&);
|
||||
|
||||
MAKE_PROXIED_FUNCTION1(Send, nsIVariant*);
|
||||
|
||||
MAKE_PROXIED_FUNCTION1(SendAsBinary, const nsAString&);
|
||||
|
||||
MAKE_PROXIED_FUNCTION2(SetRequestHeader, const nsACString&,
|
||||
const nsACString&);
|
||||
|
||||
MAKE_PROXIED_FUNCTION1(OverrideMimeType, const nsACString&);
|
||||
|
||||
MAKE_PROXIED_FUNCTION1(SetMultipart, PRBool);
|
||||
}
|
||||
|
||||
#endif /* __NSDOMWORKERXHRPROXIEDFUNCTIONS_H__ */
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,173 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is worker threads.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NSDOMWORKERXHRPROXY_H__
|
||||
#define __NSDOMWORKERXHRPROXY_H__
|
||||
|
||||
// Bases
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
#include "nsIRequestObserver.h"
|
||||
|
||||
// Other includes
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
// DOMWorker includes
|
||||
#include "nsDOMWorkerXHR.h"
|
||||
|
||||
class nsIJSXMLHttpRequest;
|
||||
class nsIThread;
|
||||
class nsIVariant;
|
||||
class nsIXMLHttpRequest;
|
||||
class nsDOMWorkerXHREvent;
|
||||
class nsDOMWorkerXHRWrappedListener;
|
||||
class nsXMLHttpRequest;
|
||||
|
||||
class nsDOMWorkerXHRProxy : public nsRunnable,
|
||||
public nsIDOMEventListener,
|
||||
public nsIRequestObserver
|
||||
{
|
||||
|
||||
friend class nsDOMWorkerXHREvent;
|
||||
friend class nsDOMWorkerXHR;
|
||||
friend class nsDOMWorkerXHRUpload;
|
||||
|
||||
typedef nsCOMPtr<nsIDOMEventListener> Listener;
|
||||
typedef nsTArray<Listener> ListenerArray;
|
||||
|
||||
typedef nsRefPtr<nsDOMWorkerXHRWrappedListener> WrappedListener;
|
||||
|
||||
typedef nsresult (NS_STDCALL nsIDOMEventTarget::*AddRemoveFunction)
|
||||
(const nsAString&, nsIDOMEventListener*, PRBool);
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
NS_DECL_NSIRUNNABLE
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
|
||||
nsDOMWorkerXHRProxy(nsDOMWorkerXHR* aWorkerXHR);
|
||||
virtual ~nsDOMWorkerXHRProxy();
|
||||
|
||||
nsresult Init();
|
||||
|
||||
nsIXMLHttpRequest* GetXMLHttpRequest();
|
||||
|
||||
nsresult Abort();
|
||||
|
||||
protected:
|
||||
nsresult InitInternal();
|
||||
void DestroyInternal();
|
||||
|
||||
nsresult Destroy();
|
||||
|
||||
void FlipOwnership();
|
||||
|
||||
nsresult AddEventListener(PRUint32 aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aOnXListener,
|
||||
PRBool aUploadListener);
|
||||
|
||||
nsresult RemoveEventListener(PRUint32 aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
PRBool aUploadListener);
|
||||
|
||||
already_AddRefed<nsIDOMEventListener> GetOnXListener(PRUint32 aType,
|
||||
PRBool aUploadListener);
|
||||
|
||||
nsresult HandleWorkerEvent(nsDOMWorkerXHREvent* aEvent, PRBool aUploadEvent);
|
||||
|
||||
nsresult HandleWorkerEvent(nsIDOMEvent* aEvent, PRBool aUploadEvent);
|
||||
|
||||
nsresult HandleEventInternal(PRUint32 aType,
|
||||
nsIDOMEvent* aEvent,
|
||||
PRBool aUploadEvent);
|
||||
|
||||
void ClearEventListeners();
|
||||
|
||||
// Methods of nsIXMLHttpRequest that we implement
|
||||
nsresult GetAllResponseHeaders(char** _retval);
|
||||
nsresult GetResponseHeader(const nsACString& aHeader,
|
||||
nsACString& _retval);
|
||||
nsresult OpenRequest(const nsACString& aMethod,
|
||||
const nsACString& aUrl,
|
||||
PRBool aAsync,
|
||||
const nsAString& aUser,
|
||||
const nsAString& aPassword);
|
||||
nsresult Send(nsIVariant* aBody);
|
||||
nsresult SendAsBinary(const nsAString& aBody);
|
||||
nsresult GetResponseText(nsAString& _retval);
|
||||
nsresult GetStatusText(nsACString& _retval);
|
||||
nsresult GetStatus(nsresult* _retval);
|
||||
nsresult GetReadyState(PRInt32* _retval);
|
||||
nsresult SetRequestHeader(const nsACString& aHeader,
|
||||
const nsACString& aValue);
|
||||
nsresult OverrideMimeType(const nsACString& aMimetype);
|
||||
nsresult GetMultipart(PRBool* aMultipart);
|
||||
nsresult SetMultipart(PRBool aMultipart);
|
||||
|
||||
// May be weak or strong, check mOwnedByXHR.
|
||||
nsDOMWorkerXHR* mWorkerXHR;
|
||||
|
||||
// Always weak!
|
||||
nsIXMLHttpRequest* mXHR;
|
||||
nsXMLHttpRequest* mConcreteXHR;
|
||||
|
||||
// May be weak or strong, check mOwnedByXHR.
|
||||
nsIXMLHttpRequestUpload* mUpload;
|
||||
|
||||
nsCOMPtr<nsIThread> mMainThread;
|
||||
|
||||
nsRefPtr<nsDOMWorkerXHREvent> mLastXHREvent;
|
||||
|
||||
nsTArray<ListenerArray> mXHRListeners;
|
||||
nsTArray<WrappedListener> mXHROnXListeners;
|
||||
|
||||
nsTArray<ListenerArray> mUploadListeners;
|
||||
nsTArray<WrappedListener> mUploadOnXListeners;
|
||||
|
||||
// Whether or not this object is owned by the real XHR object.
|
||||
PRPackedBool mOwnedByXHR;
|
||||
|
||||
PRPackedBool mMultipart;
|
||||
PRPackedBool mCanceled;
|
||||
};
|
||||
|
||||
#endif /* __NSDOMWORKERXHRPROXY_H__ */
|
|
@ -57,6 +57,8 @@ _TEST_FILES = \
|
|||
test_threadErrors.html \
|
||||
test_threadTimeouts.html \
|
||||
test_longThread.html \
|
||||
test_xhr.html \
|
||||
testXHR.txt \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
A noisy noise annoys an oyster.
|
|
@ -0,0 +1,114 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Tests of DOM Worker Threads XHR(Bug 450452 )
|
||||
-->
|
||||
<head>
|
||||
<title>Test for DOM Worker Threads XHR (Bug 450452 )</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=450452">DOM Worker Threads XHR (Bug 450452)</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
function workerScript() {
|
||||
var xhr = new XMLHttpRequest();
|
||||
|
||||
function onload(event) {
|
||||
if (event.target.status == 200) {
|
||||
var message = { type: "error",
|
||||
error: event.target.status };
|
||||
postMessageToPool(message.toSource());
|
||||
}
|
||||
|
||||
var message = { type: "load",
|
||||
data: xhr.responseText };
|
||||
postMessageToPool(message.toSource());
|
||||
}
|
||||
|
||||
xhr.onload = onload;
|
||||
xhr.addEventListener("load", onload, false);
|
||||
xhr.removeEventListener("load", onload, false);
|
||||
if (!xhr.onload) {
|
||||
var message = { type: "error",
|
||||
error: "Lost message listener!" };
|
||||
postMessageToPool(message.toSource());
|
||||
}
|
||||
|
||||
xhr.addEventListener("error", function(event) {
|
||||
var message = { type: "error",
|
||||
error: event.target.status };
|
||||
postMessageToPool(message.toSource());
|
||||
}, false);
|
||||
|
||||
function onprogress(event) {
|
||||
var message = { type: "progress",
|
||||
current: event.position,
|
||||
total: event.totalSize };
|
||||
postMessageToPool(message.toSource());
|
||||
}
|
||||
xhr.addEventListener("progress", onprogress, false);
|
||||
|
||||
xhr.addEventListener("foopety", function(event) {}, false);
|
||||
xhr.removeEventListener("doopety", function(event) {}, false);
|
||||
|
||||
var upload = xhr.upload;
|
||||
upload.onprogress = function(event) { };
|
||||
upload.addEventListener("readystatechange", function(event) { }, false);
|
||||
upload.removeEventListener("readystatechange", function(event) { }, false);
|
||||
upload.addEventListener("load", function(event) { }, false);
|
||||
upload.removeEventListener("readystatechange", function(event) { }, false);
|
||||
|
||||
this.messageListener = function(message, source) {
|
||||
if (xhr.readystate > 0) {
|
||||
throw "XHR already running!";
|
||||
}
|
||||
xhr.open("GET", message);
|
||||
xhr.send(null);
|
||||
}
|
||||
}
|
||||
|
||||
var pool = navigator.newWorkerPool();
|
||||
pool.messageListener = function(message, source) {
|
||||
var args = eval(message);
|
||||
switch (args.type) {
|
||||
case "progress": {
|
||||
ok(parseInt(args.current) <= parseInt(args.total));
|
||||
} break;
|
||||
case "error": {
|
||||
ok(false, "XHR error: " + args.error);
|
||||
} break;
|
||||
case "load": {
|
||||
is(args.data, "A noisy noise annoys an oyster.");
|
||||
document.getElementById("content").textContent = args.data;
|
||||
SimpleTest.finish();
|
||||
} break;
|
||||
default: {
|
||||
ok(false, "Unexpected message");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pool.errorListener = function(error, source) {
|
||||
ok(false, "Worker had an error:" + error);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
var worker = pool.createWorker("(" + workerScript + ")();");
|
||||
worker.postMessage("testXHR.txt");
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -3647,8 +3647,8 @@ public:
|
|||
* @param cx The JSContext, this can be null, we don't do anything then
|
||||
*/
|
||||
AutoScriptEvaluate(JSContext * cx)
|
||||
: mJSContext(cx), mState(0), mEvaluated(PR_FALSE),
|
||||
mContextHasThread(0) {}
|
||||
: mJSContext(cx), mState(0), mErrorReporterSet(PR_FALSE),
|
||||
mEvaluated(PR_FALSE), mContextHasThread(0) {}
|
||||
|
||||
/**
|
||||
* Does the pre script evaluation and sets the error reporter if given
|
||||
|
@ -3665,7 +3665,7 @@ public:
|
|||
private:
|
||||
JSContext* mJSContext;
|
||||
JSExceptionState* mState;
|
||||
JSErrorReporter mOldErrorReporter;
|
||||
PRBool mErrorReporterSet;
|
||||
PRBool mEvaluated;
|
||||
jsword mContextHasThread;
|
||||
|
||||
|
|
|
@ -55,7 +55,11 @@ void AutoScriptEvaluate::StartEvaluating(JSErrorReporter errorReporter)
|
|||
if(!mJSContext)
|
||||
return;
|
||||
mEvaluated = PR_TRUE;
|
||||
mOldErrorReporter = JS_SetErrorReporter(mJSContext, errorReporter);
|
||||
if(!mJSContext->errorReporter)
|
||||
{
|
||||
JS_SetErrorReporter(mJSContext, errorReporter);
|
||||
mErrorReporterSet = PR_TRUE;
|
||||
}
|
||||
mContextHasThread = JS_GetContextThread(mJSContext);
|
||||
if (mContextHasThread)
|
||||
JS_BeginRequest(mJSContext);
|
||||
|
@ -105,7 +109,9 @@ AutoScriptEvaluate::~AutoScriptEvaluate()
|
|||
if(scriptNotify)
|
||||
scriptNotify->ScriptExecuted();
|
||||
}
|
||||
JS_SetErrorReporter(mJSContext, mOldErrorReporter);
|
||||
|
||||
if(mErrorReporterSet)
|
||||
JS_SetErrorReporter(mJSContext, NULL);
|
||||
}
|
||||
|
||||
// It turns out that some errors may be not worth reporting. So, this
|
||||
|
@ -906,6 +912,15 @@ nsXPCWrappedJSClass::CleanupPointerTypeObject(const nsXPTType& type,
|
|||
}
|
||||
}
|
||||
|
||||
class AutoClearPendingException
|
||||
{
|
||||
public:
|
||||
AutoClearPendingException(JSContext *cx) : mCx(cx) { }
|
||||
~AutoClearPendingException() { JS_ClearPendingException(mCx); }
|
||||
private:
|
||||
JSContext* mCx;
|
||||
};
|
||||
|
||||
nsresult
|
||||
nsXPCWrappedJSClass::CheckForException(XPCCallContext & ccx,
|
||||
const char * aPropertyName,
|
||||
|
@ -926,8 +941,10 @@ nsXPCWrappedJSClass::CheckForException(XPCCallContext & ccx,
|
|||
nsresult pending_result = xpcc->GetPendingResult();
|
||||
|
||||
jsval js_exception;
|
||||
JSBool is_js_exception = JS_GetPendingException(cx, &js_exception);
|
||||
|
||||
/* JS might throw an expection whether the reporter was called or not */
|
||||
if(JS_GetPendingException(cx, &js_exception))
|
||||
if(is_js_exception)
|
||||
{
|
||||
if(!xpc_exception)
|
||||
XPCConvert::JSValToXPCException(ccx, js_exception, anInterfaceName,
|
||||
|
@ -939,9 +956,10 @@ nsXPCWrappedJSClass::CheckForException(XPCCallContext & ccx,
|
|||
{
|
||||
ccx.GetThreadData()->SetException(nsnull); // XXX necessary?
|
||||
}
|
||||
JS_ClearPendingException(cx);
|
||||
}
|
||||
|
||||
AutoClearPendingException acpe(cx);
|
||||
|
||||
if(xpc_exception)
|
||||
{
|
||||
nsresult e_result;
|
||||
|
@ -992,6 +1010,14 @@ nsXPCWrappedJSClass::CheckForException(XPCCallContext & ccx,
|
|||
}
|
||||
}
|
||||
|
||||
// Try to use the error reporter set on the context to handle this
|
||||
// error if it came from a JS exception.
|
||||
if(reportable && is_js_exception &&
|
||||
cx->errorReporter != xpcWrappedJSErrorReporter)
|
||||
{
|
||||
reportable = !JS_ReportPendingException(cx);
|
||||
}
|
||||
|
||||
if(reportable)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
|
|
Загрузка…
Ссылка в новой задаче