michael@0: /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ michael@0: /* vim: set ts=2 et sw=2 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "base/basictypes.h" michael@0: michael@0: #include "BluetoothReplyRunnable.h" michael@0: #include "BluetoothService.h" michael@0: #include "BluetoothServiceBluedroid.h" michael@0: #include "BluetoothUtils.h" michael@0: #include "jsapi.h" michael@0: #include "mozilla/Scoped.h" michael@0: #include "mozilla/dom/bluetooth/BluetoothTypes.h" michael@0: #include "nsContentUtils.h" michael@0: #include "nsCxPusher.h" michael@0: #include "nsIScriptContext.h" michael@0: #include "nsISystemMessagesInternal.h" michael@0: #include "nsString.h" michael@0: #include "nsTArray.h" michael@0: #include "nsServiceManagerUtils.h" michael@0: michael@0: BEGIN_BLUETOOTH_NAMESPACE michael@0: michael@0: const bt_interface_t* michael@0: GetBluetoothInterface() michael@0: { michael@0: return BluetoothServiceBluedroid::GetBluetoothInterface(); michael@0: } michael@0: michael@0: void michael@0: StringToBdAddressType(const nsAString& aBdAddress, michael@0: bt_bdaddr_t *aRetBdAddressType) michael@0: { michael@0: NS_ConvertUTF16toUTF8 bdAddressUTF8(aBdAddress); michael@0: const char* str = bdAddressUTF8.get(); michael@0: michael@0: for (int i = 0; i < 6; i++) { michael@0: aRetBdAddressType->address[i] = (uint8_t) strtoul(str, (char **)&str, 16); michael@0: str++; michael@0: } michael@0: } michael@0: michael@0: void michael@0: BdAddressTypeToString(bt_bdaddr_t* aBdAddressType, nsAString& aRetBdAddress) michael@0: { michael@0: uint8_t* addr = aBdAddressType->address; michael@0: char bdstr[18]; michael@0: michael@0: sprintf(bdstr, "%02x:%02x:%02x:%02x:%02x:%02x", michael@0: (int)addr[0],(int)addr[1],(int)addr[2], michael@0: (int)addr[3],(int)addr[4],(int)addr[5]); michael@0: michael@0: aRetBdAddress = NS_ConvertUTF8toUTF16(bdstr); michael@0: } michael@0: michael@0: bool michael@0: SetJsObject(JSContext* aContext, michael@0: const BluetoothValue& aValue, michael@0: JS::Handle aObj) michael@0: { michael@0: MOZ_ASSERT(aContext && aObj); michael@0: michael@0: if (aValue.type() != BluetoothValue::TArrayOfBluetoothNamedValue) { michael@0: BT_WARNING("SetJsObject: Invalid parameter type"); michael@0: return false; michael@0: } michael@0: michael@0: const nsTArray& arr = michael@0: aValue.get_ArrayOfBluetoothNamedValue(); michael@0: michael@0: for (uint32_t i = 0; i < arr.Length(); i++) { michael@0: JS::Rooted val(aContext); michael@0: const BluetoothValue& v = arr[i].value(); michael@0: michael@0: switch(v.type()) { michael@0: case BluetoothValue::TnsString: { michael@0: JSString* jsData = JS_NewUCStringCopyN(aContext, michael@0: v.get_nsString().BeginReading(), michael@0: v.get_nsString().Length()); michael@0: NS_ENSURE_TRUE(jsData, false); michael@0: val = STRING_TO_JSVAL(jsData); michael@0: break; michael@0: } michael@0: case BluetoothValue::Tuint32_t: michael@0: val = INT_TO_JSVAL(v.get_uint32_t()); michael@0: break; michael@0: case BluetoothValue::Tbool: michael@0: val = BOOLEAN_TO_JSVAL(v.get_bool()); michael@0: break; michael@0: default: michael@0: BT_WARNING("SetJsObject: Parameter is not handled"); michael@0: break; michael@0: } michael@0: michael@0: if (!JS_SetProperty(aContext, aObj, michael@0: NS_ConvertUTF16toUTF8(arr[i].name()).get(), michael@0: val)) { michael@0: BT_WARNING("Failed to set property"); michael@0: return false; michael@0: } michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: BroadcastSystemMessage(const nsAString& aType, michael@0: const BluetoothValue& aData) michael@0: { michael@0: mozilla::AutoSafeJSContext cx; michael@0: NS_ASSERTION(!::JS_IsExceptionPending(cx), michael@0: "Shouldn't get here when an exception is pending!"); michael@0: michael@0: nsCOMPtr systemMessenger = michael@0: do_GetService("@mozilla.org/system-message-internal;1"); michael@0: NS_ENSURE_TRUE(systemMessenger, false); michael@0: michael@0: JS::Rooted value(cx); michael@0: if (aData.type() == BluetoothValue::TnsString) { michael@0: JSString* jsData = JS_NewUCStringCopyN(cx, michael@0: aData.get_nsString().BeginReading(), michael@0: aData.get_nsString().Length()); michael@0: value = STRING_TO_JSVAL(jsData); michael@0: } else if (aData.type() == BluetoothValue::TArrayOfBluetoothNamedValue) { michael@0: JS::Rooted obj(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), michael@0: JS::NullPtr())); michael@0: if (!obj) { michael@0: BT_WARNING("Failed to new JSObject for system message!"); michael@0: return false; michael@0: } michael@0: michael@0: if (!SetJsObject(cx, aData, obj)) { michael@0: BT_WARNING("Failed to set properties of system message!"); michael@0: return false; michael@0: } michael@0: value = JS::ObjectValue(*obj); michael@0: } else { michael@0: BT_WARNING("Not support the unknown BluetoothValue type"); michael@0: return false; michael@0: } michael@0: michael@0: systemMessenger->BroadcastMessage(aType, value, michael@0: JS::UndefinedHandleValue); michael@0: michael@0: return true; michael@0: } michael@0: michael@0: void michael@0: DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable, michael@0: const BluetoothValue& aValue, michael@0: const nsAString& aErrorStr) michael@0: { michael@0: // Reply will be deleted by the runnable after running on main thread michael@0: BluetoothReply* reply; michael@0: if (!aErrorStr.IsEmpty()) { michael@0: nsString err(aErrorStr); michael@0: reply = new BluetoothReply(BluetoothReplyError(err)); michael@0: } else { michael@0: MOZ_ASSERT(aValue.type() != BluetoothValue::T__None); michael@0: reply = new BluetoothReply(BluetoothReplySuccess(aValue)); michael@0: } michael@0: michael@0: aRunnable->SetReply(reply); michael@0: if (NS_FAILED(NS_DispatchToMainThread(aRunnable))) { michael@0: BT_WARNING("Failed to dispatch to main thread!"); michael@0: } michael@0: } michael@0: michael@0: void michael@0: DispatchStatusChangedEvent(const nsAString& aType, michael@0: const nsAString& aAddress, michael@0: bool aStatus) michael@0: { michael@0: MOZ_ASSERT(NS_IsMainThread()); michael@0: michael@0: InfallibleTArray data; michael@0: BT_APPEND_NAMED_VALUE(data, "address", nsString(aAddress)); michael@0: BT_APPEND_NAMED_VALUE(data, "status", aStatus); michael@0: michael@0: BluetoothSignal signal(nsString(aType), NS_LITERAL_STRING(KEY_ADAPTER), data); michael@0: michael@0: BluetoothService* bs = BluetoothService::Get(); michael@0: NS_ENSURE_TRUE_VOID(bs); michael@0: bs->DistributeSignal(signal); michael@0: } michael@0: michael@0: END_BLUETOOTH_NAMESPACE