NS_IMETHODIMP TCPSocketParent::SendCallback(const nsAString& aType, const JS::Value& aDataVal, const nsAString& aReadyState, uint32_t aBuffered, JSContext* aCx) { if (!mIPCOpen) { NS_WARNING("Dropping callback due to no IPC connection"); return NS_OK; } CallbackData data; if (aDataVal.isString()) { JSString* jsstr = aDataVal.toString(); nsDependentJSString str; if (!str.init(aCx, jsstr)) { FireInteralError(this, __LINE__); return NS_ERROR_OUT_OF_MEMORY; } data = str; } else if (aDataVal.isUndefined() || aDataVal.isNull()) { data = mozilla::void_t(); } else if (aDataVal.isObject()) { JSObject* obj = &aDataVal.toObject(); if (JS_IsArrayBufferObject(obj)) { uint32_t nbytes = JS_GetArrayBufferByteLength(obj); uint8_t* buffer = JS_GetArrayBufferData(obj); if (!buffer) { FireInteralError(this, __LINE__); return NS_ERROR_OUT_OF_MEMORY; } FallibleTArray<uint8_t> fallibleArr; if (!fallibleArr.InsertElementsAt(0, buffer, nbytes)) { FireInteralError(this, __LINE__); return NS_ERROR_OUT_OF_MEMORY; } InfallibleTArray<uint8_t> arr; arr.SwapElements(fallibleArr); data = SendableData(arr); } else { nsDependentJSString message, filename; uint32_t lineNumber = 0; uint32_t columnNumber = 0; JS::Value val; if (!JS_GetProperty(aCx, obj, "message", &val)) { NS_ERROR("No message property on supposed error object"); } else if (JSVAL_IS_STRING(val)) { if (!message.init(aCx, JSVAL_TO_STRING(val))) { NS_WARNING("couldn't initialize string"); } } if (!JS_GetProperty(aCx, obj, "fileName", &val)) { NS_ERROR("No fileName property on supposed error object"); } else if (JSVAL_IS_STRING(val)) { if (!filename.init(aCx, JSVAL_TO_STRING(val))) { NS_WARNING("couldn't initialize string"); } } if (!JS_GetProperty(aCx, obj, "lineNumber", &val)) { NS_ERROR("No lineNumber property on supposed error object"); } else if (JSVAL_IS_INT(val)) { lineNumber = JSVAL_TO_INT(val); } if (!JS_GetProperty(aCx, obj, "columnNumber", &val)) { NS_ERROR("No columnNumber property on supposed error object"); } else if (JSVAL_IS_INT(val)) { columnNumber = JSVAL_TO_INT(val); } data = JSError(message, filename, lineNumber, columnNumber); } } else { NS_ERROR("Unexpected JS value encountered"); FireInteralError(this, __LINE__); return NS_ERROR_FAILURE; } mozilla::unused << PTCPSocketParent::SendCallback(nsString(aType), data, nsString(aReadyState), aBuffered); return NS_OK; }
nsresult nsDOMMultipartFile::InitBlob(JSContext* aCx, uint32_t aArgc, JS::Value* aArgv, UnwrapFuncPtr aUnwrapFunc) { bool nativeEOL = false; if (aArgc > 1) { if (NS_IsMainThread()) { BlobPropertyBag d; if (!d.Init(aCx, JS::NullPtr(), aArgv[1])) { return NS_ERROR_TYPE_ERR; } mContentType = d.mType; nativeEOL = d.mEndings == EndingTypesValues::Native; } else { BlobPropertyBagWorkers d; if (!d.Init(aCx, JS::NullPtr(), aArgv[1])) { return NS_ERROR_TYPE_ERR; } mContentType = d.mType; nativeEOL = d.mEndings == EndingTypesValues::Native; } } if (aArgc > 0) { if (!aArgv[0].isObject()) { return NS_ERROR_TYPE_ERR; // We're not interested } JSObject& obj = aArgv[0].toObject(); if (!JS_IsArrayObject(aCx, &obj)) { return NS_ERROR_TYPE_ERR; // We're not interested } BlobSet blobSet; uint32_t length; JS_ALWAYS_TRUE(JS_GetArrayLength(aCx, &obj, &length)); for (uint32_t i = 0; i < length; ++i) { JS::Value element; if (!JS_GetElement(aCx, &obj, i, &element)) return NS_ERROR_TYPE_ERR; if (element.isObject()) { JSObject& obj = element.toObject(); nsCOMPtr<nsIDOMBlob> blob = aUnwrapFunc(aCx, &obj); if (blob) { // Flatten so that multipart blobs will never nest nsDOMFileBase* file = static_cast<nsDOMFileBase*>( static_cast<nsIDOMBlob*>(blob)); const nsTArray<nsCOMPtr<nsIDOMBlob> >* subBlobs = file->GetSubBlobs(); if (subBlobs) { blobSet.AppendBlobs(*subBlobs); } else { blobSet.AppendBlob(blob); } continue; } if (JS_IsArrayBufferViewObject(&obj)) { blobSet.AppendVoidPtr(JS_GetArrayBufferViewData(&obj), JS_GetArrayBufferViewByteLength(&obj)); continue; } if (JS_IsArrayBufferObject(&obj)) { blobSet.AppendArrayBuffer(&obj); continue; } // neither Blob nor ArrayBuffer(View) } else if (element.isString()) { blobSet.AppendString(element.toString(), nativeEOL, aCx); continue; } // coerce it to a string JSString* str = JS_ValueToString(aCx, element); NS_ENSURE_TRUE(str, NS_ERROR_TYPE_ERR); blobSet.AppendString(str, nativeEOL, aCx); } mBlobs = blobSet.GetBlobs(); } return NS_OK; }
nsresult BluetoothService::HandleSettingsChanged(const nsAString& aData) { MOZ_ASSERT(NS_IsMainThread()); // The string that we're interested in will be a JSON string that looks like: // {"key":"bluetooth.enabled","value":true} JSContext* cx = nsContentUtils::GetSafeJSContext(); if (!cx) { return NS_OK; } JS::Value val; if (!JS_ParseJSON(cx, aData.BeginReading(), aData.Length(), &val)) { return JS_ReportPendingException(cx) ? NS_OK : NS_ERROR_OUT_OF_MEMORY; } if (!val.isObject()) { return NS_OK; } JSObject& obj(val.toObject()); JS::Value key; if (!JS_GetProperty(cx, &obj, "key", &key)) { MOZ_ASSERT(!JS_IsExceptionPending(cx)); return NS_ERROR_OUT_OF_MEMORY; } if (!key.isString()) { return NS_OK; } JSBool match; if (!JS_StringEqualsAscii(cx, key.toString(), BLUETOOTH_ENABLED_SETTING, &match)) { MOZ_ASSERT(!JS_IsExceptionPending(cx)); return NS_ERROR_OUT_OF_MEMORY; } if (!match) { return NS_OK; } JS::Value value; if (!JS_GetProperty(cx, &obj, "value", &value)) { MOZ_ASSERT(!JS_IsExceptionPending(cx)); return NS_ERROR_OUT_OF_MEMORY; } if (!value.isBoolean()) { MOZ_ASSERT(false, "Expecting a boolean for 'bluetooth.enabled'!"); return NS_ERROR_UNEXPECTED; } if (mSettingsCheckInProgress) { // Somehow the setting for bluetooth has been flipped before our first // settings check completed. Flip this flag so that we ignore the result // of that check whenever it finishes. mSettingsCheckInProgress = false; } if (value.toBoolean() == IsEnabled()) { // Nothing to do here. return NS_OK; } nsresult rv; if (IsEnabled()) { rv = StartStopBluetooth(false); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; } rv = StartStopBluetooth(true); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; }
nsresult BluetoothHfpManager::HandleVolumeChanged(const nsAString& aData) { MOZ_ASSERT(NS_IsMainThread()); // The string that we're interested in will be a JSON string that looks like: // {"key":"volumeup", "value":1.0} // {"key":"volumedown", "value":0.2} JSContext* cx = nsContentUtils::GetSafeJSContext(); if (!cx) { return NS_OK; } JS::Value val; if (!JS_ParseJSON(cx, aData.BeginReading(), aData.Length(), &val)) { return JS_ReportPendingException(cx) ? NS_OK : NS_ERROR_OUT_OF_MEMORY; } if (!val.isObject()) { return NS_OK; } JSObject& obj(val.toObject()); JS::Value key; if (!JS_GetProperty(cx, &obj, "key", &key)) { MOZ_ASSERT(!JS_IsExceptionPending(cx)); return NS_ERROR_OUT_OF_MEMORY; } if (!key.isString()) { return NS_OK; } JSBool match; if (!JS_StringEqualsAscii(cx, key.toString(), AUDIO_VOLUME_MASTER, &match)) { MOZ_ASSERT(!JS_IsExceptionPending(cx)); return NS_ERROR_OUT_OF_MEMORY; } if (!match) { return NS_OK; } JS::Value value; if (!JS_GetProperty(cx, &obj, "value", &value)) { MOZ_ASSERT(!JS_IsExceptionPending(cx)); return NS_ERROR_OUT_OF_MEMORY; } if (!value.isNumber()) { return NS_ERROR_UNEXPECTED; } // AG volume range: [0.0, 1.0] float volume = value.toNumber(); // HS volume range: [0, 15] mCurrentVgs = ceil(volume * 15); nsDiscriminatedUnion du; du.mType = 0; du.u.mInt8Value = mCurrentVgs; nsCString vgs; if (NS_FAILED(nsVariant::ConvertToACString(du, vgs))) { NS_WARNING("Failed to convert volume to string"); return NS_ERROR_FAILURE; } nsAutoCString newVgs; newVgs += "+VGS: "; newVgs += vgs; SendLine(newVgs.get()); return NS_OK; }
nsresult BluetoothManager::HandleMozsettingChanged(const PRUnichar* aData) { // The string that we're interested in will be a JSON string that looks like: // {"key":"bluetooth.enabled","value":true} nsresult rv; nsIScriptContext* sc = GetContextForEventHandlers(&rv); if (NS_FAILED(rv)) { return NS_ERROR_UNEXPECTED; } JSContext *cx = sc->GetNativeContext(); if (!cx) { return NS_OK; } // In the following [if] blocks, NS_OK will be returned even if JS_* functions // return false. That's because this function gets called whenever mozSettings // changes, so that we'll receive signals we're not interested in and it would // be one of the reasons for making JS_* functions return false. nsDependentString dataStr(aData); JS::Value val; if (!JS_ParseJSON(cx, dataStr.get(), dataStr.Length(), &val)) { return NS_OK; } if (!val.isObject()) { return NS_OK; } JSObject &obj(val.toObject()); JS::Value key; if (!JS_GetProperty(cx, &obj, "key", &key)) { return NS_OK; } if (!key.isString()) { return NS_OK; } JSBool match; if (!JS_StringEqualsAscii(cx, key.toString(), "bluetooth.enabled", &match)) { return NS_OK; } if (!match) { return NS_OK; } JS::Value value; if (!JS_GetProperty(cx, &obj, "value", &value)) { return NS_OK; } if (!value.isBoolean()) { return NS_OK; } BluetoothService* bs = BluetoothService::Get(); if (!bs) { NS_WARNING("BluetoothService not available!"); return NS_ERROR_FAILURE; } bool enabled = value.toBoolean(); bool isEnabled = (bs->IsEnabledInternal() > 0); if (!isEnabled && enabled) { if (NS_FAILED(bs->RegisterBluetoothSignalHandler(NS_LITERAL_STRING("/"), this))) { NS_ERROR("Failed to register object with observer!"); return NS_ERROR_FAILURE; } } else if (isEnabled && !enabled){ if (NS_FAILED(bs->UnregisterBluetoothSignalHandler(NS_LITERAL_STRING("/"), this))) { NS_WARNING("Failed to unregister object with observer!"); } } else { return NS_OK; } nsCOMPtr<nsIRunnable> resultTask = new ToggleBtResultTask(this, enabled); if (enabled) { if (NS_FAILED(bs->Start(resultTask))) { return NS_ERROR_FAILURE; } } else { if (NS_FAILED(bs->Stop(resultTask))) { return NS_ERROR_FAILURE; } } return NS_OK; }