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; }
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; }
bool WrapperAnswer::RecvPreventExtensions(const ObjectId &objId, ReturnStatus *rs, bool *succeeded) { AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) return false; JSContext *cx = jsapi.cx(); *succeeded = false; RootedObject obj(cx, findObjectById(cx, objId)); if (!obj) return fail(cx, rs); if (!JS_PreventExtensions(cx, obj, succeeded)) return fail(cx, rs); LOG("%s.preventExtensions()", ReceiverObj(objId)); return ok(rs); }
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; }
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); } }
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_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 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); }
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 BluetoothDevice::SetPropertyByValue(const BluetoothNamedValue& aValue) { const nsString& name = aValue.name(); const BluetoothValue& value = aValue.value(); if (name.EqualsLiteral("Name")) { mName = value.get_nsString(); } else if (name.EqualsLiteral("Path")) { MOZ_ASSERT(value.get_nsString().Length() > 0); mPath = value.get_nsString(); } else if (name.EqualsLiteral("Address")) { mAddress = value.get_nsString(); } else if (name.EqualsLiteral("Class")) { mClass = value.get_uint32_t(); } else if (name.EqualsLiteral("Icon")) { mIcon = value.get_nsString(); } else if (name.EqualsLiteral("Connected")) { mConnected = value.get_bool(); } else if (name.EqualsLiteral("Paired")) { mPaired = value.get_bool(); } else if (name.EqualsLiteral("UUIDs")) { mUuids = value.get_ArrayOfnsString(); AutoJSAPI jsapi; if (!jsapi.Init(GetOwner())) { BT_WARNING("Failed to initialise AutoJSAPI!"); return; } JSContext* cx = jsapi.cx(); JS::Rooted<JSObject*> uuids(cx); if (NS_FAILED(nsTArrayToJSArray(cx, mUuids, &uuids))) { BT_WARNING("Cannot set JS UUIDs object!"); return; } mJsUuids = uuids; Root(); } else if (name.EqualsLiteral("Services")) { mServices = value.get_ArrayOfnsString(); AutoJSAPI jsapi; if (!jsapi.Init(GetOwner())) { BT_WARNING("Failed to initialise AutoJSAPI!"); return; } JSContext* cx = jsapi.cx(); JS::Rooted<JSObject*> services(cx); if (NS_FAILED(nsTArrayToJSArray(cx, mServices, &services))) { BT_WARNING("Cannot set JS Services object!"); return; } mJsServices = services; Root(); } else { nsCString warningMsg; warningMsg.AssignLiteral("Not handling device property: "); warningMsg.Append(NS_ConvertUTF16toUTF8(name)); BT_WARNING(warningMsg.get()); } }
// 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(); }
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); }
nsresult nsJSUtils::CompileFunction(AutoJSAPI& jsapi, JS::AutoObjectVector& aScopeChain, JS::CompileOptions& aOptions, const nsACString& aName, uint32_t aArgCount, const char** aArgArray, const nsAString& aBody, JSObject** aFunctionObject) { MOZ_ASSERT(jsapi.OwnsErrorReporting()); JSContext* cx = jsapi.cx(); MOZ_ASSERT(js::GetEnterCompartmentDepth(cx) > 0); MOZ_ASSERT_IF(aScopeChain.length() != 0, js::IsObjectInContextCompartment(aScopeChain[0], cx)); MOZ_ASSERT_IF(aOptions.versionSet, aOptions.version != JSVERSION_UNKNOWN); mozilla::DebugOnly<nsIScriptContext*> ctx = GetScriptContextFromJSContext(cx); MOZ_ASSERT_IF(ctx, ctx->IsContextInitialized()); // Do the junk Gecko is supposed to do before calling into JSAPI. for (size_t i = 0; i < aScopeChain.length(); ++i) { JS::ExposeObjectToActiveJS(aScopeChain[i]); } // Compile. JS::Rooted<JSFunction*> fun(cx); if (!JS::CompileFunction(cx, aScopeChain, aOptions, PromiseFlatCString(aName).get(), aArgCount, aArgArray, PromiseFlatString(aBody).get(), aBody.Length(), &fun)) { return NS_ERROR_FAILURE; } *aFunctionObject = JS_GetFunctionObject(fun); return NS_OK; }
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()); return result.StealNSResult(); } mCN = new CompareNetwork(this); nsresult rv = mCN->Initialize(aPrincipal, aURL, aLoadGroup); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (!aCacheName.IsEmpty()) { mCC = new CompareCache(this); rv = mCC->Initialize(aPrincipal, aURL, aCacheName); if (NS_WARN_IF(NS_FAILED(rv))) { mCN->Abort(); return rv; } } return NS_OK; }
bool WrapperAnswer::RecvDelete(const ObjectId& objId, const JSIDVariant& idVar, 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("delete %s[%s]", ReceiverObj(objId), Identifier(idVar)); RootedId id(cx); if (!fromJSIDVariant(cx, idVar, &id)) return fail(cx, rs); ObjectOpResult success; if (!JS_DeletePropertyById(cx, obj, id, success)) return fail(cx, rs); return ok(rs, success); }
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); }
bool WrapperAnswer::RecvDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth, ReturnStatus *rs, bool *instanceof) { AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) return false; JSContext *cx = jsapi.cx(); *instanceof = false; RootedObject obj(cx, findObjectById(cx, objId)); if (!obj) return fail(cx, rs); LOG("%s.domInstanceOf()", ReceiverObj(objId)); bool tmp; if (!mozilla::dom::InterfaceHasInstance(cx, prototypeID, depth, obj, &tmp)) return fail(cx, rs); *instanceof = tmp; return ok(rs); }
bool WrapperAnswer::RecvHasInstance(const ObjectId &objId, const JSVariant &vVar, ReturnStatus *rs, bool *bp) { 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("%s.hasInstance(%s)", ReceiverObj(objId), InVariant(vVar)); RootedValue val(cx); if (!fromVariant(cx, vVar, &val)) return fail(cx, rs); if (!JS_HasInstance(cx, obj, val, bp)) return fail(cx, rs); return ok(rs); }
already_AddRefed<DOMRequest> nsBrowserElement::ExecuteScript(const nsAString& aScript, const BrowserElementExecuteScriptOptions& aOptions, ErrorResult& aRv) { NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr); RefPtr<DOMRequest> req; nsCOMPtr<nsIXPConnectWrappedJS> wrappedObj = do_QueryInterface(mBrowserElementAPI); MOZ_ASSERT(wrappedObj, "Failed to get wrapped JS from XPCOM component."); MOZ_RELEASE_ASSERT(!js::IsWrapper(wrappedObj->GetJSObject())); AutoJSAPI jsapi; if (!jsapi.Init(wrappedObj->GetJSObject())) { aRv.Throw(NS_ERROR_UNEXPECTED); return nullptr; } JSContext* cx = jsapi.cx(); JS::Rooted<JS::Value> options(cx); aRv.MightThrowJSException(); if (!ToJSValue(cx, aOptions, &options)) { aRv.StealExceptionFromJSContext(cx); return nullptr; } nsresult rv = mBrowserElementAPI->ExecuteScript(aScript, options, getter_AddRefs(req)); if (NS_FAILED(rv)) { if (rv == NS_ERROR_INVALID_ARG) { aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR); } else { aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); } return nullptr; } return req.forget(); }
void Promise::AppendNativeHandler(PromiseNativeHandler* aRunnable) { NS_ASSERT_OWNINGTHREAD(Promise); AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(mGlobal))) { // Our API doesn't allow us to return a useful error. Not like this should // happen anyway. return; } // The self-hosted promise js may keep the object we pass to it alive // for quite a while depending on when GC runs. Therefore, pass a shim // object instead. The shim will free its inner PromiseNativeHandler // after the promise has settled just like our previous c++ promises did. RefPtr<PromiseNativeHandlerShim> shim = new PromiseNativeHandlerShim(aRunnable); JSContext* cx = jsapi.cx(); JS::Rooted<JSObject*> handlerWrapper(cx); // Note: PromiseNativeHandler is NOT wrappercached. So we can't use // ToJSValue here, because it will try to do XPConnect wrapping on it, sadly. if (NS_WARN_IF(!shim->WrapObject(cx, nullptr, &handlerWrapper))) { // Again, no way to report errors. jsapi.ClearException(); return; } JS::Rooted<JSObject*> resolveFunc(cx); resolveFunc = CreateNativeHandlerFunction(cx, handlerWrapper, NativeHandlerTask::Resolve); if (NS_WARN_IF(!resolveFunc)) { jsapi.ClearException(); return; } JS::Rooted<JSObject*> rejectFunc(cx); rejectFunc = CreateNativeHandlerFunction(cx, handlerWrapper, NativeHandlerTask::Reject); if (NS_WARN_IF(!rejectFunc)) { jsapi.ClearException(); return; } JS::Rooted<JSObject*> promiseObj(cx, PromiseObj()); if (NS_WARN_IF(!JS::AddPromiseReactions(cx, promiseObj, resolveFunc, rejectFunc))) { jsapi.ClearException(); return; } }
// This is called on main thread. nsresult ReceiveBlob(already_AddRefed<Blob> aBlob) { RefPtr<Blob> blob = aBlob; ErrorResult rv; uint64_t size = blob->GetSize(rv); if (rv.Failed()) { rv.SuppressException(); } else { AutoJSAPI jsapi; if (jsapi.Init(mGlobal)) { JS_updateMallocCounter(jsapi.cx(), size); } } RefPtr<Blob> newBlob = Blob::Create(mGlobal, blob->Impl()); mFileCallback->Call(*newBlob, rv); mGlobal = nullptr; mFileCallback = nullptr; return rv.StealNSResult(); }
static void GetPropertyBagFromEvent(Event* aEvent, nsIPropertyBag2** aPropertyBag) { *aPropertyBag = nullptr; CustomEvent* customEvent = aEvent->AsCustomEvent(); if (!customEvent) return; AutoJSAPI jsapi; if (!jsapi.Init(customEvent->GetParentObject())) return; JSContext* cx = jsapi.cx(); JS::Rooted<JS::Value> detail(cx); customEvent->GetDetail(cx, &detail); if (!detail.isObject()) return; JS::Rooted<JSObject*> detailObj(cx, &detail.toObject()); nsresult rv; nsCOMPtr<nsIPropertyBag2> propBag; rv = UnwrapArg<nsIPropertyBag2>(cx, detailObj, getter_AddRefs(propBag)); if (NS_FAILED(rv)) return; propBag.forget(aPropertyBag); }
NS_IMETHODIMP MobileConnectionCallback::NotifyGetCallBarringSuccess(uint16_t aProgram, bool aEnabled, uint16_t aServiceClass) { MozCallBarringOptions result; result.mProgram.Construct().SetValue(aProgram); result.mEnabled.Construct().SetValue(aEnabled); result.mServiceClass.Construct().SetValue(aServiceClass); 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); }
bool ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue) { aValue.setUndefined(); AutoJSAPI jsapi; NS_ENSURE_TRUE(jsapi.Init(mAdapter->GetParentObject()), false); JSContext* cx = jsapi.cx(); /** * Create a new discovery handle and wrap it to return. Each * discovery handle is one-time-use only. */ nsRefPtr<BluetoothDiscoveryHandle> discoveryHandle = BluetoothDiscoveryHandle::Create(mAdapter->GetParentObject()); if (!ToJSValue(cx, discoveryHandle, aValue)) { JS_ClearPendingException(cx); return false; } // Set the created discovery handle as the one in use. mAdapter->SetDiscoveryHandleInUse(discoveryHandle); return true; }
NS_IMETHODIMP MobileMessageCallback::NotifySegmentInfoForTextGot(int32_t aSegments, int32_t aCharsPerSegment, int32_t aCharsAvailableInLastSegment) { AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(mDOMRequest->GetOwner()))) { return NotifyError(nsIMobileMessageCallback::INTERNAL_ERROR); } SmsSegmentInfo info; info.mSegments = aSegments; info.mCharsPerSegment = aCharsPerSegment; info.mCharsAvailableInLastSegment = aCharsAvailableInLastSegment; JSContext* cx = jsapi.cx(); JS::Rooted<JS::Value> val(cx); if (!ToJSValue(cx, info, &val)) { JS_ClearPendingException(cx); return NotifyError(nsIMobileMessageCallback::INTERNAL_ERROR); } return NotifySuccess(val, true); }
already_AddRefed<nsISupports> CallbackObjectHolderBase::ToXPCOMCallback(CallbackObject* aCallback, const nsIID& aIID) const { MOZ_ASSERT(NS_IsMainThread()); if (!aCallback) { return nullptr; } // We don't init the AutoJSAPI with our callback because we don't want it // reporting errors to its global's onerror handlers. AutoJSAPI jsapi; jsapi.Init(); JSContext* cx = jsapi.cx(); JS::Rooted<JSObject*> callback(cx, aCallback->CallbackOrNull()); if (!callback) { return nullptr; } JSAutoCompartment ac(cx, callback); RefPtr<nsXPCWrappedJS> wrappedJS; nsresult rv = nsXPCWrappedJS::GetNewOrUsed(callback, aIID, getter_AddRefs(wrappedJS)); if (NS_FAILED(rv) || !wrappedJS) { return nullptr; } nsCOMPtr<nsISupports> retval; rv = wrappedJS->QueryInterface(aIID, getter_AddRefs(retval)); if (NS_FAILED(rv)) { return nullptr; } return retval.forget(); }
void ProfileGatherer::Finish() { MOZ_ASSERT(NS_IsMainThread()); if (!mTicker) { // We somehow got called after we were cancelled! This shouldn't // be possible, but doing a belt-and-suspenders check to be sure. return; } UniquePtr<char[]> buf = mTicker->ToJSON(mSinceTime); nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService(); if (os) { DebugOnly<nsresult> rv = os->RemoveObserver(this, "profiler-subprocess"); NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "RemoveObserver failed"); } AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(mPromise->GlobalJSObject()))) { // We're really hosed if we can't get a JS context for some reason. Reset(); return; } JSContext* cx = jsapi.cx(); // Now parse the JSON so that we resolve with a JS Object. JS::RootedValue val(cx); { NS_ConvertUTF8toUTF16 js_string(nsDependentCString(buf.get())); if (!JS_ParseJSON(cx, static_cast<const char16_t*>(js_string.get()), js_string.Length(), &val)) { if (!jsapi.HasException()) { mPromise->MaybeReject(NS_ERROR_DOM_UNKNOWN_ERR); } else { JS::RootedValue exn(cx); DebugOnly<bool> gotException = jsapi.StealException(&exn); MOZ_ASSERT(gotException); jsapi.ClearException(); mPromise->MaybeReject(cx, exn); } } else { mPromise->MaybeResolve(val); } } Reset(); }
static bool Process(AutoJSAPI& jsapi, const char* filename, bool forceTTY) { FILE* file; if (forceTTY || !filename || strcmp(filename, "-") == 0) { file = stdin; } else { file = fopen(filename, "r"); if (!file) { JS_ReportErrorNumber(jsapi.cx(), my_GetErrorMessage, nullptr, JSSMSG_CANT_OPEN, filename, strerror(errno)); gExitCode = EXITCODE_FILE_NOT_FOUND; return false; } } bool ok = ProcessFile(jsapi, filename, file, forceTTY); if (file != stdin) fclose(file); return ok; }
NS_IMETHODIMP PostMessageEvent::Run() { MOZ_ASSERT(mTargetWindow->IsOuterWindow(), "should have been passed an outer window!"); MOZ_ASSERT(!mSource || mSource->IsOuterWindow(), "should have been passed an outer window!"); AutoJSAPI jsapi; jsapi.Init(); JSContext* cx = jsapi.cx(); // The document is just used for the principal mismatch error message below. // Use a stack variable so mSourceDocument is not held onto after this method // finishes, regardless of the method outcome. nsCOMPtr<nsIDocument> sourceDocument; sourceDocument.swap(mSourceDocument); // If we bailed before this point we're going to leak mMessage, but // that's probably better than crashing. RefPtr<nsGlobalWindow> targetWindow; if (mTargetWindow->IsClosedOrClosing() || !(targetWindow = mTargetWindow->GetCurrentInnerWindowInternal()) || targetWindow->IsClosedOrClosing()) return NS_OK; MOZ_ASSERT(targetWindow->IsInnerWindow(), "we ordered an inner window!"); JSAutoCompartment ac(cx, targetWindow->GetWrapperPreserveColor()); // Ensure that any origin which might have been provided is the origin of this // window's document. Note that we do this *now* instead of when postMessage // is called because the target window might have been navigated to a // different location between then and now. If this check happened when // postMessage was called, it would be fairly easy for a malicious webpage to // intercept messages intended for another site by carefully timing navigation // of the target window so it changed location after postMessage but before // now. if (mProvidedPrincipal) { // Get the target's origin either from its principal or, in the case the // principal doesn't carry a URI (e.g. the system principal), the target's // document. nsIPrincipal* targetPrin = targetWindow->GetPrincipal(); if (NS_WARN_IF(!targetPrin)) return NS_OK; // Note: This is contrary to the spec with respect to file: URLs, which // the spec groups into a single origin, but given we intentionally // don't do that in other places it seems better to hold the line for // now. Long-term, we want HTML5 to address this so that we can // be compliant while being safer. if (!targetPrin->Equals(mProvidedPrincipal)) { nsAutoString providedOrigin, targetOrigin; nsresult rv = nsContentUtils::GetUTFOrigin(targetPrin, targetOrigin); NS_ENSURE_SUCCESS(rv, rv); rv = nsContentUtils::GetUTFOrigin(mProvidedPrincipal, providedOrigin); NS_ENSURE_SUCCESS(rv, rv); const char16_t* params[] = { providedOrigin.get(), targetOrigin.get() }; nsContentUtils::ReportToConsole(nsIScriptError::errorFlag, NS_LITERAL_CSTRING("DOM Window"), sourceDocument, nsContentUtils::eDOM_PROPERTIES, "TargetPrincipalDoesNotMatch", params, ArrayLength(params)); return NS_OK; } } ErrorResult rv; JS::Rooted<JS::Value> messageData(cx); nsCOMPtr<nsPIDOMWindowInner> window = targetWindow->AsInner(); Read(window, cx, &messageData, rv); if (NS_WARN_IF(rv.Failed())) { return rv.StealNSResult(); } // Create the event nsCOMPtr<mozilla::dom::EventTarget> eventTarget = do_QueryObject(targetWindow); RefPtr<MessageEvent> event = new MessageEvent(eventTarget, nullptr, nullptr); Nullable<WindowProxyOrMessagePort> source; source.SetValue().SetAsWindowProxy() = mSource ? mSource->AsOuter() : nullptr; event->InitMessageEvent(nullptr, NS_LITERAL_STRING("message"), false /*non-bubbling */, false /*cancelable */, messageData, mCallerOrigin, EmptyString(), source, nullptr); nsTArray<RefPtr<MessagePort>> ports = TakeTransferredPorts(); event->SetPorts(new MessagePortList(static_cast<dom::Event*>(event.get()), ports)); // We can't simply call dispatchEvent on the window because doing so ends // up flipping the trusted bit on the event, and we don't want that to // happen because then untrusted content can call postMessage on a chrome // window if it can get a reference to it. nsIPresShell *shell = targetWindow->GetExtantDoc()->GetShell(); RefPtr<nsPresContext> presContext; if (shell) presContext = shell->GetPresContext(); event->SetTrusted(mTrustedCaller); WidgetEvent* internalEvent = event->GetInternalNSEvent(); nsEventStatus status = nsEventStatus_eIgnore; EventDispatcher::Dispatch(window, presContext, internalEvent, static_cast<dom::Event*>(event.get()), &status); return NS_OK; }
NS_IMETHODIMP PostMessageEvent::Run() { MOZ_ASSERT(mTargetWindow->IsOuterWindow(), "should have been passed an outer window!"); MOZ_ASSERT(!mSource || mSource->IsOuterWindow(), "should have been passed an outer window!"); AutoJSAPI jsapi; jsapi.Init(); JSContext* cx = jsapi.cx(); // If we bailed before this point we're going to leak mMessage, but // that's probably better than crashing. nsRefPtr<nsGlobalWindow> targetWindow; if (mTargetWindow->IsClosedOrClosing() || !(targetWindow = mTargetWindow->GetCurrentInnerWindowInternal()) || targetWindow->IsClosedOrClosing()) return NS_OK; MOZ_ASSERT(targetWindow->IsInnerWindow(), "we ordered an inner window!"); JSAutoCompartment ac(cx, targetWindow->GetWrapperPreserveColor()); // Ensure that any origin which might have been provided is the origin of this // window's document. Note that we do this *now* instead of when postMessage // is called because the target window might have been navigated to a // different location between then and now. If this check happened when // postMessage was called, it would be fairly easy for a malicious webpage to // intercept messages intended for another site by carefully timing navigation // of the target window so it changed location after postMessage but before // now. if (mProvidedPrincipal) { // Get the target's origin either from its principal or, in the case the // principal doesn't carry a URI (e.g. the system principal), the target's // document. nsIPrincipal* targetPrin = targetWindow->GetPrincipal(); if (NS_WARN_IF(!targetPrin)) return NS_OK; // Note: This is contrary to the spec with respect to file: URLs, which // the spec groups into a single origin, but given we intentionally // don't do that in other places it seems better to hold the line for // now. Long-term, we want HTML5 to address this so that we can // be compliant while being safer. if (!targetPrin->Equals(mProvidedPrincipal)) { return NS_OK; } } ErrorResult rv; JS::Rooted<JS::Value> messageData(cx); nsCOMPtr<nsPIDOMWindow> window = targetWindow.get(); Read(window, cx, &messageData, rv); if (NS_WARN_IF(rv.Failed())) { return rv.StealNSResult(); } // Create the event nsCOMPtr<mozilla::dom::EventTarget> eventTarget = do_QueryInterface(static_cast<nsPIDOMWindow*>(targetWindow.get())); nsRefPtr<MessageEvent> event = new MessageEvent(eventTarget, nullptr, nullptr); event->InitMessageEvent(NS_LITERAL_STRING("message"), false /*non-bubbling */, false /*cancelable */, messageData, mCallerOrigin, EmptyString(), mSource); nsTArray<nsRefPtr<MessagePortBase>> ports; TakeTransferredPorts(ports); event->SetPorts(new MessagePortList(static_cast<dom::Event*>(event.get()), ports)); // We can't simply call dispatchEvent on the window because doing so ends // up flipping the trusted bit on the event, and we don't want that to // happen because then untrusted content can call postMessage on a chrome // window if it can get a reference to it. nsIPresShell *shell = targetWindow->GetExtantDoc()->GetShell(); nsRefPtr<nsPresContext> presContext; if (shell) presContext = shell->GetPresContext(); event->SetTrusted(mTrustedCaller); WidgetEvent* internalEvent = event->GetInternalNSEvent(); nsEventStatus status = nsEventStatus_eIgnore; EventDispatcher::Dispatch(static_cast<nsPIDOMWindow*>(mTargetWindow), presContext, internalEvent, static_cast<dom::Event*>(event.get()), &status); return NS_OK; }