// static nsresult AsyncConnectionHelper::ConvertCloneBufferToJSVal( JSContext* aCx, JSAutoStructuredCloneBuffer& aBuffer, jsval* aResult) { NS_ASSERTION(aCx, "Null context!"); NS_ASSERTION(aResult, "Null pointer!"); JSAutoRequest ar(aCx); if (aBuffer.data()) { JSBool ok = aBuffer.read(aResult, aCx); aBuffer.clear(aCx); if (!ok) { NS_ERROR("Failed to decode!"); return NS_ERROR_DOM_DATA_CLONE_ERR; } } else { *aResult = JSVAL_VOID; } return NS_OK; }
bool WorkerMessagePort::MaybeDispatchEvent( JSContext* aCx, JSAutoStructuredCloneBuffer& aBuffer, nsTArray<nsCOMPtr<nsISupports>>& aClonedObjects) { if (mClosed) { NS_WARNING("Not going to ever run this event!"); aBuffer.clear(); aClonedObjects.Clear(); return true; } if (!mStarted) { // Queue the message for later. MessageInfo* info = mQueuedMessages.AppendElement(); info->mBuffer.swap(aBuffer); info->mClonedObjects.SwapElements(aClonedObjects); return true; } // Go ahead and dispatch the event. JS::Rooted<JSObject*> target(aCx, GetJSObject()); return DispatchMessageEvent(aCx, target, aBuffer, aClonedObjects); }
virtual bool MainThreadRun() override { AssertIsOnMainThread(); // Initialise an AutoJSAPI with the target window. AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(mBackingStore->GetParentObject()))) { mRv.Throw(NS_ERROR_UNEXPECTED); return true; } JSContext* cx = jsapi.cx(); JS::Rooted<JS::Value> value(cx); if (!mObjBuffer.read(cx, &value)) { JS_ClearPendingException(cx); mRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR); return true; } nsRefPtr<Promise> promise = mBackingStore->Add(cx, value, mId, mRevisionId, mRv); promise->AppendNativeHandler(mPromiseWorkerProxy); return true; }
static bool Serialize(JSContext *cx, unsigned argc, jsval *vp) { CallArgs args = CallArgsFromVp(argc, vp); JSAutoStructuredCloneBuffer clonebuf; if (!clonebuf.write(cx, args.get(0), args.get(1))) return false; RootedObject obj(cx, CloneBufferObject::Create(cx, &clonebuf)); if (!obj) return false; args.rval().setObject(*obj); return true; }
bool WriteStructuredClone(JSContext* aCx, JS::Handle<JS::Value> aSource, JSAutoStructuredCloneBuffer& aBuffer, StructuredCloneClosure& aClosure) { return aBuffer.write(aCx, aSource, &gCallbacks, &aClosure); }
static jobject CloneInstance(JNIEnv* env, jobject instance) { NativeJSContainer* const container = FromInstance(env, instance); if (!container || !container->EnsureObject(env)) { return nullptr; } JSContext* const cx = container->mThreadContext; JS::RootedObject object(cx, container->mJSObject); MOZ_ASSERT(object); JSAutoStructuredCloneBuffer buffer; if (!buffer.write(cx, JS::RootedValue(cx, JS::ObjectValue(*object)))) { AndroidBridge::ThrowException(env, "java/lang/UnsupportedOperationException", "Cannot serialize object"); return nullptr; } return CreateInstance(env, new NativeJSContainer(cx, Move(buffer))); }
void ServiceWorkerClient::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage, const Optional<Sequence<JS::Value>>& aTransferable, ErrorResult& aRv) { WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(workerPrivate); workerPrivate->AssertIsOnWorkerThread(); JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue()); if (aTransferable.WasPassed()) { const Sequence<JS::Value>& realTransferable = aTransferable.Value(); JS::HandleValueArray elements = JS::HandleValueArray::fromMarkedLocation(realTransferable.Length(), realTransferable.Elements()); JSObject* array = JS_NewArrayObject(aCx, elements); if (!array) { aRv.Throw(NS_ERROR_OUT_OF_MEMORY); return; } transferable.setObject(*array); } const JSStructuredCloneCallbacks* callbacks = WorkerStructuredCloneCallbacks(false); WorkerStructuredCloneClosure closure; JSAutoStructuredCloneBuffer buffer; if (!buffer.write(aCx, aMessage, transferable, callbacks, &closure)) { aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR); return; } nsRefPtr<ServiceWorkerClientPostMessageRunnable> runnable = new ServiceWorkerClientPostMessageRunnable(mWindowId, Move(buffer), closure); nsresult rv = NS_DispatchToMainThread(runnable); if (NS_FAILED(rv)) { aRv.Throw(NS_ERROR_FAILURE); } }
/* * General-purpose structured-cloning utility for cases where the structured * clone buffer is only used in stack-scope (that is to say, the buffer does * not escape from this function). The stack-scoping allows us to pass * references to various JSObjects directly in certain situations without * worrying about lifetime issues. * * This function assumes that |cx| is already entered the compartment we want * to clone to, and that |val| may not be same-compartment with cx. When the * function returns, |val| is set to the result of the clone. */ bool StackScopedClone(JSContext *cx, StackScopedCloneOptions &options, MutableHandleValue val) { JSAutoStructuredCloneBuffer buffer; StackScopedCloneData data(cx, &options); { // For parsing val we have to enter its compartment. // (unless it's a primitive) Maybe<JSAutoCompartment> ac; if (val.isObject()) { ac.construct(cx, &val.toObject()); } else if (val.isString() && !JS_WrapValue(cx, val)) { return false; } if (!buffer.write(cx, val, &gStackScopedCloneCallbacks, &data)) return false; } // Now recreate the clones in the target compartment. return buffer.read(cx, val, &gStackScopedCloneCallbacks, &data); }
DataStoreAddRunnable(WorkerPrivate* aWorkerPrivate, const nsMainThreadPtrHandle<DataStore>& aBackingStore, Promise* aWorkerPromise, JSContext* aCx, JS::Handle<JS::Value> aObj, const Optional<StringOrUnsignedLong>& aId, const nsAString& aRevisionId, ErrorResult& aRv) : DataStoreProxyRunnable(aWorkerPrivate, aBackingStore, aWorkerPromise) , mId(aId) , mRevisionId(aRevisionId) , mRv(aRv) { MOZ_ASSERT(aWorkerPrivate); aWorkerPrivate->AssertIsOnWorkerThread(); // This needs to be structured cloned while it's still on the worker thread. if (!mObjBuffer.write(aCx, aObj)) { JS_ClearPendingException(aCx); mRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR); } }
NS_IMETHODIMP PostMessageRunnable::Run() { MOZ_ASSERT(mPort); // Ensure that the buffer is freed even if we fail to post the message JSAutoStructuredCloneBuffer buffer; buffer.adopt(mMessage, mMessageLen); mMessage = nullptr; mMessageLen = 0; // Get the JSContext for the target window nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(mPort->GetOwner()); NS_ENSURE_STATE(sgo); nsCOMPtr<nsIScriptContext> scriptContext = sgo->GetContext(); AutoPushJSContext cx(scriptContext ? scriptContext->GetNativeContext() : nsContentUtils::GetSafeJSContext()); MOZ_ASSERT(cx); // Deserialize the structured clone data JS::Rooted<JS::Value> messageData(cx); { StructuredCloneInfo scInfo; scInfo.mEvent = this; scInfo.mPort = mPort; if (!buffer.read(cx, messageData.address(), &kPostMessageCallbacks, &scInfo)) { return NS_ERROR_DOM_DATA_CLONE_ERR; } } // Create the event nsIDocument* doc = mPort->GetOwner()->GetExtantDoc(); if (!doc) { return NS_OK; } ErrorResult error; nsRefPtr<nsDOMEvent> event = doc->CreateEvent(NS_LITERAL_STRING("MessageEvent"), error); if (error.Failed()) { return NS_OK; } nsCOMPtr<nsIDOMMessageEvent> message = do_QueryInterface(event); nsresult rv = message->InitMessageEvent(NS_LITERAL_STRING("message"), false /* non-bubbling */, true /* cancelable */, messageData, EmptyString(), EmptyString(), mPort->GetOwner()); if (NS_FAILED(rv)) { return NS_OK; } message->SetTrusted(true); bool status; mPort->DispatchEvent(event, &status); return status ? NS_OK : NS_ERROR_FAILURE; }