NS_IMETHOD Run() override { AssertIsOnMainThread(); MutexAutoLock lock(mProxy->GetCleanUpLock()); if (mProxy->IsClean()) { return NS_OK; } nsCOMPtr<nsIPermissionManager> permManager = mozilla::services::GetPermissionManager(); nsresult rv = NS_ERROR_FAILURE; PushPermissionState state = PushPermissionState::Denied; if (permManager) { uint32_t permission = nsIPermissionManager::DENY_ACTION; rv = permManager->TestExactPermissionFromPrincipal( mProxy->GetWorkerPrivate()->GetPrincipal(), "push", &permission); if (NS_SUCCEEDED(rv)) { switch (permission) { case nsIPermissionManager::ALLOW_ACTION: state = PushPermissionState::Granted; break; case nsIPermissionManager::DENY_ACTION: state = PushPermissionState::Denied; break; case nsIPermissionManager::PROMPT_ACTION: state = PushPermissionState::Prompt; break; default: MOZ_CRASH("Unexpected case!"); } } } AutoJSAPI jsapi; jsapi.Init(); nsRefPtr<PermissionResultRunnable> r = new PermissionResultRunnable(mProxy, rv, state); if (!r->Dispatch(jsapi.cx())) { ReleasePromiseWorkerProxy(mProxy.forget()); } return NS_OK; }
already_AddRefed<Promise> AudioContext::DecodeAudioData(const ArrayBuffer& aBuffer, const Optional<OwningNonNull<DecodeSuccessCallback> >& aSuccessCallback, const Optional<OwningNonNull<DecodeErrorCallback> >& aFailureCallback, ErrorResult& aRv) { nsCOMPtr<nsIGlobalObject> parentObject = do_QueryInterface(GetParentObject()); nsRefPtr<Promise> promise; AutoJSAPI jsapi; jsapi.Init(); JSContext* cx = jsapi.cx(); JSAutoCompartment ac(cx, aBuffer.Obj()); promise = Promise::Create(parentObject, aRv); if (aRv.Failed()) { return nullptr; } aBuffer.ComputeLengthAndData(); // Neuter the array buffer size_t length = aBuffer.Length(); JS::RootedObject obj(cx, aBuffer.Obj()); uint8_t* data = static_cast<uint8_t*>(JS_StealArrayBufferContents(cx, obj)); // Sniff the content of the media. // Failed type sniffing will be handled by AsyncDecodeWebAudio. nsAutoCString contentType; NS_SniffContent(NS_DATA_SNIFFER_CATEGORY, nullptr, data, length, contentType); nsRefPtr<DecodeErrorCallback> failureCallback; nsRefPtr<DecodeSuccessCallback> successCallback; if (aFailureCallback.WasPassed()) { failureCallback = &aFailureCallback.Value(); } if (aSuccessCallback.WasPassed()) { successCallback = &aSuccessCallback.Value(); } nsRefPtr<WebAudioDecodeJob> job( new WebAudioDecodeJob(contentType, this, promise, successCallback, failureCallback)); AsyncDecodeWebAudio(contentType.get(), data, length, *job); // Transfer the ownership to mDecodeJobs mDecodeJobs.AppendElement(job.forget()); return promise.forget(); }
bool SetAddonInterposition(const nsACString &addonIdStr, nsIAddonInterposition *interposition) { JSAddonId *addonId; { // We enter the junk scope just to allocate a string, which actually will go // in the system zone. AutoJSAPI jsapi; jsapi.Init(xpc::GetJunkScopeGlobal()); addonId = NewAddonId(jsapi.cx(), addonIdStr); if (!addonId) return false; } return XPCWrappedNativeScope::SetAddonInterposition(addonId, interposition); }
already_AddRefed<DOMRequest> MobileMessageManager::SendMMS(const MmsParameters& aParams, const MmsSendParameters& aSendParams, ErrorResult& aRv) { nsCOMPtr<nsIMmsService> mmsService = do_GetService(MMS_SERVICE_CONTRACTID); if (!mmsService) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } // Use the default one unless |aSendParams.serviceId| is available. uint32_t serviceId; nsresult rv; if (aSendParams.mServiceId.WasPassed()) { serviceId = aSendParams.mServiceId.Value(); } else { rv = mmsService->GetMmsDefaultServiceId(&serviceId); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } } AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(GetOwner()))) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } JSContext *cx = jsapi.cx(); JS::Rooted<JS::Value> val(cx); if (!ToJSValue(cx, aParams, &val)) { aRv.Throw(NS_ERROR_TYPE_ERR); return nullptr; } nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner()); nsCOMPtr<nsIMobileMessageCallback> msgCallback = new MobileMessageCallback(request); rv = mmsService->Send(serviceId, val, msgCallback); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget(); }
nsresult TranslateChoices( JS::HandleValue aChoices, const nsTArray<PermissionRequest>& aPermissionRequests, nsTArray<PermissionChoice>& aTranslatedChoices) { if (aChoices.isNullOrUndefined()) { // No choice is specified. } else if (aChoices.isObject()) { // Iterate through all permission types. for (uint32_t i = 0; i < aPermissionRequests.Length(); ++i) { nsCString type = aPermissionRequests[i].type(); JS::Rooted<JSObject*> obj(RootingCx(), &aChoices.toObject()); // People really shouldn't be passing WindowProxy or Location // objects for the choices here. obj = js::CheckedUnwrapStatic(obj); if (!obj) { return NS_ERROR_FAILURE; } AutoJSAPI jsapi; jsapi.Init(); JSContext* cx = jsapi.cx(); JSAutoRealm ar(cx, obj); JS::Rooted<JS::Value> val(cx); if (!JS_GetProperty(cx, obj, type.BeginReading(), &val) || !val.isString()) { // no setting for the permission type, clear exception and skip it jsapi.ClearException(); } else { nsAutoJSString choice; if (!choice.init(cx, val)) { jsapi.ClearException(); return NS_ERROR_FAILURE; } aTranslatedChoices.AppendElement(PermissionChoice(type, choice)); } } } else { MOZ_ASSERT(false, "SelectedChoices should be undefined or an JS object"); return NS_ERROR_FAILURE; } return NS_OK; }
virtual bool ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue) { aValue.setUndefined(); const BluetoothValue& v = mReply->get_BluetoothReplySuccess().value(); if (v.type() != BluetoothValue::TArrayOfBluetoothNamedValue) { BT_WARNING("Not a BluetoothNamedValue array!"); SetError(NS_LITERAL_STRING("BluetoothReplyTypeError")); return false; } const InfallibleTArray<BluetoothNamedValue>& values = v.get_ArrayOfBluetoothNamedValue(); nsTArray<nsRefPtr<BluetoothDevice> > devices; for (uint32_t i = 0; i < values.Length(); i++) { const BluetoothValue properties = values[i].value(); if (properties.type() != BluetoothValue::TArrayOfBluetoothNamedValue) { BT_WARNING("Not a BluetoothNamedValue array!"); SetError(NS_LITERAL_STRING("BluetoothReplyTypeError")); return false; } nsRefPtr<BluetoothDevice> d = BluetoothDevice::Create(mAdapterPtr->GetOwner(), mAdapterPtr->GetPath(), properties); devices.AppendElement(d); } AutoJSAPI jsapi; if (!jsapi.Init(mAdapterPtr->GetOwner())) { BT_WARNING("Failed to initialise AutoJSAPI!"); SetError(NS_LITERAL_STRING("BluetoothAutoJSAPIInitError")); return false; } JSContext* cx = jsapi.cx(); JS::Rooted<JSObject*> JsDevices(cx); if (NS_FAILED(nsTArrayToJSArray(cx, devices, &JsDevices))) { BT_WARNING("Cannot create JS array!"); SetError(NS_LITERAL_STRING("BluetoothError")); return false; } aValue.setObject(*JsDevices); return true; }
nsresult TelephonyDialCallback::NotifyDialMMISuccess(const nsAString& aStatusMessage) { AutoJSAPI jsapi; if (!NS_WARN_IF(jsapi.Init(mWindow))) { return NS_ERROR_FAILURE; } JSContext* cx = jsapi.cx(); MozMMIResult result; result.mServiceCode.Assign(mServiceCode); result.mStatusMessage.Assign(aStatusMessage); return NotifyDialMMISuccess(cx, result); }
bool WrapperAnswer::RecvDefineProperty(const ObjectId &objId, const JSIDVariant &idVar, const PPropertyDescriptor &descriptor, ReturnStatus *rs) { AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) return false; JSContext *cx = jsapi.cx(); RootedObject obj(cx, findObjectById(cx, objId)); if (!obj) return fail(cx, rs); LOG("define %s[%s]", ReceiverObj(objId), Identifier(idVar)); RootedId id(cx); if (!fromJSIDVariant(cx, idVar, &id)) return fail(cx, rs); Rooted<JSPropertyDescriptor> desc(cx); if (!toDescriptor(cx, descriptor, &desc)) return fail(cx, rs); if (!js::CheckDefineProperty(cx, obj, id, desc.value(), desc.attributes(), desc.getter(), desc.setter())) { return fail(cx, rs); } if (!JS_DefinePropertyById(cx, obj, id, desc.value(), // Descrriptors never store JSNatives for // accessors: they have either JSFunctions or // JSPropertyOps. desc.attributes() | JSPROP_PROPOP_ACCESSORS, JS_PROPERTYOP_GETTER(desc.getter() ? desc.getter() : JS_PropertyStub), JS_PROPERTYOP_SETTER(desc.setter() ? desc.setter() : JS_StrictPropertyStub))) { return fail(cx, rs); } return ok(rs); }
NS_IMETHODIMP MobileMessageCallback::NotifyGetSmscAddress(const nsAString& aSmscAddress) { AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(mDOMRequest->GetOwner()))) { return NotifyError(nsIMobileMessageCallback::INTERNAL_ERROR); } JSContext* cx = jsapi.cx(); JSString* smsc = JS_NewUCStringCopyN(cx, aSmscAddress.BeginReading(), aSmscAddress.Length()); if (!smsc) { return NotifyError(nsIMobileMessageCallback::INTERNAL_ERROR); } JS::Rooted<JS::Value> val(cx, JS::StringValue(smsc)); return NotifySuccess(val); }
void WorkerFetchResolver::OnResponseEnd() { AssertIsOnMainThread(); MutexAutoLock lock(mPromiseProxy->Lock()); if (mPromiseProxy->CleanedUp()) { return; } nsRefPtr<WorkerFetchResponseEndRunnable> r = new WorkerFetchResponseEndRunnable(mPromiseProxy->GetWorkerPrivate(), this); AutoJSAPI jsapi; jsapi.Init(); if (!r->Dispatch(jsapi.cx())) { NS_WARNING("Could not dispatch fetch response end"); } }
bool WrapperAnswer::RecvClassName(const ObjectId &objId, nsString *name) { AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) return false; JSContext *cx = jsapi.cx(); RootedObject obj(cx, findObjectById(cx, objId)); if (!obj) { // This is very unfortunate, but we have no choice. return "<dead CPOW>"; } LOG("%s.className()", ReceiverObj(objId)); *name = NS_ConvertASCIItoUTF16(js_ObjectClassName(cx, obj)); return true; }
XPCShellEnvironment::~XPCShellEnvironment() { if (GetGlobalObject()) { AutoJSAPI jsapi; if (!jsapi.Init(GetGlobalObject())) { return; } JSContext* cx = jsapi.cx(); Rooted<JSObject*> global(cx, GetGlobalObject()); { JSAutoCompartment ac(cx, global); JS_SetAllNonReservedSlotsToUndefined(cx, global); } mGlobalHolder.reset(); JS_GC(cx); } }
bool WrapperAnswer::RecvPreventExtensions(const ObjectId& objId, ReturnStatus* rs) { AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) return false; JSContext* cx = jsapi.cx(); RootedObject obj(cx, findObjectById(cx, objId)); if (!obj) return fail(cx, rs); ObjectOpResult success; if (!JS_PreventExtensions(cx, obj, success)) return fail(cx, rs); LOG("%s.preventExtensions()", ReceiverObj(objId)); return ok(rs, success); }
bool ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue) { aValue.setUndefined(); const BluetoothValue& v = mReply->get_BluetoothReplySuccess().value(); NS_ENSURE_TRUE(v.type() == BluetoothValue::TArrayOfuint8_t, false); AutoJSAPI jsapi; NS_ENSURE_TRUE(jsapi.Init(mCharacteristic->GetParentObject()), false); JSContext* cx = jsapi.cx(); if (!ToJSValue(cx, v.get_ArrayOfuint8_t(), aValue)) { JS_ClearPendingException(cx); return false; } return true; }
nsresult UDPSocket::DispatchReceivedData(const nsACString& aRemoteAddress, const uint16_t& aRemotePort, const uint8_t* aData, const uint32_t& aDataLength) { AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(GetOwner()))) { return NS_ERROR_FAILURE; } JSContext* cx = jsapi.cx(); // Copy packet data to ArrayBuffer JS::Rooted<JSObject*> arrayBuf(cx, ArrayBuffer::Create(cx, aDataLength, aData)); if (NS_WARN_IF(!arrayBuf)) { return NS_ERROR_FAILURE; } JS::Rooted<JS::Value> jsData(cx, JS::ObjectValue(*arrayBuf)); // Create DOM event RootedDictionary<UDPMessageEventInit> init(cx); init.mRemoteAddress = NS_ConvertUTF8toUTF16(aRemoteAddress); init.mRemotePort = aRemotePort; init.mData = jsData; RefPtr<UDPMessageEvent> udpEvent = UDPMessageEvent::Constructor(this, NS_LITERAL_STRING("message"), init); if (NS_WARN_IF(!udpEvent)) { return NS_ERROR_FAILURE; } udpEvent->SetTrusted(true); RefPtr<AsyncEventDispatcher> asyncDispatcher = new AsyncEventDispatcher(this, udpEvent); return asyncDispatcher->PostDOMEvent(); }
bool ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue) { aValue.setUndefined(); const BluetoothValue& v = mReply->get_BluetoothReplySuccess().value(); NS_ENSURE_TRUE(v.type() == BluetoothValue::TArrayOfnsString, false); const InfallibleTArray<nsString>& uuids = v.get_ArrayOfnsString(); AutoJSAPI jsapi; NS_ENSURE_TRUE(jsapi.Init(mDevice->GetParentObject()), false); JSContext* cx = jsapi.cx(); if (!ToJSValue(cx, uuids, aValue)) { BT_WARNING("Cannot create JS array!"); JS_ClearPendingException(cx); return false; } return true; }
bool WebAudioDecodeJob::AllocateBuffer() { MOZ_ASSERT(!mOutput); MOZ_ASSERT(NS_IsMainThread()); AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(mContext->GetOwner()))) { return false; } JSContext* cx = jsapi.cx(); // Now create the AudioBuffer ErrorResult rv; uint32_t channelCount = mBuffer->GetChannels(); mOutput = AudioBuffer::Create(mContext, channelCount, mWriteIndex, mContext->SampleRate(), mBuffer.forget(), cx, rv); return !rv.Failed(); }
nsresult PresentationConnection::DoReceiveMessage(const nsACString& aData, bool aIsBinary) { // Transform the data. AutoJSAPI jsapi; if (!jsapi.Init(GetOwner())) { return NS_ERROR_FAILURE; } JSContext* cx = jsapi.cx(); JS::Rooted<JS::Value> jsData(cx); nsresult rv; if (aIsBinary) { if (mBinaryType == PresentationConnectionBinaryType::Blob) { RefPtr<Blob> blob = Blob::CreateStringBlob(GetOwner(), aData, EmptyString()); MOZ_ASSERT(blob); if (!ToJSValue(cx, blob, &jsData)) { return NS_ERROR_FAILURE; } } else if (mBinaryType == PresentationConnectionBinaryType::Arraybuffer) { JS::Rooted<JSObject*> arrayBuf(cx); rv = nsContentUtils::CreateArrayBuffer(cx, aData, arrayBuf.address()); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } jsData.setObject(*arrayBuf); } else { NS_RUNTIMEABORT("Unknown binary type!"); return NS_ERROR_UNEXPECTED; } } else { NS_ConvertUTF8toUTF16 utf16Data(aData); if(NS_WARN_IF(!ToJSValue(cx, utf16Data, &jsData))) { return NS_ERROR_FAILURE; } } return DispatchMessageEvent(jsData); }
nsresult Initialize(nsIPrincipal* aPrincipal, const nsAString& aURL, const nsAString& aCacheName, nsILoadGroup* aLoadGroup) { AssertIsOnMainThread(); MOZ_ASSERT(aPrincipal); mURL = aURL; // Always create a CacheStorage since we want to write the network entry to // the cache even if there isn't an existing one. AutoJSAPI jsapi; jsapi.Init(); ErrorResult result; mSandbox.init(jsapi.cx()); mCacheStorage = CreateCacheStorage(jsapi.cx(), aPrincipal, result, &mSandbox); if (NS_WARN_IF(result.Failed())) { MOZ_ASSERT(!result.IsErrorWithMessage()); Cleanup(); return result.StealNSResult(); } mCN = new CompareNetwork(this); nsresult rv = mCN->Initialize(aPrincipal, aURL, aLoadGroup); if (NS_WARN_IF(NS_FAILED(rv))) { Cleanup(); return rv; } if (!aCacheName.IsEmpty()) { mCC = new CompareCache(this); rv = mCC->Initialize(aPrincipal, aURL, aCacheName); if (NS_WARN_IF(NS_FAILED(rv))) { mCN->Abort(); Cleanup(); return rv; } } return NS_OK; }
void TCPServerSocket::FireEvent(const nsAString& aType, TCPSocket* aSocket) { AutoJSAPI api; api.Init(GetOwnerGlobal()); TCPServerSocketEventInit init; init.mBubbles = false; init.mCancelable = false; init.mSocket = aSocket; RefPtr<TCPServerSocketEvent> event = TCPServerSocketEvent::Constructor(this, aType, init); event->SetTrusted(true); bool dummy; DispatchEvent(event, &dummy); if (mServerBridgeParent) { mServerBridgeParent->OnConnect(event); } }
NS_IMETHODIMP MobileConnectionCallback::NotifyGetClirStatusSuccess(uint16_t aN, uint16_t aM) { MozClirStatus result; result.mN.Construct(aN); result.mM.Construct(aM); AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(mWindow))) { return NS_ERROR_FAILURE; } JSContext* cx = jsapi.cx(); JS::Rooted<JS::Value> jsResult(cx); if (!ToJSValue(cx, result, &jsResult)) { JS_ClearPendingException(cx); return NS_ERROR_TYPE_ERR; } return NotifySuccess(jsResult); };
void FetchStream::Close() { AssertIsOnOwningThread(); MutexAutoLock lock(mMutex); if (mState == eClosed) { return; } AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(mGlobal))) { ReleaseObjects(lock); return; } JSContext* cx = jsapi.cx(); JS::Rooted<JSObject*> stream(cx, mStreamHolder->ReadableStreamBody()); CloseAndReleaseObjects(cx, lock, stream); }
NS_IMETHOD OnUnsubscribe(nsresult aStatus, bool aSuccess) override { AssertIsOnMainThread(); MOZ_ASSERT(mProxy, "OnUnsubscribe() called twice?"); nsRefPtr<PromiseWorkerProxy> proxy = mProxy.forget(); MutexAutoLock lock(proxy->Lock()); if (proxy->CleanedUp()) { return NS_OK; } AutoJSAPI jsapi; jsapi.Init(); nsRefPtr<UnsubscribeResultRunnable> r = new UnsubscribeResultRunnable(proxy, aStatus, aSuccess); r->Dispatch(jsapi.cx()); return NS_OK; }
NS_IMETHOD OnPushEndpoint(nsresult aStatus, const nsAString& aEndpoint) override { AssertIsOnMainThread(); MOZ_ASSERT(mProxy, "OnPushEndpoint() called twice?"); nsRefPtr<PromiseWorkerProxy> proxy = mProxy.forget(); MutexAutoLock lock(proxy->Lock()); if (proxy->CleanedUp()) { return NS_OK; } AutoJSAPI jsapi; jsapi.Init(); nsRefPtr<GetSubscriptionResultRunnable> r = new GetSubscriptionResultRunnable(proxy, aStatus, aEndpoint, mScope); r->Dispatch(jsapi.cx()); return NS_OK; }
bool WrapperAnswer::RecvObjectClassIs(const ObjectId &objId, const uint32_t &classValue, bool *result) { AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) return false; JSContext *cx = jsapi.cx(); RootedObject obj(cx, findObjectById(cx, objId)); if (!obj) { // This is very unfortunate, but we have no choice. *result = false; return true; } LOG("%s.objectClassIs()", ReceiverObj(objId)); *result = js_ObjectClassIs(cx, obj, (js::ESClassValue)classValue); return true; }
// This is called on main thread. nsresult ReceiveBlob(already_AddRefed<File> aBlob) { nsRefPtr<File> blob = aBlob; uint64_t size; nsresult rv = blob->GetSize(&size); if (NS_SUCCEEDED(rv)) { AutoJSAPI jsapi; if (jsapi.Init(mGlobal)) { JS_updateMallocCounter(jsapi.cx(), size); } } nsRefPtr<File> newBlob = new File(mGlobal, blob->Impl()); mozilla::ErrorResult error; mFileCallback->Call(*newBlob, error); mGlobal = nullptr; mFileCallback = nullptr; return error.StealNSResult(); }
already_AddRefed<InternalRequest> TypeUtils::ToInternalRequest(const nsAString& aIn, ErrorResult& aRv) { RequestOrUSVString requestOrString; requestOrString.SetAsUSVString().Rebind(aIn.Data(), aIn.Length()); // Re-create a GlobalObject stack object so we can use webidl Constructors. AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(GetGlobalObject()))) { aRv.Throw(NS_ERROR_UNEXPECTED); return nullptr; } JSContext* cx = jsapi.cx(); GlobalObject global(cx, GetGlobalObject()->GetGlobalJSObject()); MOZ_ASSERT(!global.Failed()); nsRefPtr<Request> request = Request::Constructor(global, requestOrString, RequestInit(), aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } return request->GetInternalRequest(); }
void MessagePort::DispatchError() { nsCOMPtr<nsIGlobalObject> globalObject = GetParentObject(); AutoJSAPI jsapi; if (!globalObject || !jsapi.Init(globalObject)) { NS_WARNING("Failed to initialize AutoJSAPI object."); return; } RootedDictionary<MessageEventInit> init(jsapi.cx()); init.mBubbles = false; init.mCancelable = false; RefPtr<Event> event = MessageEvent::Constructor(this, NS_LITERAL_STRING("messageerror"), init); event->SetTrusted(true); bool dummy; DispatchEvent(event, &dummy); }
bool WrapperAnswer::RecvIsExtensible(const ObjectId &objId, ReturnStatus *rs, bool *result) { AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) return false; JSContext *cx = jsapi.cx(); *result = false; RootedObject obj(cx, findObjectById(cx, objId)); if (!obj) return fail(cx, rs); LOG("%s.isExtensible()", ReceiverObj(objId)); bool extensible; if (!JS_IsExtensible(cx, obj, &extensible)) return fail(cx, rs); *result = !!extensible; return ok(rs); }
NS_IMETHODIMP MobileMessageCallback::NotifyMessageDeleted(bool *aDeleted, uint32_t aSize) { if (aSize == 1) { AutoJSContext cx; JS::Rooted<JS::Value> val(cx, JS::BooleanValue(*aDeleted)); return NotifySuccess(val); } AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(mDOMRequest->GetOwner()))) { return NS_ERROR_FAILURE; } JSContext* cx = jsapi.cx(); JS::Rooted<JSObject*> deleteArrayObj(cx, JS_NewArrayObject(cx, aSize)); for (uint32_t i = 0; i < aSize; i++) { JS_DefineElement(cx, deleteArrayObj, i, aDeleted[i], JSPROP_ENUMERATE); } JS::Rooted<JS::Value> deleteArrayVal(cx, JS::ObjectValue(*deleteArrayObj)); return NotifySuccess(deleteArrayVal); }