NS_IMETHODIMP MobileMessageManager::Delete(const JS::Value& aParam, nsIDOMDOMRequest** aRequest) { if (aParam.isInt32()) { return Delete(aParam.toInt32(), aRequest); } if (!aParam.isObject()) { return NS_ERROR_INVALID_ARG; } nsresult rv; nsIScriptContext* sc = GetContextForEventHandlers(&rv); AutoPushJSContext cx(sc->GetNativeContext()); NS_ENSURE_STATE(sc); int32_t id; nsCOMPtr<nsIDOMMozSmsMessage> smsMessage = do_QueryInterface(nsContentUtils::XPConnect()->GetNativeOfWrapper(cx, &aParam.toObject())); if (smsMessage) { smsMessage->GetId(&id); } else { nsCOMPtr<nsIDOMMozMmsMessage> mmsMessage = do_QueryInterface(nsContentUtils::XPConnect()->GetNativeOfWrapper(cx, &aParam.toObject())); if (mmsMessage) { mmsMessage->GetId(&id); } else { return NS_ERROR_INVALID_ARG; } } return Delete(id, aRequest); }
NS_IMETHODIMP nsScreen::MozLockOrientation(const JS::Value& aOrientation, JSContext* aCx, bool* aReturn) { if (aOrientation.isObject() && IsArrayLike(aCx, &aOrientation.toObject())) { JSObject* seq = &aOrientation.toObject(); uint32_t length; // JS_GetArrayLength actually works on all objects if (!JS_GetArrayLength(aCx, seq, &length)) { return NS_ERROR_FAILURE; } Sequence<nsString> orientations; if (!orientations.SetCapacity(length)) { return NS_ERROR_OUT_OF_MEMORY; } for (uint32_t i = 0; i < length; ++i) { JS::Value temp; if (!JS_GetElement(aCx, seq, i, &temp)) { return NS_ERROR_FAILURE; } js::RootedString jsString(aCx, JS_ValueToString(aCx, temp)); if (!jsString) { return NS_ERROR_FAILURE; } nsDependentJSString str; if (!str.init(aCx, jsString)) { return NS_ERROR_FAILURE; } *orientations.AppendElement() = str; } ErrorResult rv; *aReturn = MozLockOrientation(orientations, rv); return rv.ErrorCode(); } js::RootedString jsString(aCx, JS_ValueToString(aCx, aOrientation)); if (!jsString) { return NS_ERROR_FAILURE; } nsDependentJSString orientation; if (!orientation.init(aCx, jsString)) { return NS_ERROR_FAILURE; } ErrorResult rv; *aReturn = MozLockOrientation(orientation, rv); return rv.ErrorCode(); }
void nsGeolocationService::HandleMozsettingChanged(const PRUnichar* aData) { // The string that we're interested in will be a JSON string that looks like: // {"key":"gelocation.enabled","value":true} SafeAutoJSContext cx; nsDependentString dataStr(aData); JS::Value val; if (!JS_ParseJSON(cx, dataStr.get(), dataStr.Length(), &val) || !val.isObject()) { return; } JSObject &obj(val.toObject()); JS::Value key; if (!JS_GetProperty(cx, &obj, "key", &key) || !key.isString()) { return; } JSBool match; if (!JS_StringEqualsAscii(cx, key.toString(), GEO_SETINGS_ENABLED, &match) || (match != JS_TRUE)) { return; } JS::Value value; if (!JS_GetProperty(cx, &obj, "value", &value) || !value.isBoolean()) { return; } HandleMozsettingValue(value.toBoolean()); }
NS_IMETHODIMP TCPSocketChild::Send(const JS::Value& aData, uint32_t aByteOffset, uint32_t aByteLength, JSContext* aCx) { if (aData.isString()) { JSString* jsstr = aData.toString(); nsDependentJSString str; bool ok = str.init(aCx, jsstr); NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE); SendData(str); } else { NS_ENSURE_TRUE(aData.isObject(), NS_ERROR_FAILURE); JS::Rooted<JSObject*> obj(aCx, &aData.toObject()); NS_ENSURE_TRUE(JS_IsArrayBufferObject(obj), NS_ERROR_FAILURE); uint32_t buflen = JS_GetArrayBufferByteLength(obj); aByteOffset = std::min(buflen, aByteOffset); uint32_t nbytes = std::min(buflen - aByteOffset, aByteLength); uint8_t* data = JS_GetArrayBufferData(obj); if (!data) { return NS_ERROR_OUT_OF_MEMORY; } FallibleTArray<uint8_t> fallibleArr; if (!fallibleArr.InsertElementsAt(0, data, nbytes)) { return NS_ERROR_OUT_OF_MEMORY; } InfallibleTArray<uint8_t> arr; arr.SwapElements(fallibleArr); SendData(arr); } return NS_OK; }
NS_IMETHODIMP TCPSocketParent::InitJS(const JS::Value& aIntermediary, JSContext* aCx) { MOZ_ASSERT(aIntermediary.isObject()); mIntermediaryObj = &aIntermediary.toObject(); return NS_OK; }
// Helper for weighted regions. nsresult CameraControlImpl::Set(JSContext* aCx, uint32_t aKey, const JS::Value& aValue, uint32_t aLimit) { if (aLimit == 0) { DOM_CAMERA_LOGI("%s:%d : aLimit = 0, nothing to do\n", __func__, __LINE__); return NS_OK; } if (!aValue.isObject()) { return NS_ERROR_INVALID_ARG; } uint32_t length = 0; JSObject* regions = &aValue.toObject(); if (!JS_GetArrayLength(aCx, regions, &length)) { return NS_ERROR_FAILURE; } DOM_CAMERA_LOGI("%s:%d : got %d regions (limited to %d)\n", __func__, __LINE__, length, aLimit); if (length > aLimit) { length = aLimit; } nsTArray<CameraRegion> regionArray; regionArray.SetCapacity(length); for (uint32_t i = 0; i < length; ++i) { JS::Value v; if (!JS_GetElement(aCx, regions, i, &v)) { return NS_ERROR_FAILURE; } CameraRegion* r = regionArray.AppendElement(); /** * These are the default values. We can remove these when the xpidl * dictionary parser gains the ability to grok default values. */ r->top = -1000; r->left = -1000; r->bottom = 1000; r->right = 1000; r->weight = 1000; nsresult rv = r->Init(aCx, &v); NS_ENSURE_SUCCESS(rv, rv); DOM_CAMERA_LOGI("region %d: top=%d, left=%d, bottom=%d, right=%d, weight=%d\n", i, r->top, r->left, r->bottom, r->right, r->weight ); } SetParameter(aKey, regionArray); return NS_OK; }
JSScript *createScriptViaXDR(JSPrincipals *prin, JSPrincipals *orig, int testCase) { const char src[] = "function f() { return 1; }\n" "f;\n"; js::RootedObject global(cx, JS_GetGlobalObject(cx)); JSScript *script = CompileScriptForPrincipalsVersionOrigin(cx, global, prin, orig, src, strlen(src), "test", 1, JSVERSION_DEFAULT); if (!script) return NULL; if (testCase == TEST_SCRIPT || testCase == TEST_SERIALIZED_FUNCTION) { script = FreezeThaw(cx, script); if (!script) return NULL; if (testCase == TEST_SCRIPT) return script; } JS::Value v; JSBool ok = JS_ExecuteScript(cx, global, script, &v); if (!ok || !v.isObject()) return NULL; js::RootedObject funobj(cx, &v.toObject()); if (testCase == TEST_FUNCTION) { funobj = FreezeThaw(cx, funobj); if (!funobj) return NULL; } return GetScript(cx, funobj); }
// static JSObject* DOMProxyHandler::GetAndClearExpandoObject(JSObject* obj) { MOZ_ASSERT(IsDOMProxy(obj), "expected a DOM proxy object"); JS::Value v = js::GetProxyExtra(obj, JSPROXYSLOT_EXPANDO); if (v.isUndefined()) { return nullptr; } if (v.isObject()) { js::SetProxyExtra(obj, JSPROXYSLOT_EXPANDO, UndefinedValue()); xpc::GetObjectScope(obj)->RemoveDOMExpandoObject(obj); } else { js::ExpandoAndGeneration* expandoAndGeneration = static_cast<js::ExpandoAndGeneration*>(v.toPrivate()); v = expandoAndGeneration->expando; if (v.isUndefined()) { return nullptr; } expandoAndGeneration->expando = UndefinedValue(); } return &v.toObject(); }
nsresult xpcJSWeakReference::Init(JSContext* cx, const JS::Value& object) { if (!object.isObject()) return NS_OK; JS::RootedObject obj(cx, &object.toObject()); XPCCallContext ccx(NATIVE_CALLER, cx); // See if the object is a wrapped native that supports weak references. nsISupports* supports = nsXPConnect::XPConnect()->GetNativeOfWrapper(cx, obj); nsCOMPtr<nsISupportsWeakReference> supportsWeakRef = do_QueryInterface(supports); if (supportsWeakRef) { supportsWeakRef->GetWeakReference(getter_AddRefs(mReferent)); if (mReferent) { return NS_OK; } } // If it's not a wrapped native, or it is a wrapped native that does not // support weak references, fall back to getting a weak ref to the object. // See if object is a wrapped JSObject. nsRefPtr<nsXPCWrappedJS> wrapped; nsresult rv = nsXPCWrappedJS::GetNewOrUsed(obj, NS_GET_IID(nsISupports), getter_AddRefs(wrapped)); if (!wrapped) { NS_ERROR("can't get nsISupportsWeakReference wrapper for obj"); return rv; } return wrapped->GetWeakReference(getter_AddRefs(mReferent)); }
Promise* WrapperPromiseCallback::GetDependentPromise() { // Per spec, various algorithms like all() and race() are actually implemented // in terms of calling then() but passing it the resolve/reject functions that // are passed as arguments to function passed to the Promise constructor. // That will cause the promise in question to hold on to a // WrapperPromiseCallback, but the dependent promise should really be the one // whose constructor those functions came from, not the about-to-be-ignored // return value of "then". So try to determine whether we're in that case and // if so go ahead and dig the dependent promise out of the function we have. JSObject* callable = mCallback->Callable(); // Unwrap it, in case it's a cross-compartment wrapper. Our caller here is // system, so it's really ok to just go and unwrap. callable = js::UncheckedUnwrap(callable); if (JS_IsNativeFunction(callable, Promise::JSCallback)) { JS::Value promiseVal = js::GetFunctionNativeReserved(callable, Promise::SLOT_PROMISE); Promise* promise; UNWRAP_OBJECT(Promise, &promiseVal.toObject(), promise); return promise; } if (mNextPromise) { return mNextPromise; } Promise* promise; if (NS_SUCCEEDED(UNWRAP_OBJECT(Promise, mNextPromiseObj, promise))) { return promise; } // Oh, well. return nullptr; }
NS_IMETHODIMP SmsManager::Send(const JS::Value& aNumber, const nsAString& aMessage, JS::Value* aReturn) { nsresult rv; nsIScriptContext* sc = GetContextForEventHandlers(&rv); NS_ENSURE_STATE(sc); AutoPushJSContext cx(sc->GetNativeContext()); NS_ASSERTION(cx, "Failed to get a context!"); if (!aNumber.isString() && !(aNumber.isObject() && JS_IsArrayObject(cx, &aNumber.toObject()))) { return NS_ERROR_INVALID_ARG; } JSObject* global = sc->GetNativeGlobal(); NS_ASSERTION(global, "Failed to get global object!"); JSAutoRequest ar(cx); JSAutoCompartment ac(cx, global); if (aNumber.isString()) { return Send(cx, global, aNumber.toString(), aMessage, aReturn); } // Must be an array then. JSObject& numbers = aNumber.toObject(); uint32_t size; JS_ALWAYS_TRUE(JS_GetArrayLength(cx, &numbers, &size)); JS::Value* requests = new JS::Value[size]; for (uint32_t i=0; i<size; ++i) { JS::Value number; if (!JS_GetElement(cx, &numbers, i, &number)) { return NS_ERROR_INVALID_ARG; } nsresult rv = Send(cx, global, number.toString(), aMessage, &requests[i]); NS_ENSURE_SUCCESS(rv, rv); } aReturn->setObjectOrNull(JS_NewArrayObject(cx, size, requests)); NS_ENSURE_TRUE(aReturn->isObject(), NS_ERROR_FAILURE); return NS_OK; }
NS_IMETHODIMP TimeZoneSettingObserver::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData) { if (strcmp(aTopic, MOZSETTINGS_CHANGED) != 0) { return NS_OK; } // Note that this function gets called for any and all settings changes, // so we need to carefully check if we have the one we're interested in. // // The string that we're interested in will be a JSON string that looks like: // {"key":"time.timezone","value":"America/Chicago"} // Get the safe JS context. nsCOMPtr<nsIThreadJSContextStack> stack = do_GetService("@mozilla.org/js/xpc/ContextStack;1"); if (!stack) { ERR("Failed to get JSContextStack"); return NS_OK; } JSContext *cx = stack->GetSafeJSContext(); if (!cx) { ERR("Failed to GetSafeJSContext"); return NS_OK; } // Parse the JSON value. nsDependentString dataStr(aData); JS::Value val; if (!JS_ParseJSON(cx, dataStr.get(), dataStr.Length(), &val) || !val.isObject()) { return NS_OK; } // Get the key, which should be the JS string "time.timezone". JSObject &obj(val.toObject()); JS::Value key; if (!JS_GetProperty(cx, &obj, "key", &key) || !key.isString()) { return NS_OK; } JSBool match; if (!JS_StringEqualsAscii(cx, key.toString(), TIME_TIMEZONE, &match) || match != JS_TRUE) { return NS_OK; } // Get the value, which should be a JS string like "America/Chicago". JS::Value value; if (!JS_GetProperty(cx, &obj, "value", &value) || !value.isString()) { return NS_OK; } // Set the system timezone. return SetTimeZone(value, cx); }
bool ValueHasISupportsPrivate(const JS::Value &v) { if (!v.isObject()) { return false; } const DOMClass* domClass = GetDOMClass(&v.toObject()); if (domClass) { return domClass->mDOMObjectIsISupports; } JSClass* clasp = ::JS_GetClass(&v.toObject()); const uint32_t HAS_PRIVATE_NSISUPPORTS = JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS; return (clasp->flags & HAS_PRIVATE_NSISUPPORTS) == HAS_PRIVATE_NSISUPPORTS; }
nsresult nsJSON::EncodeInternal(JSContext* cx, const JS::Value& aValue, nsJSONWriter* writer) { JSAutoRequest ar(cx); // Backward compatibility: // nsIJSON does not allow to serialize anything other than objects if (!aValue.isObject()) { return NS_ERROR_INVALID_ARG; } JSObject* obj = &aValue.toObject(); JS::Value val = aValue; /* Backward compatibility: * Manually call toJSON if implemented by the object and check that * the result is still an object * Note: It is perfectly fine to not implement toJSON, so it is * perfectly fine for GetMethod to fail */ JS::Value toJSON; if (JS_GetMethod(cx, obj, "toJSON", NULL, &toJSON) && !JSVAL_IS_PRIMITIVE(toJSON) && JS_ObjectIsCallable(cx, JSVAL_TO_OBJECT(toJSON))) { // If toJSON is implemented, it must not throw if (!JS_CallFunctionValue(cx, obj, toJSON, 0, NULL, &val)) { if (JS_IsExceptionPending(cx)) // passing NS_OK will throw the pending exception return NS_OK; // No exception, but still failed return NS_ERROR_FAILURE; } // Backward compatibility: // nsIJSON does not allow to serialize anything other than objects if (JSVAL_IS_PRIMITIVE(val)) return NS_ERROR_INVALID_ARG; } // GetMethod may have thrown else if (JS_IsExceptionPending(cx)) // passing NS_OK will throw the pending exception return NS_OK; // Backward compatibility: // function shall not pass, just "plain" objects and arrays JSType type = JS_TypeOfValue(cx, val); if (type == JSTYPE_FUNCTION) return NS_ERROR_INVALID_ARG; // We're good now; try to stringify if (!JS_Stringify(cx, &val, NULL, JSVAL_NULL, WriteCallback, writer)) return NS_ERROR_FAILURE; return NS_OK; }
//static JSObject * DOMProxyHandler::GetExpandoObject(JSObject *obj) { MOZ_ASSERT(IsDOMProxy(obj), "expected a DOM proxy object"); JS::Value v = js::GetProxyExtra(obj, JSPROXYSLOT_EXPANDO); if (v.isObject()) { return &v.toObject(); } if (v.isUndefined()) { return nullptr; } js::ExpandoAndGeneration* expandoAndGeneration = static_cast<js::ExpandoAndGeneration*>(v.toPrivate()); v = expandoAndGeneration->expando; return v.isUndefined() ? nullptr : &v.toObject(); }
NS_IMETHODIMP nsHTMLAudioElement::MozWriteAudio(const JS::Value& aData, JSContext* aCx, uint32_t* aRetVal) { if (!mAudioStream) { return NS_ERROR_DOM_INVALID_STATE_ERR; } if (!aData.isObject()) { return NS_ERROR_DOM_TYPE_MISMATCH_ERR; } JSObject* darray = &aData.toObject(); JS::AutoObjectRooter tvr(aCx); JSObject* tsrc = NULL; // Allow either Float32Array or plain JS Array if (JS_IsFloat32Array(darray)) { tsrc = darray; } else if (JS_IsArrayObject(aCx, darray)) { JSObject* nobj = JS_NewFloat32ArrayFromArray(aCx, darray); if (!nobj) { return NS_ERROR_DOM_TYPE_MISMATCH_ERR; } tsrc = nobj; } else { return NS_ERROR_DOM_TYPE_MISMATCH_ERR; } tvr.setObject(tsrc); uint32_t dataLength = JS_GetTypedArrayLength(tsrc); // Make sure that we are going to write the correct amount of data based // on number of channels. if (dataLength % mChannels != 0) { return NS_ERROR_DOM_INDEX_SIZE_ERR; } // Don't write more than can be written without blocking. uint32_t writeLen = std::min(mAudioStream->Available(), dataLength / mChannels); float* frames = JS_GetFloat32ArrayData(tsrc); // Convert the samples back to integers as we are using fixed point audio in // the AudioStream. // This could be optimized to avoid allocation and memcpy when // AudioDataValue is 'float', but it's not worth it for this deprecated API. nsAutoArrayPtr<AudioDataValue> audioData(new AudioDataValue[writeLen * mChannels]); ConvertAudioSamples(frames, audioData.get(), writeLen * mChannels); nsresult rv = mAudioStream->Write(audioData.get(), writeLen); if (NS_FAILED(rv)) { return rv; } // Return the actual amount written. *aRetVal = writeLen * mChannels; return rv; }
// JS-to-native helpers // Setter for weighted regions: { top, bottom, left, right, weight } nsresult nsDOMCameraControl::Set(JSContext* aCx, uint32_t aKey, const JS::Value& aValue, uint32_t aLimit) { if (aLimit == 0) { DOM_CAMERA_LOGI("%s:%d : aLimit = 0, nothing to do\n", __func__, __LINE__); return NS_OK; } if (!aValue.isObject()) { return NS_ERROR_INVALID_ARG; } uint32_t length = 0; JS::Rooted<JSObject*> regions(aCx, &aValue.toObject()); if (!JS_GetArrayLength(aCx, regions, &length)) { return NS_ERROR_FAILURE; } DOM_CAMERA_LOGI("%s:%d : got %d regions (limited to %d)\n", __func__, __LINE__, length, aLimit); if (length > aLimit) { length = aLimit; } nsTArray<ICameraControl::Region> regionArray; regionArray.SetCapacity(length); for (uint32_t i = 0; i < length; ++i) { JS::Rooted<JS::Value> v(aCx); if (!JS_GetElement(aCx, regions, i, &v)) { return NS_ERROR_FAILURE; } CameraRegion region; if (!region.Init(aCx, v)) { return NS_ERROR_FAILURE; } ICameraControl::Region* r = regionArray.AppendElement(); r->top = region.mTop; r->left = region.mLeft; r->bottom = region.mBottom; r->right = region.mRight; r->weight = region.mWeight; DOM_CAMERA_LOGI("region %d: top=%d, left=%d, bottom=%d, right=%d, weight=%u\n", i, r->top, r->left, r->bottom, r->right, r->weight ); } return mCameraControl->Set(aKey, regionArray); }
nsresult MobileMessageManager::GetMessageId(AutoPushJSContext &aCx, const JS::Value &aMessage, int32_t &aId) { nsCOMPtr<nsIDOMMozSmsMessage> smsMessage = do_QueryInterface(nsContentUtils::XPConnect()->GetNativeOfWrapper(aCx, &aMessage.toObject())); if (smsMessage) { return smsMessage->GetId(&aId); } nsCOMPtr<nsIDOMMozMmsMessage> mmsMessage = do_QueryInterface(nsContentUtils::XPConnect()->GetNativeOfWrapper(aCx, &aMessage.toObject())); if (mmsMessage) { return mmsMessage->GetId(&aId); } return NS_ERROR_INVALID_ARG; }
std::string gjs_debug_value(JS::Value v) { std::ostringstream out; if (v.isNull()) return "null"; if (v.isUndefined()) return "undefined"; if (v.isInt32()) { out << v.toInt32(); return out.str(); } if (v.isDouble()) { out << v.toDouble(); return out.str(); } if (v.isString()) { out << gjs_debug_string(v.toString()); return out.str(); } if (v.isSymbol()) { out << gjs_debug_symbol(v.toSymbol()); return out.str(); } if (v.isObject() && js::IsFunctionObject(&v.toObject())) { JSFunction* fun = JS_GetObjectFunction(&v.toObject()); JSString *display_name = JS_GetFunctionDisplayId(fun); if (display_name) out << "<function " << gjs_debug_string(display_name); else out << "<unnamed function"; out << " at " << fun << '>'; return out.str(); } if (v.isObject()) { out << gjs_debug_object(&v.toObject()); return out.str(); } if (v.isBoolean()) return (v.toBoolean() ? "true" : "false"); if (v.isMagic()) return "<magic>"; return "unexpected value"; }
nsresult nsXBLProtoImpl::InitTargetObjects(nsXBLPrototypeBinding* aBinding, nsIScriptContext* aContext, nsIContent* aBoundElement, nsIXPConnectJSObjectHolder** aScriptObjectHolder, JS::MutableHandle<JSObject*> aTargetClassObject, bool* aTargetIsNew) { nsresult rv = NS_OK; *aScriptObjectHolder = nullptr; if (!mClassObject) { rv = CompilePrototypeMembers(aBinding); // This is the first time we've ever installed this binding on an element. // We need to go ahead and compile all methods and properties on a class // in our prototype binding. if (NS_FAILED(rv)) return rv; MOZ_ASSERT(mClassObject); } nsIDocument *ownerDoc = aBoundElement->OwnerDoc(); nsIGlobalObject *sgo; if (!(sgo = ownerDoc->GetScopeObject())) { return NS_ERROR_UNEXPECTED; } // Because our prototype implementation has a class, we need to build up a corresponding // class for the concrete implementation in the bound document. AutoPushJSContext cx(aContext->GetNativeContext()); JS::Rooted<JSObject*> global(cx, sgo->GetGlobalJSObject()); nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper; JS::Value v; rv = nsContentUtils::WrapNative(cx, global, aBoundElement, &v, getter_AddRefs(wrapper)); NS_ENSURE_SUCCESS(rv, rv); JS::Rooted<JSObject*> value(cx, &v.toObject()); // All of the above code was just obtaining the bound element's script object and its immediate // concrete base class. We need to alter the object so that our concrete class is interposed // between the object and its base class. We become the new base class of the object, and the // object's old base class becomes the new class' base class. rv = aBinding->InitClass(mClassName, cx, global, value, aTargetClassObject, aTargetIsNew); if (NS_FAILED(rv)) { return rv; } nsContentUtils::PreserveWrapper(aBoundElement, aBoundElement); wrapper.swap(*aScriptObjectHolder); return rv; }
// static JSObject* DOMProxyHandler::GetExpandoObject(JSObject* obj) { CheckDOMProxy(obj); JS::Value v = js::GetProxyPrivate(obj); if (v.isObject()) { CheckExpandoObject(obj, v); return &v.toObject(); } if (v.isUndefined()) { return nullptr; } js::ExpandoAndGeneration* expandoAndGeneration = static_cast<js::ExpandoAndGeneration*>(v.toPrivate()); CheckExpandoAndGeneration(obj, expandoAndGeneration); v = expandoAndGeneration->expando; return v.isUndefined() ? nullptr : &v.toObject(); }
nsresult nsJSON::EncodeInternal(JSContext* cx, const JS::Value& aValue, nsJSONWriter* writer) { // Backward compatibility: // nsIJSON does not allow to serialize anything other than objects if (!aValue.isObject()) { return NS_ERROR_INVALID_ARG; } JS::Rooted<JSObject*> obj(cx, &aValue.toObject()); /* Backward compatibility: * Manually call toJSON if implemented by the object and check that * the result is still an object * Note: It is perfectly fine to not implement toJSON, so it is * perfectly fine for GetMethod to fail */ JS::Rooted<JS::Value> val(cx, aValue); JS::Rooted<JS::Value> toJSON(cx); if (JS_GetProperty(cx, obj, "toJSON", &toJSON) && toJSON.isObject() && JS_ObjectIsCallable(cx, &toJSON.toObject())) { // If toJSON is implemented, it must not throw if (!JS_CallFunctionValue(cx, obj, toJSON, JS::HandleValueArray::empty(), &val)) { if (JS_IsExceptionPending(cx)) // passing NS_OK will throw the pending exception return NS_OK; // No exception, but still failed return NS_ERROR_FAILURE; } // Backward compatibility: // nsIJSON does not allow to serialize anything other than objects if (val.isPrimitive()) return NS_ERROR_INVALID_ARG; } // GetMethod may have thrown else if (JS_IsExceptionPending(cx)) // passing NS_OK will throw the pending exception return NS_OK; // Backward compatibility: // function shall not pass, just "plain" objects and arrays JSType type = JS_TypeOfValue(cx, val); if (type == JSTYPE_FUNCTION) return NS_ERROR_INVALID_ARG; // We're good now; try to stringify if (!JS_Stringify(cx, &val, JS::NullPtr(), JS::NullHandleValue, WriteCallback, writer)) return NS_ERROR_FAILURE; return NS_OK; }
/** * Constraints look like this: * * { * "mandatory": {"foo":"hello", "bar": false, "baz": 10}, * "optional": [{"hello":"foo"}, {"baz": false}] * } * * Optional constraints are ordered, and hence in an array. This function * converts a jsval that looks like the above into a MediaConstraints object. */ nsresult PeerConnectionImpl::ConvertConstraints( const JS::Value& aConstraints, MediaConstraints* aObj, JSContext* aCx) { size_t i; jsval mandatory, optional; JSObject& constraints = aConstraints.toObject(); // Mandatory constraints. if (JS_GetProperty(aCx, &constraints, "mandatory", &mandatory)) { if (mandatory.isObject()) { JSObject* opts = JSVAL_TO_OBJECT(mandatory); JS::AutoIdArray mandatoryOpts(aCx, JS_Enumerate(aCx, opts)); // Iterate over each property. for (i = 0; i < mandatoryOpts.length(); i++) { jsval option, optionName; if (JS_GetPropertyById(aCx, opts, mandatoryOpts[i], &option)) { if (JS_IdToValue(aCx, mandatoryOpts[i], &optionName)) { // We only support boolean constraints for now. if (JSVAL_IS_BOOLEAN(option)) { JSString* optionNameString = JS_ValueToString(aCx, optionName); NS_ConvertUTF16toUTF8 stringVal(JS_GetStringCharsZ(aCx, optionNameString)); aObj->setBooleanConstraint(stringVal.get(), JSVAL_TO_BOOLEAN(option), true); } } } } } } // Optional constraints. if (JS_GetProperty(aCx, &constraints, "optional", &optional)) { if (optional.isObject()) { JSObject* opts = JSVAL_TO_OBJECT(optional); if (JS_IsArrayObject(aCx, opts)) { uint32_t length; if (!JS_GetArrayLength(aCx, opts, &length)) { return NS_ERROR_FAILURE; } for (i = 0; i < length; i++) { jsval val; JS_GetElement(aCx, opts, i, &val); if (val.isObject()) { // Extract name & value and store. // FIXME: MediaConstraints does not support optional constraints? } } } } } return NS_OK; }
Promise* GetPromise(JSContext* aCx, JS::Handle<JSObject*> aFunc) { JS::Value promiseVal = js::GetFunctionNativeReserved(aFunc, SLOT_PROMISE); MOZ_ASSERT(promiseVal.isObject()); Promise* promise; UNWRAP_OBJECT(Promise, &promiseVal.toObject(), promise); return promise; }
NS_IMETHODIMP AutoMounterSetting::Observe(nsISupports* aSubject, const char* aTopic, const PRUnichar* aData) { if (strcmp(aTopic, MOZSETTINGS_CHANGED) != 0) { return NS_OK; } // Note that this function gets called for any and all settings changes, // so we need to carefully check if we have the one we're interested in. // // The string that we're interested in will be a JSON string that looks like: // {"key":"ums.autoMount","value":true} nsCOMPtr<nsIThreadJSContextStack> stack = do_GetService("@mozilla.org/js/xpc/ContextStack;1"); if (!stack) { ERR("Failed to get JSContextStack"); return NS_OK; } JSContext* cx = stack->GetSafeJSContext(); if (!cx) { ERR("Failed to GetSafeJSContext"); return NS_OK; } nsDependentString dataStr(aData); JS::Value val; if (!JS_ParseJSON(cx, dataStr.get(), dataStr.Length(), &val) || !val.isObject()) { return NS_OK; } JSObject& obj(val.toObject()); JS::Value key; if (!JS_GetProperty(cx, &obj, "key", &key) || !key.isString()) { return NS_OK; } JSBool match; if (!JS_StringEqualsAscii(cx, key.toString(), UMS_MODE, &match) || (match != JS_TRUE)) { return NS_OK; } JS::Value value; if (!JS_GetProperty(cx, &obj, "value", &value) || !value.isInt32()) { return NS_OK; } int32_t mode = value.toInt32(); SetAutoMounterMode(mode); return NS_OK; }
JSObject* XPCWrappedNativeScope::EnsureXBLScope(JSContext *cx) { JSObject *global = GetGlobalJSObject(); MOZ_ASSERT(js::IsObjectInContextCompartment(global, cx)); MOZ_ASSERT(!mIsXBLScope); MOZ_ASSERT(strcmp(js::GetObjectClass(global)->name, "nsXBLPrototypeScript compilation scope")); // If we already have a special XBL scope object, we know what to use. if (mXBLScope) return mXBLScope; // If this scope doesn't need an XBL scope, just return the global. if (!mUseXBLScope) return global; // Set up the sandbox options. Note that we use the DOM global as the // sandboxPrototype so that the XBL scope can access all the DOM objects // it's accustomed to accessing. // // NB: One would think that wantXrays wouldn't make a difference here. // However, wantXrays lives a secret double life, and one of its other // hobbies is to waive Xray on the returned sandbox when set to false. // So make sure to keep this set to true, here. SandboxOptions options; options.wantXrays = true; options.wantComponents = true; options.wantXHRConstructor = false; options.proto = global; options.sameZoneAs = global; // Use an nsExpandedPrincipal to create asymmetric security. nsIPrincipal *principal = GetPrincipal(); nsCOMPtr<nsIExpandedPrincipal> ep; MOZ_ASSERT(!(ep = do_QueryInterface(principal))); nsTArray< nsCOMPtr<nsIPrincipal> > principalAsArray(1); principalAsArray.AppendElement(principal); ep = new nsExpandedPrincipal(principalAsArray); // Create the sandbox. JSAutoRequest ar(cx); JS::Value v = JS::UndefinedValue(); nsresult rv = xpc_CreateSandboxObject(cx, &v, ep, options); NS_ENSURE_SUCCESS(rv, nullptr); mXBLScope = &v.toObject(); // Tag it. EnsureCompartmentPrivate(js::UnwrapObject(mXBLScope))->scope->mIsXBLScope = true; // Good to go! return mXBLScope; }
NS_IMETHODIMP TCPSocketChild::SetSocketAndWindow(nsITCPSocketInternal *aSocket, const JS::Value& aWindowObj, JSContext* aCx) { mSocket = aSocket; MOZ_ASSERT(aWindowObj.isObject()); mWindowObj = js::CheckedUnwrap(&aWindowObj.toObject()); if (!mWindowObj) { return NS_ERROR_FAILURE; } return NS_OK; }
nsresult DOMEventTargetHelper::SetEventHandler(nsIAtom* aType, JSContext* aCx, const JS::Value& aValue) { RefPtr<EventHandlerNonNull> handler; JS::Rooted<JSObject*> callable(aCx); if (aValue.isObject() && JS::IsCallable(callable = &aValue.toObject())) { handler = new EventHandlerNonNull(aCx, callable, dom::GetIncumbentGlobal()); } SetEventHandler(aType, EmptyString(), handler); return NS_OK; }
void nsGeolocationSettings::HandleGeolocationAlwaysPreciseChange(const JS::Value& aVal) { if (!aVal.isObject()) { return; } // clear the list of apps that are always precise mAlwaysPreciseApps.Clear(); // root the object and get the global JS::Rooted<JSObject*> obj(nsContentUtils::RootingCx(), &aVal.toObject()); MOZ_ASSERT(obj); nsIGlobalObject* global = xpc::NativeGlobal(obj); NS_ENSURE_TRUE_VOID(global && global->GetGlobalJSObject()); // the spec requires calling getters when accessing array by index AutoEntryScript aes(global, "geolocation.always_precise indexing"); aes.TakeOwnershipOfErrorReporting(); JSContext *cx = aes.cx(); if (!JS_IsArrayObject(cx, obj)) { return; } uint32_t length; if (!JS_GetArrayLength(cx, obj, &length)) { return; } // process the list of apps... for (uint32_t i = 0; i < length; ++i) { JS::RootedValue value(cx); if (!JS_GetElement(cx, obj, i, &value) || !value.isString()) { continue; } nsAutoJSString origin; if (!origin.init(cx, value)) { continue; } GPSLOG("adding always precise for %s", NS_ConvertUTF16toUTF8(origin).get()); // add the origin to the list of apps that will always receive // precise location information mAlwaysPreciseApps.AppendElement(origin); } }
NS_IMETHODIMP nsHTMLAudioElement::MozWriteAudio(const JS::Value& aData, JSContext* aCx, PRUint32* aRetVal) { if (!mAudioStream) { return NS_ERROR_DOM_INVALID_STATE_ERR; } if (!aData.isObject()) { return NS_ERROR_DOM_TYPE_MISMATCH_ERR; } JSObject* darray = &aData.toObject(); JS::AutoObjectRooter tvr(aCx); JSObject* tsrc = NULL; // Allow either Float32Array or plain JS Array if (JS_IsFloat32Array(darray, aCx)) { tsrc = darray; } else if (JS_IsArrayObject(aCx, darray)) { JSObject* nobj = JS_NewFloat32ArrayFromArray(aCx, darray); if (!nobj) { return NS_ERROR_DOM_TYPE_MISMATCH_ERR; } tsrc = nobj; } else { return NS_ERROR_DOM_TYPE_MISMATCH_ERR; } tvr.setObject(tsrc); PRUint32 dataLength = JS_GetTypedArrayLength(tsrc, aCx); // Make sure that we are going to write the correct amount of data based // on number of channels. if (dataLength % mChannels != 0) { return NS_ERROR_DOM_INDEX_SIZE_ERR; } // Don't write more than can be written without blocking. PRUint32 writeLen = NS_MIN(mAudioStream->Available(), dataLength / mChannels); nsresult rv = mAudioStream->Write(JS_GetFloat32ArrayData(tsrc, aCx), writeLen); if (NS_FAILED(rv)) { return rv; } // Return the actual amount written. *aRetVal = writeLen * mChannels; return rv; }