michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* vim: set ts=8 sts=4 et sw=4 tw=99: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsContentUtils.h" michael@0: #include "BackstagePass.h" michael@0: #include "nsIProgrammingLanguage.h" michael@0: #include "nsDOMClassInfo.h" michael@0: #include "nsIPrincipal.h" michael@0: michael@0: #include "mozilla/dom/workers/Workers.h" michael@0: michael@0: using mozilla::dom::workers::ResolveWorkerClasses; michael@0: michael@0: NS_INTERFACE_MAP_BEGIN(BackstagePass) michael@0: NS_INTERFACE_MAP_ENTRY(nsIGlobalObject) michael@0: NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable) michael@0: NS_INTERFACE_MAP_ENTRY(nsIClassInfo) michael@0: NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal) michael@0: NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) michael@0: NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCScriptable) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: NS_IMPL_ADDREF(BackstagePass) michael@0: NS_IMPL_RELEASE(BackstagePass) michael@0: michael@0: // The nsIXPCScriptable map declaration that will generate stubs for us... michael@0: #define XPC_MAP_CLASSNAME BackstagePass michael@0: #define XPC_MAP_QUOTED_CLASSNAME "BackstagePass" michael@0: #define XPC_MAP_WANT_NEWRESOLVE michael@0: #define XPC_MAP_WANT_FINALIZE michael@0: #define XPC_MAP_WANT_PRECREATE michael@0: michael@0: #define XPC_MAP_FLAGS nsIXPCScriptable::USE_JSSTUB_FOR_ADDPROPERTY | \ michael@0: nsIXPCScriptable::USE_JSSTUB_FOR_DELPROPERTY | \ michael@0: nsIXPCScriptable::USE_JSSTUB_FOR_SETPROPERTY | \ michael@0: nsIXPCScriptable::DONT_ENUM_STATIC_PROPS | \ michael@0: nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE | \ michael@0: nsIXPCScriptable::IS_GLOBAL_OBJECT | \ michael@0: nsIXPCScriptable::DONT_REFLECT_INTERFACE_NAMES michael@0: #include "xpc_map_end.h" /* This will #undef the above */ michael@0: michael@0: /* bool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, out JSObjectPtr objp); */ michael@0: NS_IMETHODIMP michael@0: BackstagePass::NewResolve(nsIXPConnectWrappedNative *wrapper, michael@0: JSContext * cx, JSObject * objArg, michael@0: jsid idArg, JSObject * *objpArg, michael@0: bool *_retval) michael@0: { michael@0: JS::RootedObject obj(cx, objArg); michael@0: JS::RootedId id(cx, idArg); michael@0: michael@0: bool resolved; michael@0: *objpArg = nullptr; michael@0: michael@0: *_retval = !!JS_ResolveStandardClass(cx, obj, id, &resolved); michael@0: NS_ENSURE_TRUE(*_retval, NS_ERROR_FAILURE); michael@0: michael@0: if (resolved) { michael@0: *objpArg = obj; michael@0: return NS_OK; michael@0: } michael@0: michael@0: JS::RootedObject objp(cx, *objpArg); michael@0: michael@0: *_retval = ResolveWorkerClasses(cx, obj, id, &objp); michael@0: NS_ENSURE_TRUE(*_retval, NS_ERROR_FAILURE); michael@0: michael@0: if (objp) { michael@0: *objpArg = objp; michael@0: return NS_OK; michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: /***************************************************************************/ michael@0: /* void getInterfaces (out uint32_t count, [array, size_is (count), retval] michael@0: out nsIIDPtr array); */ michael@0: NS_IMETHODIMP michael@0: BackstagePass::GetInterfaces(uint32_t *aCount, nsIID * **aArray) michael@0: { michael@0: const uint32_t count = 2; michael@0: *aCount = count; michael@0: nsIID **array; michael@0: *aArray = array = static_cast(nsMemory::Alloc(count * sizeof(nsIID*))); michael@0: if (!array) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: uint32_t index = 0; michael@0: nsIID* clone; michael@0: #define PUSH_IID(id) \ michael@0: clone = static_cast(nsMemory::Clone(&NS_GET_IID( id ), \ michael@0: sizeof(nsIID))); \ michael@0: if (!clone) \ michael@0: goto oom; \ michael@0: array[index++] = clone; michael@0: michael@0: PUSH_IID(nsIXPCScriptable) michael@0: PUSH_IID(nsIScriptObjectPrincipal) michael@0: #undef PUSH_IID michael@0: michael@0: return NS_OK; michael@0: oom: michael@0: while (index) michael@0: nsMemory::Free(array[--index]); michael@0: nsMemory::Free(array); michael@0: *aArray = nullptr; michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: michael@0: /* nsISupports getHelperForLanguage (in uint32_t language); */ michael@0: NS_IMETHODIMP michael@0: BackstagePass::GetHelperForLanguage(uint32_t language, michael@0: nsISupports **retval) michael@0: { michael@0: nsCOMPtr supports = michael@0: do_QueryInterface(static_cast(this)); michael@0: supports.forget(retval); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute string contractID; */ michael@0: NS_IMETHODIMP michael@0: BackstagePass::GetContractID(char * *aContractID) michael@0: { michael@0: *aContractID = nullptr; michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: /* readonly attribute string classDescription; */ michael@0: NS_IMETHODIMP michael@0: BackstagePass::GetClassDescription(char * *aClassDescription) michael@0: { michael@0: static const char classDescription[] = "BackstagePass"; michael@0: *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription)); michael@0: return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: michael@0: /* readonly attribute nsCIDPtr classID; */ michael@0: NS_IMETHODIMP michael@0: BackstagePass::GetClassID(nsCID * *aClassID) michael@0: { michael@0: *aClassID = nullptr; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute uint32_t implementationLanguage; */ michael@0: NS_IMETHODIMP michael@0: BackstagePass::GetImplementationLanguage(uint32_t *aImplementationLanguage) michael@0: { michael@0: *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute uint32_t flags; */ michael@0: NS_IMETHODIMP michael@0: BackstagePass::GetFlags(uint32_t *aFlags) michael@0: { michael@0: *aFlags = nsIClassInfo::MAIN_THREAD_ONLY; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */ michael@0: NS_IMETHODIMP michael@0: BackstagePass::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc) michael@0: { michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: BackstagePass::Finalize(nsIXPConnectWrappedNative *wrapper, JSFreeOp * fop, JSObject * obj) michael@0: { michael@0: nsCOMPtr bsp(do_QueryWrappedNative(wrapper)); michael@0: MOZ_ASSERT(bsp); michael@0: static_cast(bsp.get())->ForgetGlobalObject(); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: BackstagePass::PreCreate(nsISupports *nativeObj, JSContext *cx, michael@0: JSObject *globalObj, JSObject **parentObj) michael@0: { michael@0: // We do the same trick here as for WindowSH. Return the js global michael@0: // as parent, so XPConenct can find the right scope and the wrapper michael@0: // that already exists. michael@0: nsCOMPtr global(do_QueryInterface(nativeObj)); michael@0: MOZ_ASSERT(global, "nativeObj not a global object!"); michael@0: michael@0: JSObject *jsglobal = global->GetGlobalJSObject(); michael@0: if (jsglobal) michael@0: *parentObj = jsglobal; michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: NS_NewBackstagePass(BackstagePass** ret) michael@0: { michael@0: nsRefPtr bsp = new BackstagePass( michael@0: nsContentUtils::GetSystemPrincipal()); michael@0: bsp.forget(ret); michael@0: return NS_OK; michael@0: }