Backing out worker changes, a=backout.

This commit is contained in:
Ben Turner 2010-12-21 16:44:49 -05:00
parent ff23778648
commit 8a02f568a0
33 changed files with 341 additions and 1414 deletions

View File

@ -10276,8 +10276,8 @@ nsNavigator::SetDocShell(nsIDocShell *aDocShell)
// nsNavigator::nsIDOMNavigator
//*****************************************************************************
nsresult
NS_GetNavigatorUserAgent(nsAString& aUserAgent)
NS_IMETHODIMP
nsNavigator::GetUserAgent(nsAString& aUserAgent)
{
nsresult rv;
nsCOMPtr<nsIHttpProtocolHandler>
@ -10291,8 +10291,92 @@ NS_GetNavigatorUserAgent(nsAString& aUserAgent)
return rv;
}
nsresult
NS_GetNavigatorPlatform(nsAString& aPlatform)
NS_IMETHODIMP
nsNavigator::GetAppCodeName(nsAString& aAppCodeName)
{
nsresult rv;
nsCOMPtr<nsIHttpProtocolHandler>
service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv));
if (NS_SUCCEEDED(rv)) {
nsCAutoString appName;
rv = service->GetAppName(appName);
CopyASCIItoUTF16(appName, aAppCodeName);
}
return rv;
}
NS_IMETHODIMP
nsNavigator::GetAppVersion(nsAString& aAppVersion)
{
if (!nsContentUtils::IsCallerTrustedForRead()) {
const nsAdoptingCString& override =
nsContentUtils::GetCharPref("general.appversion.override");
if (override) {
CopyUTF8toUTF16(override, aAppVersion);
return NS_OK;
}
}
nsresult rv;
nsCOMPtr<nsIHttpProtocolHandler>
service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv));
if (NS_SUCCEEDED(rv)) {
nsCAutoString str;
rv = service->GetAppVersion(str);
CopyASCIItoUTF16(str, aAppVersion);
if (NS_FAILED(rv))
return rv;
aAppVersion.AppendLiteral(" (");
rv = service->GetPlatform(str);
if (NS_FAILED(rv))
return rv;
AppendASCIItoUTF16(str, aAppVersion);
aAppVersion.Append(PRUnichar(')'));
}
return rv;
}
NS_IMETHODIMP
nsNavigator::GetAppName(nsAString& aAppName)
{
if (!nsContentUtils::IsCallerTrustedForRead()) {
const nsAdoptingCString& override =
nsContentUtils::GetCharPref("general.appname.override");
if (override) {
CopyUTF8toUTF16(override, aAppName);
return NS_OK;
}
}
aAppName.AssignLiteral("Netscape");
return NS_OK;
}
NS_IMETHODIMP
nsNavigator::GetLanguage(nsAString& aLanguage)
{
nsresult rv;
nsCOMPtr<nsIHttpProtocolHandler>
service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv));
if (NS_SUCCEEDED(rv)) {
nsCAutoString lang;
rv = service->GetLanguage(lang);
CopyASCIItoUTF16(lang, aLanguage);
}
return rv;
}
NS_IMETHODIMP
nsNavigator::GetPlatform(nsAString& aPlatform)
{
if (!nsContentUtils::IsCallerTrustedForRead()) {
const nsAdoptingCString& override =
@ -10335,113 +10419,6 @@ NS_GetNavigatorPlatform(nsAString& aPlatform)
return rv;
}
nsresult
NS_GetNavigatorAppVersion(nsAString& aAppVersion)
{
if (!nsContentUtils::IsCallerTrustedForRead()) {
const nsAdoptingCString& override =
nsContentUtils::GetCharPref("general.appversion.override");
if (override) {
CopyUTF8toUTF16(override, aAppVersion);
return NS_OK;
}
}
nsresult rv;
nsCOMPtr<nsIHttpProtocolHandler>
service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv));
if (NS_SUCCEEDED(rv)) {
nsCAutoString str;
rv = service->GetAppVersion(str);
CopyASCIItoUTF16(str, aAppVersion);
if (NS_FAILED(rv))
return rv;
aAppVersion.AppendLiteral(" (");
rv = service->GetPlatform(str);
if (NS_FAILED(rv))
return rv;
AppendASCIItoUTF16(str, aAppVersion);
aAppVersion.Append(PRUnichar(')'));
}
return rv;
}
nsresult
NS_GetNavigatorAppName(nsAString& aAppName)
{
if (!nsContentUtils::IsCallerTrustedForRead()) {
const nsAdoptingCString& override =
nsContentUtils::GetCharPref("general.appname.override");
if (override) {
CopyUTF8toUTF16(override, aAppName);
return NS_OK;
}
}
aAppName.AssignLiteral("Netscape");
return NS_OK;
}
NS_IMETHODIMP
nsNavigator::GetUserAgent(nsAString& aUserAgent)
{
return NS_GetNavigatorUserAgent(aUserAgent);
}
NS_IMETHODIMP
nsNavigator::GetAppCodeName(nsAString& aAppCodeName)
{
nsresult rv;
nsCOMPtr<nsIHttpProtocolHandler>
service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv));
if (NS_SUCCEEDED(rv)) {
nsCAutoString appName;
rv = service->GetAppName(appName);
CopyASCIItoUTF16(appName, aAppCodeName);
}
return rv;
}
NS_IMETHODIMP
nsNavigator::GetAppVersion(nsAString& aAppVersion)
{
return NS_GetNavigatorAppVersion(aAppVersion);
}
NS_IMETHODIMP
nsNavigator::GetAppName(nsAString& aAppName)
{
return NS_GetNavigatorAppName(aAppName);
}
NS_IMETHODIMP
nsNavigator::GetLanguage(nsAString& aLanguage)
{
nsresult rv;
nsCOMPtr<nsIHttpProtocolHandler>
service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv));
if (NS_SUCCEEDED(rv)) {
nsCAutoString lang;
rv = service->GetLanguage(lang);
CopyASCIItoUTF16(lang, aLanguage);
}
return rv;
}
NS_IMETHODIMP
nsNavigator::GetPlatform(nsAString& aPlatform)
{
return NS_GetNavigatorPlatform(aPlatform);
}
NS_IMETHODIMP
nsNavigator::GetOscpu(nsAString& aOSCPU)

View File

@ -1058,11 +1058,6 @@ protected:
nsIDocShell* mDocShell; // weak reference
};
nsresult NS_GetNavigatorUserAgent(nsAString& aUserAgent);
nsresult NS_GetNavigatorPlatform(nsAString& aPlatform);
nsresult NS_GetNavigatorAppVersion(nsAString& aAppVersion);
nsresult NS_GetNavigatorAppName(nsAString& aAppName);
class nsIURI;
//*****************************************************************************

View File

@ -4071,8 +4071,7 @@ static JSObject*
DOMReadStructuredClone(JSContext* cx,
JSStructuredCloneReader* reader,
uint32 tag,
uint32 data,
void* closure)
uint32 data)
{
// We don't currently support any extensions to structured cloning.
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_DOM_DATA_CLONE_ERR);
@ -4082,8 +4081,7 @@ DOMReadStructuredClone(JSContext* cx,
static JSBool
DOMWriteStructuredClone(JSContext* cx,
JSStructuredCloneWriter* writer,
JSObject* obj,
void *closure)
JSObject* obj)
{
// We don't currently support any extensions to structured cloning.
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_DOM_DATA_CLONE_ERR);

View File

@ -528,7 +528,7 @@ IDBObjectStore::GetKeyPathValueFromStructuredData(const PRUint8* aData,
jsval clone;
if (!JS_ReadStructuredClone(cx, reinterpret_cast<const uint64*>(aData),
aDataLength, JS_STRUCTURED_CLONE_VERSION,
&clone, NULL, NULL)) {
&clone)) {
return NS_ERROR_DOM_DATA_CLONE_ERR;
}

View File

@ -46,6 +46,8 @@
#include "nsIConsoleService.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "nsIDOMNavigator.h"
#include "nsIDOMWindowInternal.h"
#include "nsIEventTarget.h"
#include "nsIJSContextStack.h"
#include "nsIJSRuntimeService.h"
@ -63,7 +65,6 @@
#include "nsAutoPtr.h"
#include "nsContentUtils.h"
#include "nsDeque.h"
#include "nsGlobalWindow.h"
#include "nsIClassInfoImpl.h"
#include "nsStringBuffer.h"
#include "nsThreadUtils.h"
@ -755,9 +756,6 @@ nsDOMThreadService::Init()
success = mPools.Init();
NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
success = mThreadsafeContractIDs.Init();
NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
success = mJSContexts.SetCapacity(THREADPOOL_THREAD_CAP);
NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
@ -845,9 +843,6 @@ nsDOMThreadService::Cleanup()
// Init fails somehow. We can therefore assume that all services will still
// be available here.
// Cancel all workers that weren't tied to a window.
CancelWorkersForGlobal(nsnull);
{
nsAutoMonitor mon(mMonitor);
@ -1048,6 +1043,8 @@ already_AddRefed<nsDOMWorkerPool>
nsDOMThreadService::GetPoolForGlobal(nsIScriptGlobalObject* aGlobalObject,
PRBool aRemove)
{
NS_ASSERTION(aGlobalObject, "Null pointer!");
nsAutoMonitor mon(mMonitor);
nsRefPtr<nsDOMWorkerPool> pool;
@ -1120,6 +1117,8 @@ nsDOMThreadService::RescheduleSuspendedWorkerForPool(nsDOMWorkerPool* aPool)
void
nsDOMThreadService::CancelWorkersForGlobal(nsIScriptGlobalObject* aGlobalObject)
{
NS_ASSERTION(aGlobalObject, "Null pointer!");
nsRefPtr<nsDOMWorkerPool> pool = GetPoolForGlobal(aGlobalObject, PR_TRUE);
if (pool) {
pool->Cancel();
@ -1217,43 +1216,6 @@ nsDOMThreadService::ChangeThreadPoolMaxThreads(PRInt16 aDelta)
return NS_OK;
}
void
nsDOMThreadService::NoteThreadsafeContractId(const nsACString& aContractId,
PRBool aIsThreadsafe)
{
NS_ASSERTION(!aContractId.IsEmpty(), "Empty contract id!");
nsAutoMonitor mon(mMonitor);
#ifdef DEBUG
{
PRBool isThreadsafe;
if (mThreadsafeContractIDs.Get(aContractId, &isThreadsafe)) {
NS_ASSERTION(aIsThreadsafe == isThreadsafe, "Inconsistent threadsafety!");
}
}
#endif
if (!mThreadsafeContractIDs.Put(aContractId, aIsThreadsafe)) {
NS_WARNING("Out of memory!");
}
}
ThreadsafeStatus
nsDOMThreadService::GetContractIdThreadsafeStatus(const nsACString& aContractId)
{
NS_ASSERTION(!aContractId.IsEmpty(), "Empty contract id!");
nsAutoMonitor mon(mMonitor);
PRBool isThreadsafe;
if (mThreadsafeContractIDs.Get(aContractId, &isThreadsafe)) {
return isThreadsafe ? Threadsafe : NotThreadsafe;
}
return Unknown;
}
// static
nsIJSRuntimeService*
nsDOMThreadService::JSRuntimeService()
@ -1405,8 +1367,9 @@ nsDOMThreadService::RegisterWorker(nsDOMWorker* aWorker,
nsIScriptGlobalObject* aGlobalObject)
{
NS_ASSERTION(aWorker, "Null pointer!");
NS_ASSERTION(aGlobalObject, "Null pointer!");
if (aGlobalObject && NS_IsMainThread()) {
if (NS_IsMainThread()) {
nsCOMPtr<nsPIDOMWindow> domWindow(do_QueryInterface(aGlobalObject));
NS_ENSURE_TRUE(domWindow, NS_ERROR_NO_INTERFACE);
@ -1439,32 +1402,36 @@ nsDOMThreadService::RegisterWorker(nsDOMWorker* aWorker,
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
if (!mNavigatorStringsLoaded) {
rv = NS_GetNavigatorAppName(mAppName);
nsCOMPtr<nsIDOMWindowInternal> internal(do_QueryInterface(aGlobalObject));
NS_ENSURE_TRUE(internal, NS_ERROR_NO_INTERFACE);
nsCOMPtr<nsIDOMNavigator> navigator;
rv = internal->GetNavigator(getter_AddRefs(navigator));
NS_ENSURE_SUCCESS(rv, rv);
rv = NS_GetNavigatorAppVersion(mAppVersion);
rv = navigator->GetAppName(mAppName);
NS_ENSURE_SUCCESS(rv, rv);
rv = NS_GetNavigatorPlatform(mPlatform);
rv = navigator->GetAppVersion(mAppVersion);
NS_ENSURE_SUCCESS(rv, rv);
rv = NS_GetNavigatorUserAgent(mUserAgent);
rv = navigator->GetPlatform(mPlatform);
NS_ENSURE_SUCCESS(rv, rv);
rv = navigator->GetUserAgent(mUserAgent);
NS_ENSURE_SUCCESS(rv, rv);
mNavigatorStringsLoaded = PR_TRUE;
}
nsCOMPtr<nsIDocument> document;
if (aGlobalObject) {
nsCOMPtr<nsPIDOMWindow> domWindow(do_QueryInterface(aGlobalObject));
NS_ENSURE_TRUE(domWindow, NS_ERROR_NO_INTERFACE);
nsCOMPtr<nsPIDOMWindow> domWindow(do_QueryInterface(aGlobalObject));
NS_ENSURE_TRUE(domWindow, NS_ERROR_NO_INTERFACE);
nsIDOMDocument* domDocument = domWindow->GetExtantDocument();
NS_ENSURE_STATE(domDocument);
nsIDOMDocument* domDocument = domWindow->GetExtantDocument();
NS_ENSURE_STATE(domDocument);
document = do_QueryInterface(domDocument);
NS_ENSURE_STATE(document);
}
nsCOMPtr<nsIDocument> document(do_QueryInterface(domDocument));
NS_ENSURE_STATE(document);
pool = new nsDOMWorkerPool(aGlobalObject, document);
NS_ENSURE_TRUE(pool, NS_ERROR_OUT_OF_MEMORY);

View File

@ -49,7 +49,6 @@
#include "jsapi.h"
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "nsDataHashtable.h"
#include "nsRefPtrHashtable.h"
#include "nsStringGlue.h"
#include "nsTPtrArray.h"
@ -70,13 +69,6 @@ class nsIThreadJSContextStack;
class nsIXPConnect;
class nsIXPCSecurityManager;
enum ThreadsafeStatus
{
Threadsafe,
NotThreadsafe,
Unknown
};
class nsDOMThreadService : public nsIEventTarget,
public nsIObserver,
public nsIThreadPoolListener
@ -122,11 +114,6 @@ public:
nsresult ChangeThreadPoolMaxThreads(PRInt16 aDelta);
void NoteThreadsafeContractId(const nsACString& aContractId,
PRBool aIsThreadsafe);
ThreadsafeStatus GetContractIdThreadsafeStatus(const nsACString& aContractId);
private:
nsDOMThreadService();
~nsDOMThreadService();
@ -198,9 +185,6 @@ private:
// suspended. Always protected with mMonitor.
nsTArray<nsDOMWorkerRunnable*> mSuspendedWorkers;
// Always protected with mMonitor.
nsDataHashtable<nsCStringHashKey, PRBool> mThreadsafeContractIDs;
nsString mAppName;
nsString mAppVersion;
nsString mPlatform;

View File

@ -51,7 +51,6 @@
#include "nsAutoLock.h"
#include "nsAXPCNativeCallContext.h"
#include "nsContentUtils.h"
#include "nsDOMClassInfo.h"
#include "nsDOMClassInfoID.h"
#include "nsGlobalWindow.h"
#include "nsJSON.h"
@ -70,57 +69,6 @@
#include "nsDOMWorkerTimeout.h"
#include "nsDOMWorkerXHR.h"
class TestComponentThreadsafetyRunnable : public nsIRunnable
{
public:
NS_DECL_ISUPPORTS
TestComponentThreadsafetyRunnable(const nsACString& aContractId,
PRBool aService)
: mContractId(aContractId),
mService(aService),
mIsThreadsafe(PR_FALSE)
{ }
NS_IMETHOD Run()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
nsresult rv;
nsCOMPtr<nsISupports> instance;
if (mService) {
instance = do_GetService(mContractId.get(), &rv);
}
else {
instance = do_CreateInstance(mContractId.get(), &rv);
}
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIClassInfo> classInfo = do_QueryInterface(instance, &rv);
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 flags;
rv = classInfo->GetFlags(&flags);
NS_ENSURE_SUCCESS(rv, rv);
mIsThreadsafe = !!(flags & nsIClassInfo::THREADSAFE);
return NS_OK;
}
PRBool IsThreadsafe()
{
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
return mIsThreadsafe;
}
private:
nsCString mContractId;
PRBool mService;
PRBool mIsThreadsafe;
};
NS_IMPL_THREADSAFE_ISUPPORTS1(TestComponentThreadsafetyRunnable, nsIRunnable)
class nsDOMWorkerFunctions
{
public:
@ -167,19 +115,6 @@ public:
static JSBool
NewChromeWorker(JSContext* aCx, uintN aArgc, jsval* aVp);
static JSBool
XPCOMLazyGetter(JSContext* aCx, JSObject* aObj, jsid aId, jsval* aVp);
static JSBool
CreateInstance(JSContext* aCx, uintN aArgc, jsval* aVp) {
return GetInstanceCommon(aCx, aArgc, aVp, PR_FALSE);
}
static JSBool
GetService(JSContext* aCx, uintN aArgc, jsval* aVp) {
return GetInstanceCommon(aCx, aArgc, aVp, PR_TRUE);
}
#ifdef BUILD_CTYPES
static JSBool
CTypesLazyGetter(JSContext* aCx, JSObject* aObj, jsid aId, jsval* aVp);
@ -193,15 +128,6 @@ private:
static JSBool
MakeNewWorker(JSContext* aCx, uintN aArgc, jsval* aVp,
WorkerPrivilegeModel aPrivilegeModel);
static JSBool
GetInstanceCommon(JSContext* aCx, uintN aArgc, jsval* aVp, PRBool aService);
};
JSFunctionSpec gDOMWorkerXPCOMFunctions[] = {
{"createInstance", nsDOMWorkerFunctions::CreateInstance, 1, JSPROP_ENUMERATE},
{"getService", nsDOMWorkerFunctions::GetService, 1, JSPROP_ENUMERATE},
{ nsnull, nsnull, 0, 0 }
};
JSBool
@ -358,7 +284,7 @@ nsDOMWorkerFunctions::LoadScripts(JSContext* aCx,
return JS_FALSE;
}
rv = loader->LoadScripts(aCx, urls, PR_TRUE);
rv = loader->LoadScripts(aCx, urls, PR_FALSE);
if (NS_FAILED(rv)) {
if (!JS_IsExceptionPending(aCx)) {
JS_ReportError(aCx, "Failed to load scripts");
@ -482,170 +408,6 @@ nsDOMWorkerFunctions::NewChromeWorker(JSContext* aCx,
return MakeNewWorker(aCx, aArgc, aVp, nsDOMWorker::CHROME);
}
JSBool
nsDOMWorkerFunctions::XPCOMLazyGetter(JSContext* aCx,
JSObject* aObj,
jsid aId,
jsval* aVp)
{
#ifdef DEBUG
{
NS_ASSERTION(JS_GetGlobalForObject(aCx, aObj) == aObj, "Bad object!");
NS_ASSERTION(JSID_IS_STRING(aId), "Not a string!");
JSString* str = JSID_TO_STRING(aId);
NS_ASSERTION(nsDependentJSString(str).EqualsLiteral("XPCOM"), "Bad id!");
}
#endif
nsDOMWorker* worker = static_cast<nsDOMWorker*>(JS_GetContextPrivate(aCx));
NS_ASSERTION(worker, "This should be set by the DOM thread service!");
if (worker->IsCanceled()) {
return JS_FALSE;
}
PRUint16 dummy;
nsCOMPtr<nsIXPCSecurityManager> secMan;
nsContentUtils::XPConnect()->
GetSecurityManagerForJSContext(aCx, getter_AddRefs(secMan), &dummy);
if (!secMan) {
JS_ReportError(aCx, "Could not get security manager!");
return JS_FALSE;
}
nsCID dummyCID;
if (NS_FAILED(secMan->CanGetService(aCx, dummyCID))) {
JS_ReportError(aCx, "Access to the XPCOM object is denied!");
return JS_FALSE;
}
JSObject* xpcom = JS_NewObject(aCx, nsnull, nsnull, nsnull);
NS_ENSURE_TRUE(xpcom, JS_FALSE);
JSBool ok = JS_DefineFunctions(aCx, xpcom, gDOMWorkerXPCOMFunctions);
NS_ENSURE_TRUE(ok, JS_FALSE);
ok = JS_DeletePropertyById(aCx, aObj, aId);
NS_ENSURE_TRUE(ok, JS_FALSE);
jsval xpcomVal = OBJECT_TO_JSVAL(xpcom);
ok = JS_SetPropertyById(aCx, aObj, aId, &xpcomVal);
NS_ENSURE_TRUE(ok, JS_FALSE);
JS_SET_RVAL(aCx, aVp, xpcomVal);
return JS_TRUE;
}
JSBool
nsDOMWorkerFunctions::GetInstanceCommon(JSContext* aCx,
uintN aArgc,
jsval* aVp,
PRBool aService)
{
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
nsDOMWorker* worker = static_cast<nsDOMWorker*>(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, "Function requires at least 1 parameter");
return JS_FALSE;
}
JSString* str = JS_ValueToString(aCx, JS_ARGV(aCx, aVp)[0]);
if (!str) {
NS_ASSERTION(JS_IsExceptionPending(aCx), "Need to set an exception!");
return JS_FALSE;
}
JSAutoByteString strBytes(aCx, str);
if (!strBytes) {
NS_ASSERTION(JS_IsExceptionPending(aCx), "Need to set an exception!");
return JS_FALSE;
}
nsDependentCString contractId(strBytes.ptr(), JS_GetStringLength(str));
nsDOMThreadService* threadService = nsDOMThreadService::get();
ThreadsafeStatus status =
threadService->GetContractIdThreadsafeStatus(contractId);
if (status == Unknown) {
nsCOMPtr<nsIThread> mainThread;
nsresult rv = NS_GetMainThread(getter_AddRefs(mainThread));
if (NS_FAILED(rv)) {
JS_ReportError(aCx, "Failed to get main thread!");
return JS_FALSE;
}
nsRefPtr<TestComponentThreadsafetyRunnable> runnable =
new TestComponentThreadsafetyRunnable(contractId, aService);
rv = mainThread->Dispatch(runnable, NS_DISPATCH_SYNC);
if (NS_FAILED(rv)) {
JS_ReportError(aCx, "Failed to check threadsafety!");
return JS_FALSE;
}
// The worker may have been canceled while waiting above. Check again.
if (worker->IsCanceled()) {
return JS_FALSE;
}
if (runnable->IsThreadsafe()) {
threadService->NoteThreadsafeContractId(contractId, PR_TRUE);
status = Threadsafe;
}
else {
threadService->NoteThreadsafeContractId(contractId, PR_FALSE);
status = NotThreadsafe;
}
}
if (status == NotThreadsafe) {
JS_ReportError(aCx, "ChromeWorker may not create an XPCOM object that is "
"not threadsafe!");
return JS_FALSE;
}
nsCOMPtr<nsISupports> instance;
if (aService) {
instance = do_GetService(contractId.get());
if (!instance) {
JS_ReportError(aCx, "Could not get the service!");
return JS_FALSE;
}
}
else {
instance = do_CreateInstance(contractId.get());
if (!instance) {
JS_ReportError(aCx, "Could not create the instance!");
return JS_FALSE;
}
}
JSObject* global = JS_GetGlobalForObject(aCx, JS_GetScopeChain(aCx));
if (!global) {
NS_ASSERTION(JS_IsExceptionPending(aCx), "Need to set an exception!");
return JS_FALSE;
}
jsval val;
nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
if (NS_FAILED(nsContentUtils::WrapNative(aCx, global, instance, &val,
getter_AddRefs(wrapper)))) {
JS_ReportError(aCx, "Failed to wrap object!");
return JS_FALSE;
}
JS_SET_RVAL(aCx, aVp, val);
return JS_TRUE;
}
JSBool
nsDOMWorkerFunctions::MakeNewWorker(JSContext* aCx,
uintN aArgc,
@ -672,6 +434,10 @@ nsDOMWorkerFunctions::MakeNewWorker(JSContext* aCx,
// This pointer is protected by our pool, but it is *not* threadsafe and must
// not be used in any way other than to pass it along to the Initialize call.
nsIScriptGlobalObject* owner = worker->Pool()->ScriptGlobalObject();
if (!owner) {
JS_ReportError(aCx, "Couldn't get owner from pool!");
return JS_FALSE;
}
nsCOMPtr<nsIXPConnectWrappedNative> wrappedWorker =
worker->GetWrappedNative();
@ -787,70 +553,6 @@ JSFunctionSpec gDOMWorkerChromeFunctions[] = {
{ nsnull, nsnull, 0, 0 }
};
enum DOMWorkerStructuredDataType
{
// We have a special tag for XPCWrappedNatives that are being passed between
// threads. This will not work across processes and cannot be persisted. Only
// for ChromeWorker use at present.
DOMWORKER_SCTAG_WRAPPEDNATIVE = JS_SCTAG_USER_MIN + 0x1000,
DOMWORKER_SCTAG_END
};
PR_STATIC_ASSERT(DOMWORKER_SCTAG_END <= JS_SCTAG_USER_MAX);
// static
JSBool
WriteStructuredClone(JSContext* aCx,
JSStructuredCloneWriter* aWriter,
JSObject* aObj,
void* aClosure)
{
NS_ASSERTION(aClosure, "Null pointer!");
// We'll stash any nsISupports pointers that need to be AddRef'd here.
nsTArray<nsCOMPtr<nsISupports> >* wrappedNatives =
static_cast<nsTArray<nsCOMPtr<nsISupports> >*>(aClosure);
// See if this is a wrapped native.
nsCOMPtr<nsIXPConnectWrappedNative> wrappedNative;
nsContentUtils::XPConnect()->
GetWrappedNativeOfJSObject(aCx, aObj, getter_AddRefs(wrappedNative));
if (wrappedNative) {
// Get the raw nsISupports out of it.
nsISupports* wrappedObject = wrappedNative->Native();
NS_ASSERTION(wrappedObject, "Null pointer?!");
// See if this nsISupports is threadsafe.
nsCOMPtr<nsIClassInfo> classInfo = do_QueryInterface(wrappedObject);
if (classInfo) {
PRUint32 flags;
if (NS_SUCCEEDED(classInfo->GetFlags(&flags)) &&
(flags & nsIClassInfo::THREADSAFE)) {
// Write the raw pointer into the stream, and add it to the list we're
return JS_WriteUint32Pair(aWriter, DOMWORKER_SCTAG_WRAPPEDNATIVE, 0) &&
JS_WriteBytes(aWriter, &wrappedObject, sizeof(wrappedObject)) &&
wrappedNatives->AppendElement(wrappedObject);
}
}
}
// Something failed above, try using the runtime callbacks instead.
const JSStructuredCloneCallbacks* runtimeCallbacks =
aCx->runtime->structuredCloneCallbacks;
if (runtimeCallbacks) {
return runtimeCallbacks->write(aCx, aWriter, aObj, nsnull);
}
// We can't handle this object, throw an exception if one hasn't been thrown
// already.
if (!JS_IsExceptionPending(aCx)) {
nsDOMClassInfo::ThrowJSException(aCx, NS_ERROR_DOM_DATA_CLONE_ERR);
}
return JS_FALSE;
}
nsDOMWorkerScope::nsDOMWorkerScope(nsDOMWorker* aWorker)
: mWorker(aWorker),
mWrappedNative(nsnull),
@ -1392,7 +1094,7 @@ nsDOMWorker::~nsDOMWorker()
}
nsIURI* uri;
mBaseURI.forget(&uri);
mURI.forget(&uri);
if (uri) {
NS_ProxyRelease(mainThread, uri, PR_FALSE);
}
@ -1594,9 +1296,6 @@ nsDOMWorker::InitializeInternal(nsIScriptGlobalObject* aOwner,
PRUint32 aArgc,
jsval* aArgv)
{
NS_ASSERTION(aCx, "Null context!");
NS_ASSERTION(aObj, "Null global object!");
NS_ENSURE_TRUE(aArgc, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
NS_ENSURE_ARG_POINTER(aArgv);
@ -1606,68 +1305,6 @@ nsDOMWorker::InitializeInternal(nsIScriptGlobalObject* aOwner,
mScriptURL.Assign(nsDependentJSString(str));
NS_ENSURE_FALSE(mScriptURL.IsEmpty(), NS_ERROR_INVALID_ARG);
nsresult rv;
// Figure out the principal and base URI to use if we're on the main thread.
// Otherwise this is a sub-worker and it will have its principal set by the
// script loader.
if (NS_IsMainThread()) {
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
NS_ASSERTION(ssm, "Should never be null!");
PRBool isChrome;
rv = ssm->IsCapabilityEnabled("UniversalXPConnect", &isChrome);
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(isChrome || aOwner, "How can we have a non-chrome, non-window "
"worker?!");
// Chrome callers (whether ChromeWorker of Worker) always get the system
// principal.
if (isChrome) {
rv = ssm->GetSystemPrincipal(getter_AddRefs(mPrincipal));
NS_ENSURE_SUCCESS(rv, rv);
}
if (aOwner) {
// We're being created inside a window. Get the document's base URI and
// use it as our base URI.
nsCOMPtr<nsPIDOMWindow> domWindow = do_QueryInterface(aOwner, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsIDOMDocument* domDocument = domWindow->GetExtantDocument();
NS_ENSURE_STATE(domDocument);
nsCOMPtr<nsIDocument> document = do_QueryInterface(domDocument, &rv);
NS_ENSURE_SUCCESS(rv, rv);
mBaseURI = document->GetDocBaseURI();
if (!mPrincipal) {
// Use the document's NodePrincipal as our principal if we're not being
// called from chrome.
mPrincipal = document->NodePrincipal();
NS_ENSURE_STATE(mPrincipal);
}
}
else {
// We're being created outside of a window. Need to figure out the script
// that is creating us in order for us to use relative URIs later on.
JSStackFrame* frame = JS_GetScriptedCaller(aCx, nsnull);
if (frame) {
JSScript* script = JS_GetFrameScript(aCx, frame);
NS_ENSURE_STATE(script);
const char* filename = JS_GetScriptFilename(aCx, script);
rv = NS_NewURI(getter_AddRefs(mBaseURI), filename);
NS_ENSURE_SUCCESS(rv, rv);
}
}
NS_ASSERTION(mPrincipal, "Should have set the principal!");
}
mLock = nsAutoLock::NewLock("nsDOMWorker::mLock");
NS_ENSURE_TRUE(mLock, NS_ERROR_OUT_OF_MEMORY);
@ -1675,8 +1312,9 @@ nsDOMWorker::InitializeInternal(nsIScriptGlobalObject* aOwner,
nsCOMPtr<nsIXPConnectJSObjectHolder> thisWrapped;
jsval v;
rv = nsContentUtils::WrapNative(aCx, aObj, static_cast<nsIWorker*>(this), &v,
getter_AddRefs(thisWrapped));
nsresult rv = nsContentUtils::WrapNative(aCx, aObj,
static_cast<nsIWorker*>(this), &v,
getter_AddRefs(thisWrapped));
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(mWrappedNative, "Post-create hook should have set this!");
@ -1958,19 +1596,11 @@ nsDOMWorker::PostMessageInternal(PRBool aToInner)
rv = cc->GetJSContext(&cx);
NS_ENSURE_SUCCESS(rv, rv);
// If we're a ChromeWorker then we allow wrapped natives to be passed via
// structured cloning by supplying a custom write callback. To do that we need
// to make sure they stay alive while the message is being sent, so we collect
// the wrapped natives in an array to be packaged with the message.
JSStructuredCloneCallbacks callbacks = {
nsnull, IsPrivileged() ? WriteStructuredClone : nsnull, nsnull
};
JSAutoRequest ar(cx);
JSAutoStructuredCloneBuffer buffer;
nsTArray<nsCOMPtr<nsISupports> > wrappedNatives;
if (!buffer.write(cx, argv[0], &callbacks, &wrappedNatives)) {
if (!buffer.write(cx, argv[0])) {
return NS_ERROR_DOM_DATA_CLONE_ERR;
}
@ -1982,7 +1612,7 @@ nsDOMWorker::PostMessageInternal(PRBool aToInner)
nsnull);
NS_ENSURE_SUCCESS(rv, rv);
rv = message->SetJSData(cx, buffer, wrappedNatives);
rv = message->SetJSData(cx, buffer);
NS_ENSURE_SUCCESS(rv, rv);
nsRefPtr<nsDOMFireEventRunnable> runnable =
@ -2101,16 +1731,11 @@ nsDOMWorker::CompileGlobalObject(JSContext* aCx, nsLazyAutoRequest *aRequest,
success = JS_DefineFunctions(aCx, global, gDOMWorkerFunctions);
NS_ENSURE_TRUE(success, PR_FALSE);
if (IsPrivileged()) {
if (mPrivilegeModel == CHROME) {
// Add chrome functions.
success = JS_DefineFunctions(aCx, global, gDOMWorkerChromeFunctions);
NS_ENSURE_TRUE(success, PR_FALSE);
success = JS_DefineProperty(aCx, global, "XPCOM", JSVAL_VOID,
nsDOMWorkerFunctions::XPCOMLazyGetter, nsnull,
0);
NS_ENSURE_TRUE(success, PR_FALSE);
#ifdef BUILD_CTYPES
// Add the lazy getter for ctypes.
success = JS_DefineProperty(aCx, global, "ctypes", JSVAL_VOID,
@ -2131,6 +1756,13 @@ nsDOMWorker::CompileGlobalObject(JSContext* aCx, nsLazyAutoRequest *aRequest,
nsRefPtr<nsDOMWorkerScriptLoader> loader =
new nsDOMWorkerScriptLoader(this);
NS_ASSERTION(loader, "Out of memory!");
if (!loader) {
mGlobal = NULL;
mInnerScope = nsnull;
mScopeWN = nsnull;
return PR_FALSE;
}
rv = AddFeature(loader, aCx);
if (NS_FAILED(rv)) {
@ -2140,7 +1772,7 @@ nsDOMWorker::CompileGlobalObject(JSContext* aCx, nsLazyAutoRequest *aRequest,
return PR_FALSE;
}
rv = loader->LoadWorkerScript(aCx, mScriptURL);
rv = loader->LoadScript(aCx, mScriptURL, PR_TRUE);
JS_ReportPendingException(aCx);
@ -2151,33 +1783,7 @@ nsDOMWorker::CompileGlobalObject(JSContext* aCx, nsLazyAutoRequest *aRequest,
return PR_FALSE;
}
NS_ASSERTION(mPrincipal, "Script loader didn't set our principal!");
NS_ASSERTION(mBaseURI, "Script loader didn't set our base uri!");
// Make sure we kept the system principal.
if (IsPrivileged() && !nsContentUtils::IsSystemPrincipal(mPrincipal)) {
static const char warning[] = "ChromeWorker attempted to load a "
"non-chrome worker script!";
NS_WARNING(warning);
JS_ReportError(aCx, warning);
mGlobal = NULL;
mInnerScope = nsnull;
mScopeWN = nsnull;
return PR_FALSE;
}
rv = loader->ExecuteScripts(aCx);
JS_ReportPendingException(aCx);
if (NS_FAILED(rv)) {
mGlobal = NULL;
mInnerScope = nsnull;
mScopeWN = nsnull;
return PR_FALSE;
}
NS_ASSERTION(mPrincipal && mURI, "Script loader didn't set our principal!");
aRequest->swap(localRequest);
aComp->swap(localAutoCompartment);
@ -2331,22 +1937,14 @@ nsDOMWorker::ResumeFeatures()
}
}
void
nsDOMWorker::SetPrincipal(nsIPrincipal* aPrincipal)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(aPrincipal, "Null pointer!");
mPrincipal = aPrincipal;
}
nsresult
nsDOMWorker::SetBaseURI(nsIURI* aURI)
nsDOMWorker::SetURI(nsIURI* aURI)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(aURI, "Don't hand me a null pointer!");
NS_ASSERTION(!mURI && !mLocation, "Called more than once?!");
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
mBaseURI = aURI;
mURI = aURI;
nsCOMPtr<nsIURL> url(do_QueryInterface(aURI));
NS_ENSURE_TRUE(url, NS_ERROR_NO_INTERFACE);
@ -2357,14 +1955,6 @@ nsDOMWorker::SetBaseURI(nsIURI* aURI)
return NS_OK;
}
void
nsDOMWorker::ClearBaseURI()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
mBaseURI = nsnull;
mLocation = nsnull;
}
nsresult
nsDOMWorker::FireCloseRunnable(PRIntervalTime aTimeoutInterval,
PRBool aClearQueue,
@ -2407,11 +1997,7 @@ nsDOMWorker::FireCloseRunnable(PRIntervalTime aTimeoutInterval,
// Our worker has been collected and we want to keep the inner scope alive,
// so pass that along in the runnable.
if (aFromFinalize) {
// Make sure that our scope wrapped native exists here, but if the worker
// script failed to compile then it will be null already.
if (mGlobal) {
NS_ASSERTION(mScopeWN, "This shouldn't be null!");
}
NS_ASSERTION(mScopeWN, "This shouldn't be null!");
runnable->ReplaceWrappedNative(mScopeWN);
}
@ -2507,53 +2093,6 @@ nsDOMWorker::GetExpirationTime()
}
#endif
// static
JSObject*
nsDOMWorker::ReadStructuredClone(JSContext* aCx,
JSStructuredCloneReader* aReader,
uint32 aTag,
uint32 aData,
void* aClosure)
{
NS_ASSERTION(aCx, "Null context!");
NS_ASSERTION(aReader, "Null reader!");
NS_ASSERTION(!aClosure, "Shouldn't have a closure here!");
if (aTag == DOMWORKER_SCTAG_WRAPPEDNATIVE) {
NS_ASSERTION(!aData, "Huh?");
nsISupports* wrappedNative;
if (JS_ReadBytes(aReader, &wrappedNative, sizeof(wrappedNative))) {
NS_ASSERTION(wrappedNative, "Null pointer?!");
JSObject* global = JS_GetGlobalForObject(aCx, JS_GetScopeChain(aCx));
if (global) {
jsval val;
nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
if (NS_SUCCEEDED(nsContentUtils::WrapNative(aCx, global, wrappedNative,
&val,
getter_AddRefs(wrapper)))) {
return JSVAL_TO_OBJECT(val);
}
}
}
}
// Something failed above, try using the runtime callbacks instead.
const JSStructuredCloneCallbacks* runtimeCallbacks =
aCx->runtime->structuredCloneCallbacks;
if (runtimeCallbacks) {
return runtimeCallbacks->read(aCx, aReader, aTag, aData, nsnull);
}
// We can't handle this object, throw an exception if one hasn't been thrown
// already.
if (!JS_IsExceptionPending(aCx)) {
nsDOMClassInfo::ThrowJSException(aCx, NS_ERROR_DOM_DATA_CLONE_ERR);
}
return nsnull;
}
PRBool
nsDOMWorker::QueueSuspendedRunnable(nsIRunnable* aRunnable)
{
@ -2749,19 +2288,19 @@ nsWorkerFactory::NewChromeWorker(nsIWorker** _retval)
// Determine the current script global. We need it to register the worker.
// NewChromeDOMWorker will check that we are chrome, so no access check.
JSObject* global = JS_GetGlobalForScopeChain(cx);
NS_ENSURE_TRUE(global, NS_ERROR_UNEXPECTED);
JSObject* globalobj = JS_GetGlobalForScopeChain(cx);
NS_ENSURE_TRUE(globalobj, NS_ERROR_UNEXPECTED);
// May be null if we're being called from a JSM or something.
nsCOMPtr<nsIScriptGlobalObject> scriptGlobal =
nsJSUtils::GetStaticScriptGlobal(cx, global);
nsCOMPtr<nsIScriptGlobalObject> global =
nsJSUtils::GetStaticScriptGlobal(cx, globalobj);
NS_ENSURE_TRUE(global, NS_ERROR_UNEXPECTED);
// Create, initialize, and return the worker.
nsRefPtr<nsDOMWorker> chromeWorker;
rv = nsDOMWorker::NewChromeDOMWorker(getter_AddRefs(chromeWorker));
NS_ENSURE_SUCCESS(rv, rv);
rv = chromeWorker->InitializeInternal(scriptGlobal, cx, global, argc, argv);
rv = chromeWorker->InitializeInternal(global, cx, globalobj, argc, argv);
NS_ENSURE_SUCCESS(rv, rv);
chromeWorker.forget(_retval);

View File

@ -234,12 +234,6 @@ public:
return mPrivilegeModel == CHROME;
}
static JSObject* ReadStructuredClone(JSContext* aCx,
JSStructuredCloneReader* aReader,
uint32 aTag,
uint32 aData,
void* aClosure);
/**
* Use this chart to help figure out behavior during each of the closing
* statuses. Details below.
@ -314,15 +308,15 @@ private:
return mPrincipal;
}
void SetPrincipal(nsIPrincipal* aPrincipal);
nsIURI* GetBaseURI() {
return mBaseURI;
void SetPrincipal(nsIPrincipal* aPrincipal) {
mPrincipal = aPrincipal;
}
nsresult SetBaseURI(nsIURI* aURI);
nsIURI* GetURI() {
return mURI;
}
void ClearBaseURI();
nsresult SetURI(nsIURI* aURI);
nsresult FireCloseRunnable(PRIntervalTime aTimeoutInterval,
PRBool aClearQueue,
@ -370,7 +364,7 @@ private:
nsIXPConnectWrappedNative* mWrappedNative;
nsCOMPtr<nsIPrincipal> mPrincipal;
nsCOMPtr<nsIURI> mBaseURI;
nsCOMPtr<nsIURI> mURI;
PRInt32 mErrorHandlerRecursionCount;

View File

@ -279,10 +279,8 @@ NS_IMPL_CI_INTERFACE_GETTER2(nsDOMWorkerMessageEvent, nsIDOMEvent,
NS_IMPL_THREADSAFE_DOM_CI_GETINTERFACES(nsDOMWorkerMessageEvent)
nsresult
nsDOMWorkerMessageEvent::SetJSData(
JSContext* aCx,
JSAutoStructuredCloneBuffer& aBuffer,
nsTArray<nsCOMPtr<nsISupports> >& aWrappedNatives)
nsDOMWorkerMessageEvent::SetJSData(JSContext* aCx,
JSAutoStructuredCloneBuffer& aBuffer)
{
NS_ASSERTION(aCx, "Null context!");
@ -291,10 +289,6 @@ nsDOMWorkerMessageEvent::SetJSData(
return NS_ERROR_FAILURE;
}
if (!mWrappedNatives.SwapElements(aWrappedNatives)) {
NS_ERROR("This should never fail!");
}
aBuffer.steal(&mData, &mDataLen);
return NS_OK;
}
@ -321,17 +315,7 @@ nsDOMWorkerMessageEvent::GetData(nsAString& aData)
mData = nsnull;
mDataLen = 0;
JSStructuredCloneCallbacks callbacks = {
nsDOMWorker::ReadStructuredClone, nsnull, nsnull
};
JSBool ok = buffer.read(mDataVal.ToJSValPtr(), cx, &callbacks);
// Release wrapped natives now, regardless of whether or not the deserialize
// succeeded.
mWrappedNatives.Clear();
if (!ok) {
if (!buffer.read(mDataVal.ToJSValPtr())) {
NS_WARNING("Failed to deserialize!");
return NS_ERROR_FAILURE;
}

View File

@ -215,8 +215,7 @@ public:
~nsDOMWorkerMessageEvent();
nsresult SetJSData(JSContext* aCx,
JSAutoStructuredCloneBuffer& aBuffer,
nsTArray<nsCOMPtr<nsISupports> >& aWrappedNatives);
JSAutoStructuredCloneBuffer& aBuffer);
protected:
nsString mOrigin;
@ -225,7 +224,6 @@ protected:
nsAutoJSValHolder mDataVal;
uint64* mData;
size_t mDataLen;
nsTArray<nsCOMPtr<nsISupports> > mWrappedNatives;
};
class nsDOMWorkerProgressEvent : public nsDOMWorkerEvent,

View File

@ -71,6 +71,8 @@ nsDOMWorkerPool::nsDOMWorkerPool(nsIScriptGlobalObject* aGlobalObject,
mSuspended(PR_FALSE),
mWindowID(aDocument ? aDocument->OuterWindowID() : 0)
{
NS_ASSERTION(aGlobalObject, "Must have a global object!");
NS_ASSERTION(aDocument, "Must have a document!");
}
nsDOMWorkerPool::~nsDOMWorkerPool()

View File

@ -43,7 +43,6 @@
#include "nsIContentPolicy.h"
#include "nsIHttpChannel.h"
#include "nsIIOService.h"
#include "nsIProtocolHandler.h"
#include "nsIRequest.h"
#include "nsIScriptSecurityManager.h"
#include "nsIStreamLoader.h"
@ -91,7 +90,7 @@ NS_IMPL_ISUPPORTS_INHERITED2(nsDOMWorkerScriptLoader, nsDOMWorkerFeature,
nsresult
nsDOMWorkerScriptLoader::LoadScripts(JSContext* aCx,
const nsTArray<nsString>& aURLs,
PRBool aExecute)
PRBool aForWorker)
{
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(aCx, "Null context!");
@ -103,6 +102,8 @@ nsDOMWorkerScriptLoader::LoadScripts(JSContext* aCx,
return NS_ERROR_ABORT;
}
mForWorker = aForWorker;
mScriptCount = aURLs.Length();
if (!mScriptCount) {
return NS_ERROR_INVALID_ARG;
@ -146,26 +147,23 @@ nsDOMWorkerScriptLoader::LoadScripts(JSContext* aCx,
return rv;
}
if (aExecute) {
rv = ExecuteScripts(aCx);
if (NS_FAILED(rv)) {
return rv;
}
rv = ExecuteScripts(aCx);
if (NS_FAILED(rv)) {
return rv;
}
return NS_OK;
}
nsresult
nsDOMWorkerScriptLoader::LoadWorkerScript(JSContext* aCx,
const nsString& aURL)
nsDOMWorkerScriptLoader::LoadScript(JSContext* aCx,
const nsString& aURL,
PRBool aForWorker)
{
mForWorker = PR_TRUE;
nsAutoTArray<nsString, 1> url;
url.AppendElement(aURL);
return LoadScripts(aCx, url, PR_FALSE);
return LoadScripts(aCx, url, aForWorker);
}
nsresult
@ -410,57 +408,46 @@ nsDOMWorkerScriptLoader::RunInternal()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
// Things we need to make all this work...
nsCOMPtr<nsIDocument> parentDoc = mWorker->Pool()->ParentDocument();
if (!parentDoc) {
// Must have been canceled.
return NS_ERROR_ABORT;
}
nsIPrincipal* principal;
nsIURI* baseURI;
if (mForWorker) {
NS_ASSERTION(mScriptCount == 1, "Bad state!");
}
nsRefPtr<nsDOMWorker> parentWorker = mWorker->GetParent();
// Figure out which principal to use.
nsIPrincipal* principal = mWorker->GetPrincipal();
if (!principal) {
if (!parentWorker) {
NS_ERROR("Must have a principal if this is not a subworker!");
}
principal = parentWorker->GetPrincipal();
}
NS_ASSERTION(principal, "This should never be null here!");
// Figure out our base URI.
nsCOMPtr<nsIURI> baseURI;
if (mForWorker) {
nsRefPtr<nsDOMWorker> parentWorker = mWorker->GetParent();
if (parentWorker) {
baseURI = parentWorker->GetBaseURI();
NS_ASSERTION(baseURI, "Should have been set already!");
principal = parentWorker->GetPrincipal();
NS_ENSURE_STATE(principal);
baseURI = parentWorker->GetURI();
NS_ENSURE_STATE(baseURI);
}
else {
// May be null.
baseURI = mWorker->GetBaseURI();
principal = parentDoc->NodePrincipal();
NS_ENSURE_STATE(principal);
// Don't leave a temporary URI hanging around.
mWorker->ClearBaseURI();
baseURI = parentDoc->GetDocBaseURI();
}
NS_ASSERTION(!mWorker->GetBaseURI(), "Should not be set here!");
}
else {
baseURI = mWorker->GetBaseURI();
NS_ASSERTION(baseURI, "Should have been set already!");
}
principal = mWorker->GetPrincipal();
baseURI = mWorker->GetURI();
nsCOMPtr<nsIDocument> parentDoc = mWorker->Pool()->ParentDocument();
NS_ASSERTION(principal && baseURI, "Should have been set already!");
}
// All of these can potentially be null, but that should be ok. We'll either
// succeed without them or fail below.
nsCOMPtr<nsILoadGroup> loadGroup;
if (parentDoc) {
loadGroup = parentDoc->GetDocumentLoadGroup();
}
nsCOMPtr<nsILoadGroup> loadGroup(parentDoc->GetDocumentLoadGroup());
nsCOMPtr<nsIIOService> ios(do_GetIOService());
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
NS_ASSERTION(secMan, "This should never be null!");
for (PRUint32 index = 0; index < mScriptCount; index++) {
ScriptLoadInfo& loadInfo = mLoadInfos[index];
nsresult& rv = loadInfo.result;
@ -473,30 +460,39 @@ nsDOMWorkerScriptLoader::RunInternal()
return rv;
}
// If we're part of a document then check the content load policy.
if (parentDoc) {
PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_SCRIPT, uri,
principal, parentDoc,
NS_LITERAL_CSTRING("text/javascript"),
nsnull, &shouldLoad,
nsContentUtils::GetContentPolicy(),
secMan);
if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
if (NS_FAILED(rv) || shouldLoad != nsIContentPolicy::REJECT_TYPE) {
return (rv = NS_ERROR_CONTENT_BLOCKED);
}
return (rv = NS_ERROR_CONTENT_BLOCKED_SHOW_ALT);
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
NS_ENSURE_TRUE(secMan, NS_ERROR_FAILURE);
PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_SCRIPT, uri,
principal, parentDoc,
NS_LITERAL_CSTRING("text/javascript"),
nsnull, &shouldLoad,
nsContentUtils::GetContentPolicy(), secMan);
if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
if (NS_FAILED(rv) || shouldLoad != nsIContentPolicy::REJECT_TYPE) {
return NS_ERROR_CONTENT_BLOCKED;
}
return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
}
// If this script loader is being used to make a new worker then we need to
// do a same-origin check. Otherwise we need to clear the load with the
// security manager.
rv = mForWorker ?
principal->CheckMayLoad(uri, PR_FALSE):
secMan->CheckLoadURIWithPrincipal(principal, uri, 0);
NS_ENSURE_SUCCESS(rv, rv);
if (mForWorker) {
rv = principal->CheckMayLoad(uri, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
// Set the principal and URI on the new worker.
mWorker->SetPrincipal(principal);
rv = mWorker->SetURI(uri);
NS_ENSURE_SUCCESS(rv, rv);
}
else {
rv = secMan->CheckLoadURIWithPrincipal(principal, uri, 0);
NS_ENSURE_SUCCESS(rv, rv);
}
// We need to know which index we're on in OnStreamComplete so we know where
// to put the result.
@ -513,27 +509,25 @@ nsDOMWorkerScriptLoader::RunInternal()
rv = NS_NewStreamLoader(getter_AddRefs(loader), this);
NS_ENSURE_SUCCESS(rv, rv);
// Get Content Security Policy from parent document to pass into channel
nsCOMPtr<nsIContentSecurityPolicy> csp;
rv = principal->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
// get Content Security Policy from parent document to pass into channel
nsCOMPtr<nsIChannelPolicy> channelPolicy;
nsCOMPtr<nsIContentSecurityPolicy> csp;
rv = parentDoc->NodePrincipal()->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
if (csp) {
channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = channelPolicy->SetContentSecurityPolicy(csp);
NS_ENSURE_SUCCESS(rv, rv);
rv = channelPolicy->SetLoadType(nsIContentPolicy::TYPE_SCRIPT);
NS_ENSURE_SUCCESS(rv, rv);
channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
channelPolicy->SetContentSecurityPolicy(csp);
channelPolicy->SetLoadType(nsIContentPolicy::TYPE_SCRIPT);
}
rv = NS_NewChannel(getter_AddRefs(loadInfo.channel),
uri, ios, loadGroup, nsnull,
nsIRequest::LOAD_NORMAL | nsIChannel::LOAD_CLASSIFY_URI,
channelPolicy);
uri,
ios,
loadGroup,
nsnull, // callbacks
nsIRequest::LOAD_NORMAL |
nsIChannel::LOAD_CLASSIFY_URI, // loadFlags
channelPolicy); // CSP info
NS_ENSURE_SUCCESS(rv, rv);
rv = loadInfo.channel->AsyncOpen(loader, indexSupports);
@ -572,11 +566,34 @@ nsDOMWorkerScriptLoader::OnStreamCompleteInternal(nsIStreamLoader* aLoader,
NS_ASSERTION(!loadInfo.done, "Got complete on the same load twice!");
loadInfo.done = PR_TRUE;
// Use an alias to keep rv and loadInfo.result in sync.
nsresult& rv = loadInfo.result;
#ifdef DEBUG
// Make sure we're seeing the channel that we expect.
nsCOMPtr<nsIRequest> requestDebug;
nsresult rvDebug = aLoader->GetRequest(getter_AddRefs(requestDebug));
if (NS_FAILED(aStatus)) {
return rv = aStatus;
// When we cancel sometimes we get null here. That should be ok, but only if
// we're canceled.
NS_ASSERTION(NS_SUCCEEDED(rvDebug) || mCanceled, "GetRequest failed!");
if (NS_SUCCEEDED(rvDebug)) {
nsCOMPtr<nsIChannel> channel(do_QueryInterface(requestDebug));
NS_ASSERTION(channel, "QI failed!");
nsCOMPtr<nsISupports> thisChannel(do_QueryInterface(channel));
NS_ASSERTION(thisChannel, "QI failed!");
nsCOMPtr<nsISupports> ourChannel(do_QueryInterface(loadInfo.channel));
NS_ASSERTION(ourChannel, "QI failed!");
NS_ASSERTION(thisChannel == ourChannel, "Wrong channel!");
}
#endif
// Use an alias to keep rv and loadInfo.result in sync.
nsresult& rv = loadInfo.result = aStatus;
if (NS_FAILED(rv)) {
return rv;
}
if (!(aStringLen && aString)) {
@ -589,7 +606,7 @@ nsDOMWorkerScriptLoader::OnStreamCompleteInternal(nsIStreamLoader* aLoader,
rv = aLoader->GetRequest(getter_AddRefs(request));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(request);
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(request));
if (httpChannel) {
PRBool requestSucceeded;
rv = httpChannel->GetRequestSucceeded(&requestSucceeded);
@ -600,8 +617,12 @@ nsDOMWorkerScriptLoader::OnStreamCompleteInternal(nsIStreamLoader* aLoader,
}
}
// May be null.
nsIDocument* parentDoc = mWorker->Pool()->ParentDocument();
if (!parentDoc) {
NS_ASSERTION(mWorker->IsCanceled(),
"Null parent document when we're not canceled?!");
return rv = NS_ERROR_FAILURE;
}
// Use the regular nsScriptLoader for this grunt work! Should be just fine
// because we're running on the main thread.
@ -617,8 +638,7 @@ nsDOMWorkerScriptLoader::OnStreamCompleteInternal(nsIStreamLoader* aLoader,
}
nsCString filename;
rv = loadInfo.finalURI->GetSpec(filename);
NS_ENSURE_SUCCESS(rv, rv);
loadInfo.finalURI->GetSpec(filename);
if (filename.IsEmpty()) {
filename.Assign(NS_LossyConvertUTF16toASCII(loadInfo.url));
@ -629,32 +649,6 @@ nsDOMWorkerScriptLoader::OnStreamCompleteInternal(nsIStreamLoader* aLoader,
loadInfo.url.Assign(NS_ConvertUTF8toUTF16(filename));
}
// Update the principal of the worker and its base URI if we just loaded the
// worker's primary script.
if (mForWorker) {
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
NS_ASSERTION(channel, "This should never fail!");
// We're only going to muck with the principal if this worker has a
// non-system principal.
if (!nsContentUtils::IsSystemPrincipal(mWorker->GetPrincipal())) {
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
NS_ASSERTION(ssm, "Should never be null!");
nsCOMPtr<nsIPrincipal> principal;
rv = ssm->GetChannelPrincipal(channel, getter_AddRefs(principal));
NS_ENSURE_SUCCESS(rv, rv);
mWorker->SetPrincipal(principal);
}
nsCOMPtr<nsIURI> finalURI;
rv = NS_GetFinalChannelURI(channel, getter_AddRefs(finalURI));
NS_ENSURE_SUCCESS(rv, rv);
mWorker->SetBaseURI(finalURI);
}
nsRefPtr<ScriptCompiler> compiler =
new ScriptCompiler(this, loadInfo.scriptText, filename, loadInfo.scriptObj);
NS_ASSERTION(compiler, "Out of memory!");

View File

@ -103,12 +103,11 @@ public:
nsresult LoadScripts(JSContext* aCx,
const nsTArray<nsString>& aURLs,
PRBool aExecute);
PRBool aForWorker);
nsresult LoadWorkerScript(JSContext* aCx,
const nsString& aURL);
nsresult ExecuteScripts(JSContext* aCx);
nsresult LoadScript(JSContext* aCx,
const nsString& aURL,
PRBool aForWorker);
virtual void Cancel();
@ -118,6 +117,7 @@ private:
nsresult DoRunLoop(JSContext* aCx);
nsresult VerifyScripts(JSContext* aCx);
nsresult ExecuteScripts(JSContext* aCx);
nsresult RunInternal();

View File

@ -43,12 +43,9 @@
// Other includes
#include "jsapi.h"
#include "nsDOMError.h"
#include "nsThreadUtils.h"
// DOMWorker includes
#include "nsDOMThreadService.h"
#include "nsDOMWorker.h"
#define LOG(_args) PR_LOG(gDOMThreadsLog, PR_LOG_DEBUG, _args)
@ -76,7 +73,7 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(nsDOMWorkerSecurityManager,
nsIXPCSecurityManager)
NS_IMETHODIMP
nsDOMWorkerSecurityManager::CanCreateWrapper(JSContext* aCx,
nsDOMWorkerSecurityManager::CanCreateWrapper(JSContext* aJSContext,
const nsIID& aIID,
nsISupports* aObj,
nsIClassInfo* aClassInfo,
@ -86,22 +83,19 @@ nsDOMWorkerSecurityManager::CanCreateWrapper(JSContext* aCx,
}
NS_IMETHODIMP
nsDOMWorkerSecurityManager::CanCreateInstance(JSContext* aCx,
nsDOMWorkerSecurityManager::CanCreateInstance(JSContext* aJSContext,
const nsCID& aCID)
{
return CanGetService(aCx, aCID);
NS_NOTREACHED("Should not call this!");
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP
nsDOMWorkerSecurityManager::CanGetService(JSContext* aCx,
nsDOMWorkerSecurityManager::CanGetService(JSContext* aJSContext,
const nsCID& aCID)
{
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
nsDOMWorker* worker = static_cast<nsDOMWorker*>(JS_GetContextPrivate(aCx));
NS_ASSERTION(worker, "This should be set by the DOM thread service!");
return worker->IsPrivileged() ? NS_OK : NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED;
NS_NOTREACHED("Should not call this!");
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP

View File

@ -397,23 +397,22 @@ nsDOMWorkerXHRProxy::InitInternal()
NS_ASSERTION(!mXHR, "InitInternal shouldn't be called twice!");
nsDOMWorker* worker = mWorkerXHR->mWorker;
nsRefPtr<nsDOMWorkerPool> pool = worker->Pool();
if (worker->IsCanceled()) {
return NS_ERROR_ABORT;
}
NS_ASSERTION(worker->GetPrincipal(), "Must have a principal!");
NS_ASSERTION(worker->GetBaseURI(), "Must have a URI!");
nsIScriptGlobalObject* sgo = worker->Pool()->ScriptGlobalObject();
nsIScriptContext* scriptContext = sgo ? sgo->GetContext() : nsnull;
nsCOMPtr<nsPIDOMWindow> ownerWindow = do_QueryInterface(sgo);
nsIPrincipal* nodePrincipal = pool->ParentDocument()->NodePrincipal();
nsIScriptContext* scriptContext = pool->ScriptGlobalObject()->GetContext();
nsCOMPtr<nsPIDOMWindow> ownerWindow =
do_QueryInterface( pool->ScriptGlobalObject());
nsRefPtr<nsXMLHttpRequest> xhrConcrete = new nsXMLHttpRequest();
NS_ENSURE_TRUE(xhrConcrete, NS_ERROR_OUT_OF_MEMORY);
nsresult rv = xhrConcrete->Init(worker->GetPrincipal(), scriptContext,
ownerWindow, worker->GetBaseURI());
nsresult rv = xhrConcrete->Init(nodePrincipal, scriptContext, ownerWindow,
worker->GetURI());
NS_ENSURE_SUCCESS(rv, rv);
// Call QI manually here to avoid keeping up with the cast madness of

View File

@ -44,14 +44,6 @@ VPATH = @srcdir@
relativesrcdir = dom/src/threads/test
include $(DEPTH)/config/autoconf.mk
EXTRA_JS_MODULES = \
WorkerTest.jsm \
WorkerTest_worker.js \
WorkerTest_subworker.js \
testXHR.txt \
$(NULL)
include $(topsrcdir)/config/rules.mk
_TEST_FILES = \
@ -118,9 +110,6 @@ _TEST_FILES = \
test_newError.html \
newError_worker.js \
test_chromeWorker.html \
WorkerTest_badworker.js \
test_xpcom.html \
xpcom_worker.js \
$(NULL)
_SUBDIR_TEST_FILES = \
@ -132,7 +121,6 @@ _SUBDIR_TEST_FILES = \
_CHROME_TEST_FILES = \
test_chromeWorker.xul \
test_chromeWorkerComponent.xul \
test_chromeWorkerJSM.xul \
chromeWorker_worker.js \
chromeWorker_subworker.js \
$(NULL)

View File

@ -1,56 +0,0 @@
/* ***** 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 DOM Worker Tests.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Turner <bent.mozilla@gmail.com>
*
* 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 ***** */
let EXPORTED_SYMBOLS = [
"WorkerTest"
];
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
// Define our lazy getters.
XPCOMUtils.defineLazyServiceGetter(this, "workerFactory",
"@mozilla.org/threads/workerfactory;1",
"nsIWorkerFactory");
const WorkerTest = {
go: function(message, messageCallback, errorCallback) {
let worker = workerFactory.newChromeWorker("WorkerTest_worker.js");
worker.onmessage = messageCallback;
worker.onerror = errorCallback;
worker.postMessage(message);
}
};

View File

@ -1,64 +0,0 @@
/* ***** 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 DOM Worker Tests.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Turner <bent.mozilla@gmail.com>
*
* 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 ***** */
function onmessage(event) {
var xhr = new XMLHttpRequest();
xhr.open("GET", event.data, false);
try {
xhr.send();
}
catch (e) {
// NS_ERROR_DOM_BAD_URI
if (e.result != 2152924148) {
throw e;
}
}
if (xhr.responseText) {
throw "Shouldn't be able to xhr to a chrome URL!";
}
xhr = new XMLHttpRequest();
xhr.onload = function(event) {
postMessage(xhr.responseText);
};
xhr.open("GET", "testXHR.txt");
xhr.send();
}

View File

@ -1,74 +0,0 @@
/* ***** 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 DOM Worker Tests.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Turner <bent.mozilla@gmail.com>
*
* 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 ***** */
onmessage = function(event) {
// We should be able to XHR to anything we want.
let chromeURL = event.data.replace("test_chromeWorkerJSM.xul",
"WorkerTest_badworker.js");
let mochitestURL = event.data.replace("test_chromeWorkerJSM.xul",
"WorkerTest_badworker.js")
.replace("chrome://mochitests/content/chrome",
"http://mochi.test:8888/tests");
let anotherChromeURL = event.data.replace("test_chromeWorkerJSM.xul",
"chromeWorker_worker.js");
let xhr = new XMLHttpRequest();
xhr.open("GET", mochitestURL, false);
xhr.send();
if (!xhr.responseText) {
throw "Can't load script file via XHR!";
}
// But we shouldn't be able to make a ChromeWorker to anywhere we want.
let worker = new ChromeWorker(mochitestURL);
worker.onmessage = function(event) {
throw event.data;
};
worker.onerror = function(event) {
event.preventDefault();
// Though we should be able to make a regular Worker.
worker = new Worker(mochitestURL);
worker.onmessage = function(event) {
postMessage(event.data);
};
worker.postMessage(anotherChromeURL);
};
};

View File

@ -1,44 +0,0 @@
/* ***** 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 DOM Worker Tests.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Turner <bent.mozilla@gmail.com>
*
* 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 ***** */
onmessage = function(event) {
let worker = new ChromeWorker("WorkerTest_subworker.js");
worker.onmessage = function(event) {
postMessage(event.data);
}
worker.postMessage(event.data);
}

View File

@ -35,34 +35,8 @@
*
* ***** END LICENSE BLOCK ***** */
// Test XPCOM.getService()
let threadMan = XPCOM.getService("@mozilla.org/thread-manager;1");
let mainThread = threadMan.mainThread;
if (mainThread.isOnCurrentThread()) {
throw "Thread manager is lying to us!";
}
// Test XPCOM.createInstance
let threadPool = XPCOM.createInstance("@mozilla.org/thread-pool;1");
threadPool.shutdown();
let notThreadsafe;
try {
notThreadsafe = XPCOM.createInstance("@mozilla.org/supports-PRBool;1");
}
catch(e) { }
if (notThreadsafe) {
throw "Shouldn't be able to create non-threadsafe component!";
}
function onmessage(event) {
// Test passing wrapped natives from the main thread.
event.data.shutdown();
let worker = new ChromeWorker("chromeWorker_subworker.js");
worker.onmessage = function(event) {
postMessage(event.data);
}
worker.postMessage("Go");
let worker = new ChromeWorker("chromeWorker_subworker.js");
worker.onmessage = function(event) {
postMessage(event.data);
}
worker.postMessage("Go");

View File

@ -64,25 +64,6 @@
worker.terminate();
SimpleTest.finish();
}
// Test passing a non-threadsafe wrapped native to the worker.
var isupports =
Components.classes["@mozilla.org/supports-PRBool;1"]
.createInstance(Components.interfaces.nsISupportsPRBool);
try {
worker.postMessage(isupports);
ok(false, "Passing non-threadsafe thing should throw!");
}
catch (e) {
ok(true, "Passing non-threadsafe thing threw");
}
// Test passing a wrapped native to the worker.
var thread = Components.classes["@mozilla.org/thread-manager;1"]
.getService().newThread(0);
worker.postMessage(thread);
}
]]>

View File

@ -68,12 +68,6 @@
worker.terminate();
SimpleTest.finish();
}
// Test passing a wrapped native to the worker.
var thread = Components.classes["@mozilla.org/thread-manager;1"]
.getService().newThread(0);
worker.postMessage(thread);
}
]]>

View File

@ -1,81 +0,0 @@
<?xml version="1.0"?>
<!-- ***** 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 DOM Worker tests.
-
- The Initial Developer of the Original Code is
- The Mozilla Foundation.
- Portions created by the Initial Developer are Copyright (C) 2010
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
- Ben Turner <bent.mozilla@gmail.com>
-
- 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 LGPL or the GPL. 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 ***** -->
<window title="DOM Worker Threads Test"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="test();">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"/>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
<script type="application/javascript">
<![CDATA[
function test()
{
SimpleTest.waitForExplicitFinish();
function messageCallback(event) {
is(event.data, "A noisy noise annoys an oyster.", "Correct message");
SimpleTest.finish();
}
function errorCallback(event) {
ok(false, "Worker had an error: " + event.message);
SimpleTest.finish();
}
Components.utils.import("resource://gre/modules/WorkerTest.jsm");
WorkerTest.go(window.location.href + "", messageCallback, errorCallback);
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display:none;"></div>
<pre id="test"></pre>
</body>
<label id="test-result"/>
</window>

View File

@ -1,45 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for DOM Worker Threads</title>
<script type="text/javascript" src="/MochiKit/packed.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>
<pre id="test">
<script class="testbody" type="text/javascript">
var worker = new Worker("xpcom_worker.js");
worker.onmessage = function(event) {
is(event.data, "Done", "Correct message");
SimpleTest.finish();
};
worker.onerror = function(event) {
ok(false, "Worker had an error: " + event.message);
SimpleTest.finish();
};
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
// Test passing a wrapped native to the worker.
var thread = Components.classes["@mozilla.org/thread-manager;1"]
.getService().newThread(0);
try {
worker.postMessage(thread);
ok(false, "postMessage with a wrapped native should fail!");
}
catch(e) {
ok(true, "postMessage with a wrapped native failed");
}
worker.postMessage("Hi");
SimpleTest.waitForExplicitFinish();
</script>
</pre>
</body>
</html>

View File

@ -1,18 +0,0 @@
var exception;
try {
var xpcom = XPCOM;
}
catch(e) {
exception = e;
}
if (!exception) {
throw "Worker shouldn't be able to access the XPCOM object!";
}
onmessage = function(event) {
if (event.data != "Hi") {
throw "Bad message!";
}
postMessage("Done");
}

View File

@ -5481,48 +5481,26 @@ JS_FinishJSONParse(JSContext *cx, JSONParser *jp, jsval reviver)
}
JS_PUBLIC_API(JSBool)
JS_ReadStructuredClone(JSContext *cx, const uint64 *buf, size_t nbytes,
uint32 version, jsval *vp,
const JSStructuredCloneCallbacks *optionalCallbacks,
void *closure)
JS_ReadStructuredClone(JSContext *cx, const uint64 *buf, size_t nbytes, uint32 version, jsval *vp)
{
if (version > JS_STRUCTURED_CLONE_VERSION) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CLONE_VERSION);
return false;
}
const JSStructuredCloneCallbacks *callbacks =
optionalCallbacks ?
optionalCallbacks :
cx->runtime->structuredCloneCallbacks;
return ReadStructuredClone(cx, buf, nbytes, Valueify(vp), callbacks, closure);
return ReadStructuredClone(cx, buf, nbytes, Valueify(vp));
}
JS_PUBLIC_API(JSBool)
JS_WriteStructuredClone(JSContext *cx, jsval v, uint64 **bufp, size_t *nbytesp,
const JSStructuredCloneCallbacks *optionalCallbacks,
void *closure)
JS_WriteStructuredClone(JSContext *cx, jsval v, uint64 **bufp, size_t *nbytesp)
{
const JSStructuredCloneCallbacks *callbacks =
optionalCallbacks ?
optionalCallbacks :
cx->runtime->structuredCloneCallbacks;
return WriteStructuredClone(cx, Valueify(v), (uint64_t **) bufp, nbytesp,
callbacks, closure);
return WriteStructuredClone(cx, Valueify(v), (uint64_t **) bufp, nbytesp);
}
JS_PUBLIC_API(JSBool)
JS_StructuredClone(JSContext *cx, jsval v, jsval *vp,
ReadStructuredCloneOp optionalReadOp,
const JSStructuredCloneCallbacks *optionalCallbacks,
void *closure)
JS_StructuredClone(JSContext *cx, jsval v, jsval *vp)
{
const JSStructuredCloneCallbacks *callbacks =
optionalCallbacks ?
optionalCallbacks :
cx->runtime->structuredCloneCallbacks;
JSAutoStructuredCloneBuffer buf;
return buf.write(cx, v, callbacks, closure) &&
buf.read(vp, cx, callbacks, closure);
return buf.write(cx, v) && buf.read(vp);
}
JS_PUBLIC_API(void)

View File

@ -3207,28 +3207,15 @@ JS_FinishJSONParse(JSContext *cx, JSONParser *jp, jsval reviver);
/* The maximum supported structured-clone serialization format version. */
#define JS_STRUCTURED_CLONE_VERSION 1
struct JSStructuredCloneCallbacks {
ReadStructuredCloneOp read;
WriteStructuredCloneOp write;
StructuredCloneErrorOp reportError;
};
JS_PUBLIC_API(JSBool)
JS_ReadStructuredClone(JSContext *cx, const uint64 *data, size_t nbytes,
uint32 version, jsval *vp,
const JSStructuredCloneCallbacks *optionalCallbacks,
void *closure);
JS_ReadStructuredClone(JSContext *cx, const uint64 *data, size_t nbytes, uint32 version, jsval *vp);
/* Note: On success, the caller is responsible for calling js_free(*datap). */
JS_PUBLIC_API(JSBool)
JS_WriteStructuredClone(JSContext *cx, jsval v, uint64 **datap, size_t *nbytesp,
const JSStructuredCloneCallbacks *optionalCallbacks,
void *closure);
JS_WriteStructuredClone(JSContext *cx, jsval v, uint64 **datap, size_t *nbytesp);
JS_PUBLIC_API(JSBool)
JS_StructuredClone(JSContext *cx, jsval v, jsval *vp,
const JSStructuredCloneCallbacks *optionalCallbacks,
void *closure);
JS_StructuredClone(JSContext *cx, jsval v, jsval *vp);
#ifdef __cplusplus
/* RAII sugar for JS_WriteStructuredClone. */
@ -3293,24 +3280,18 @@ class JSAutoStructuredCloneBuffer {
version_ = 0;
}
bool read(jsval *vp, JSContext *cx=NULL,
const JSStructuredCloneCallbacks *optionalCallbacks=NULL,
void *closure=NULL) const {
bool read(jsval *vp, JSContext *cx=NULL) const {
if (!cx)
cx = cx_;
JS_ASSERT(cx);
JS_ASSERT(data_);
return !!JS_ReadStructuredClone(cx, data_, nbytes_, version_, vp,
optionalCallbacks, closure);
return !!JS_ReadStructuredClone(cx, data_, nbytes_, version_, vp);
}
bool write(JSContext *cx, jsval v,
const JSStructuredCloneCallbacks *optionalCallbacks=NULL,
void *closure=NULL) {
bool write(JSContext *cx, jsval v) {
clear(cx);
cx_ = cx;
bool ok = !!JS_WriteStructuredClone(cx, v, &data_, &nbytes_,
optionalCallbacks, closure);
bool ok = !!JS_WriteStructuredClone(cx, v, &data_, &nbytes_);
if (!ok) {
data_ = NULL;
nbytes_ = 0;
@ -3354,6 +3335,12 @@ class JSAutoStructuredCloneBuffer {
#define JS_SCERR_RECURSION 0
struct JSStructuredCloneCallbacks {
ReadStructuredCloneOp read;
WriteStructuredCloneOp write;
StructuredCloneErrorOp reportError;
};
JS_PUBLIC_API(void)
JS_SetStructuredCloneCallbacks(JSRuntime *rt, const JSStructuredCloneCallbacks *callbacks);

View File

@ -49,20 +49,18 @@ namespace js
{
bool
WriteStructuredClone(JSContext *cx, const Value &v, uint64 **bufp, size_t *nbytesp,
const JSStructuredCloneCallbacks *cb, void *cbClosure)
WriteStructuredClone(JSContext *cx, const Value &v, uint64 **bufp, size_t *nbytesp)
{
SCOutput out(cx);
JSStructuredCloneWriter w(out, cb, cbClosure);
JSStructuredCloneWriter w(out);
return w.init() && w.write(v) && out.extractBuffer(bufp, nbytesp);
}
bool
ReadStructuredClone(JSContext *cx, const uint64_t *data, size_t nbytes, Value *vp,
const JSStructuredCloneCallbacks *cb, void *cbClosure)
ReadStructuredClone(JSContext *cx, const uint64_t *data, size_t nbytes, Value *vp)
{
SCInput in(cx, data, nbytes);
JSStructuredCloneReader r(in, cb, cbClosure);
JSStructuredCloneReader r(in);
return r.read(vp);
}
@ -467,8 +465,9 @@ JSStructuredCloneWriter::startObject(JSObject *obj)
HashSet<JSObject *>::AddPtr p = memory.lookupForAdd(obj);
if (p) {
JSContext *cx = context();
if (callbacks && callbacks->reportError)
callbacks->reportError(cx, JS_SCERR_RECURSION);
const JSStructuredCloneCallbacks *cb = cx->runtime->structuredCloneCallbacks;
if (cb)
cb->reportError(cx, JS_SCERR_RECURSION);
else
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_SC_RECURSION);
return false;
@ -533,8 +532,9 @@ JSStructuredCloneWriter::startWrite(const js::Value &v)
return writeString(SCTAG_STRING_OBJECT, obj->getPrimitiveThis().toString());
}
if (callbacks && callbacks->write)
return callbacks->write(context(), this, obj, closure);
const JSStructuredCloneCallbacks *cb = context()->runtime->structuredCloneCallbacks;
if (cb)
return cb->write(context(), this, obj);
/* else fall through */
}
@ -786,12 +786,13 @@ JSStructuredCloneReader::startRead(Value *vp)
if (SCTAG_TYPED_ARRAY_MIN <= tag && tag <= SCTAG_TYPED_ARRAY_MAX)
return readTypedArray(tag, data, vp);
if (!callbacks || !callbacks->read) {
const JSStructuredCloneCallbacks *cb = context()->runtime->structuredCloneCallbacks;
if (!cb) {
JS_ReportErrorNumber(context(), js_GetErrorMessage, NULL, JSMSG_SC_BAD_SERIALIZED_DATA,
"unsupported type");
return false;
}
JSObject *obj = callbacks->read(context(), this, tag, data, closure);
JSObject *obj = cb->read(context(), this, tag, data);
if (!obj)
return false;
vp->setObject(*obj);

View File

@ -49,12 +49,10 @@
namespace js {
bool
WriteStructuredClone(JSContext *cx, const Value &v, uint64_t **bufp, size_t *nbytesp,
const JSStructuredCloneCallbacks *cb, void *cbClosure);
WriteStructuredClone(JSContext *cx, const Value &v, uint64_t **bufp, size_t *nbytesp);
bool
ReadStructuredClone(JSContext *cx, const uint64_t *data, size_t nbytes, Value *vp,
const JSStructuredCloneCallbacks *cb, void *cbClosure);
ReadStructuredClone(JSContext *cx, const uint64_t *data, size_t nbytes, Value *vp);
struct SCOutput {
public:
@ -111,9 +109,8 @@ struct SCInput {
struct JSStructuredCloneReader {
public:
explicit JSStructuredCloneReader(js::SCInput &in, const JSStructuredCloneCallbacks *cb,
void *cbClosure)
: in(in), objs(in.context()), callbacks(cb), closure(cbClosure) { }
explicit JSStructuredCloneReader(js::SCInput &in)
: in(in), objs(in.context()) {}
js::SCInput &input() { return in; }
bool read(js::Value *vp);
@ -132,20 +129,13 @@ struct JSStructuredCloneReader {
// Stack of objects with properties remaining to be read.
js::AutoValueVector objs;
// The user defined callbacks that will be used for cloning.
const JSStructuredCloneCallbacks *callbacks;
// Any value passed to JS_ReadStructuredClone.
void *closure;
};
struct JSStructuredCloneWriter {
public:
explicit JSStructuredCloneWriter(js::SCOutput &out, const JSStructuredCloneCallbacks *cb,
void *cbClosure)
explicit JSStructuredCloneWriter(js::SCOutput &out)
: out(out), objs(out.context()), counts(out.context()), ids(out.context()),
memory(out.context()), callbacks(cb), closure(cbClosure) { }
memory(out.context()) {}
bool init() { return memory.init(); }
@ -180,12 +170,6 @@ struct JSStructuredCloneWriter {
// The "memory" list described in the HTML5 internal structured cloning algorithm.
// memory has the same elements as objs.
js::HashSet<JSObject *> memory;
// The user defined callbacks that will be used for cloning.
const JSStructuredCloneCallbacks *callbacks;
// Any value passed to JS_WriteStructuredClone.
void *closure;
};
#endif /* jsclone_h___ */

View File

@ -584,11 +584,10 @@ typedef JSBool
*
* tag and data are the pair of uint32 values from the header. The callback may
* use the JS_Read* APIs to read any other relevant parts of the object from
* the reader r. closure is any value passed to the JS_ReadStructuredClone
* function. Return the new object on success, NULL on error/exception.
* the reader r. Return the new object on success, NULL on error/exception.
*/
typedef JSObject *(*ReadStructuredCloneOp)(JSContext *cx, JSStructuredCloneReader *r,
uint32 tag, uint32 data, void *closure);
uint32 tag, uint32 data);
/*
* Structured data serialization hook. The engine can write primitive values,
@ -597,12 +596,11 @@ typedef JSObject *(*ReadStructuredCloneOp)(JSContext *cx, JSStructuredCloneReade
* the JS_WriteUint32Pair API to write an object header, passing a value
* greater than JS_SCTAG_USER to the tag parameter. Then it can use the
* JS_Write* APIs to write any other relevant parts of the value v to the
* writer w. closure is any value passed to the JS_WriteStructuredCLone function.
* writer w.
*
* Return true on success, false on error/exception.
*/
typedef JSBool (*WriteStructuredCloneOp)(JSContext *cx, JSStructuredCloneWriter *w,
JSObject *obj, void *closure);
typedef JSBool (*WriteStructuredCloneOp)(JSContext *cx, JSStructuredCloneWriter *w, JSObject *obj);
/*
* This is called when JS_WriteStructuredClone finds that the object to be

View File

@ -4169,7 +4169,7 @@ Serialize(JSContext *cx, uintN argc, jsval *vp)
jsval v = argc > 0 ? JS_ARGV(cx, vp)[0] : JSVAL_VOID;
uint64 *datap;
size_t nbytes;
if (!JS_WriteStructuredClone(cx, v, &datap, &nbytes, NULL, NULL))
if (!JS_WriteStructuredClone(cx, v, &datap, &nbytes))
return false;
JSObject *arrayobj = js_CreateTypedArray(cx, TypedArray::TYPE_UINT8, nbytes);
@ -4201,7 +4201,7 @@ Deserialize(JSContext *cx, uintN argc, jsval *vp)
}
if (!JS_ReadStructuredClone(cx, (uint64 *) array->data, array->byteLength,
JS_STRUCTURED_CLONE_VERSION, &v, NULL, NULL)) {
JS_STRUCTURED_CLONE_VERSION, &v)) {
return false;
}
JS_SET_RVAL(cx, vp, v);

View File

@ -294,8 +294,7 @@ class Event
}
bool deserializeData(JSContext *cx, jsval *vp) {
return !!JS_ReadStructuredClone(cx, data, nbytes, JS_STRUCTURED_CLONE_VERSION, vp,
NULL, NULL);
return !!JS_ReadStructuredClone(cx, data, nbytes, JS_STRUCTURED_CLONE_VERSION, vp);
}
virtual Result process(JSContext *cx) = 0;
@ -308,7 +307,7 @@ class Event
{
uint64 *data;
size_t nbytes;
if (!JS_WriteStructuredClone(cx, v, &data, &nbytes, NULL, NULL))
if (!JS_WriteStructuredClone(cx, v, &data, &nbytes))
return NULL;
EventType *event = new EventType;