diff --git a/dom/bluetooth/BluetoothUtils.cpp b/dom/bluetooth/bluedroid/BluetoothUtils.cpp similarity index 100% rename from dom/bluetooth/BluetoothUtils.cpp rename to dom/bluetooth/bluedroid/BluetoothUtils.cpp diff --git a/dom/bluetooth/BluetoothUtils.h b/dom/bluetooth/bluedroid/BluetoothUtils.h similarity index 100% rename from dom/bluetooth/BluetoothUtils.h rename to dom/bluetooth/bluedroid/BluetoothUtils.h diff --git a/dom/bluetooth/bluez/BluetoothUtils.cpp b/dom/bluetooth/bluez/BluetoothUtils.cpp new file mode 100644 index 000000000000..55571587ae6c --- /dev/null +++ b/dom/bluetooth/bluez/BluetoothUtils.cpp @@ -0,0 +1,198 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "base/basictypes.h" + +#include "BluetoothReplyRunnable.h" +#include "BluetoothService.h" +#include "BluetoothUtils.h" +#include "jsapi.h" +#include "mozilla/Scoped.h" +#include "mozilla/dom/bluetooth/BluetoothTypes.h" +#include "nsContentUtils.h" +#include "nsCxPusher.h" +#include "nsIScriptContext.h" +#include "nsISystemMessagesInternal.h" +#include "nsString.h" +#include "nsTArray.h" +#include "nsServiceManagerUtils.h" + +BEGIN_BLUETOOTH_NAMESPACE + +bool +SetJsObject(JSContext* aContext, + const BluetoothValue& aValue, + JS::Handle aObj) +{ + MOZ_ASSERT(aContext && aObj); + + if (aValue.type() != BluetoothValue::TArrayOfBluetoothNamedValue) { + BT_WARNING("SetJsObject: Invalid parameter type"); + return false; + } + + const nsTArray& arr = + aValue.get_ArrayOfBluetoothNamedValue(); + + for (uint32_t i = 0; i < arr.Length(); i++) { + JS::Rooted val(aContext); + const BluetoothValue& v = arr[i].value(); + + switch(v.type()) { + case BluetoothValue::TnsString: { + JSString* jsData = JS_NewUCStringCopyN(aContext, + v.get_nsString().BeginReading(), + v.get_nsString().Length()); + NS_ENSURE_TRUE(jsData, false); + val = STRING_TO_JSVAL(jsData); + break; + } + case BluetoothValue::Tuint32_t: + val = INT_TO_JSVAL(v.get_uint32_t()); + break; + case BluetoothValue::Tbool: + val = BOOLEAN_TO_JSVAL(v.get_bool()); + break; + default: + BT_WARNING("SetJsObject: Parameter is not handled"); + break; + } + + if (!JS_SetProperty(aContext, aObj, + NS_ConvertUTF16toUTF8(arr[i].name()).get(), + val)) { + BT_WARNING("Failed to set property"); + return false; + } + } + + return true; +} + +nsString +GetObjectPathFromAddress(const nsAString& aAdapterPath, + const nsAString& aDeviceAddress) +{ + // The object path would be like /org/bluez/2906/hci0/dev_00_23_7F_CB_B4_F1, + // and the adapter path would be the first part of the object path, according + // to the example above, it's /org/bluez/2906/hci0. + nsString devicePath(aAdapterPath); + devicePath.AppendLiteral("/dev_"); + devicePath.Append(aDeviceAddress); + devicePath.ReplaceChar(':', '_'); + return devicePath; +} + +nsString +GetAddressFromObjectPath(const nsAString& aObjectPath) +{ + // The object path would be like /org/bluez/2906/hci0/dev_00_23_7F_CB_B4_F1, + // and the adapter path would be the first part of the object path, according + // to the example above, it's /org/bluez/2906/hci0. + nsString address(aObjectPath); + int addressHead = address.RFind("/") + 5; + + MOZ_ASSERT(addressHead + BLUETOOTH_ADDRESS_LENGTH == (int)address.Length()); + + address.Cut(0, addressHead); + address.ReplaceChar('_', ':'); + + return address; +} + +bool +BroadcastSystemMessage(const nsAString& aType, + const InfallibleTArray& aData) +{ + mozilla::AutoSafeJSContext cx; + NS_ASSERTION(!::JS_IsExceptionPending(cx), + "Shouldn't get here when an exception is pending!"); + + JS::Rooted obj(cx, JS_NewObject(cx, nullptr, nullptr, nullptr)); + if (!obj) { + BT_WARNING("Failed to new JSObject for system message!"); + return false; + } + + if (!SetJsObject(cx, aData, obj)) { + BT_WARNING("Failed to set properties of system message!"); + return false; + } + + nsCOMPtr systemMessenger = + do_GetService("@mozilla.org/system-message-internal;1"); + NS_ENSURE_TRUE(systemMessenger, false); + + systemMessenger->BroadcastMessage(aType, + OBJECT_TO_JSVAL(obj), + JS::UndefinedValue()); + + return true; +} + +void +DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable, + const BluetoothValue& aValue, + const nsAString& aErrorStr) +{ + // Reply will be deleted by the runnable after running on main thread + BluetoothReply* reply; + if (!aErrorStr.IsEmpty()) { + nsString err(aErrorStr); + reply = new BluetoothReply(BluetoothReplyError(err)); + } else { + MOZ_ASSERT(aValue.type() != BluetoothValue::T__None); + reply = new BluetoothReply(BluetoothReplySuccess(aValue)); + } + + aRunnable->SetReply(reply); + if (NS_FAILED(NS_DispatchToMainThread(aRunnable))) { + BT_WARNING("Failed to dispatch to main thread!"); + } +} + +void +ParseAtCommand(const nsACString& aAtCommand, const int aStart, + nsTArray& aRetValues) +{ + int length = aAtCommand.Length(); + int begin = aStart; + + for (int i = aStart; i < length; ++i) { + // Use ',' as separator + if (aAtCommand[i] == ',') { + nsCString tmp(nsDependentCSubstring(aAtCommand, begin, i - begin)); + aRetValues.AppendElement(tmp); + + begin = i + 1; + } + } + + nsCString tmp(nsDependentCSubstring(aAtCommand, begin)); + aRetValues.AppendElement(tmp); +} + +void +DispatchStatusChangedEvent(const nsAString& aType, + const nsAString& aAddress, + bool aStatus) +{ + MOZ_ASSERT(NS_IsMainThread()); + + InfallibleTArray data; + data.AppendElement( + BluetoothNamedValue(NS_LITERAL_STRING("address"), nsString(aAddress))); + data.AppendElement( + BluetoothNamedValue(NS_LITERAL_STRING("status"), aStatus)); + + BluetoothSignal signal(nsString(aType), NS_LITERAL_STRING(KEY_ADAPTER), data); + + BluetoothService* bs = BluetoothService::Get(); + NS_ENSURE_TRUE_VOID(bs); + bs->DistributeSignal(signal); +} + +END_BLUETOOTH_NAMESPACE diff --git a/dom/bluetooth/bluez/BluetoothUtils.h b/dom/bluetooth/bluez/BluetoothUtils.h new file mode 100644 index 000000000000..2156207f1d4f --- /dev/null +++ b/dom/bluetooth/bluez/BluetoothUtils.h @@ -0,0 +1,51 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_bluetooth_bluetoothutils_h__ +#define mozilla_dom_bluetooth_bluetoothutils_h__ + +#include "BluetoothCommon.h" +#include "js/TypeDecls.h" + +BEGIN_BLUETOOTH_NAMESPACE + +class BluetoothNamedValue; +class BluetoothValue; +class BluetoothReplyRunnable; + +bool +SetJsObject(JSContext* aContext, + const BluetoothValue& aValue, + JS::Handle aObj); + +nsString +GetObjectPathFromAddress(const nsAString& aAdapterPath, + const nsAString& aDeviceAddress); + +nsString +GetAddressFromObjectPath(const nsAString& aObjectPath); + +bool +BroadcastSystemMessage(const nsAString& aType, + const InfallibleTArray& aData); + +void +DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable, + const BluetoothValue& aValue, + const nsAString& aErrorStr); + +void +ParseAtCommand(const nsACString& aAtCommand, const int aStart, + nsTArray& aRetValues); + +void +DispatchStatusChangedEvent(const nsAString& aType, + const nsAString& aDeviceAddress, + bool aStatus); + +END_BLUETOOTH_NAMESPACE + +#endif diff --git a/dom/bluetooth/moz.build b/dom/bluetooth/moz.build index 7b12fc3fd919..08a01d377404 100644 --- a/dom/bluetooth/moz.build +++ b/dom/bluetooth/moz.build @@ -16,7 +16,6 @@ if CONFIG['MOZ_B2G_BT']: 'BluetoothPropertyContainer.cpp', 'BluetoothReplyRunnable.cpp', 'BluetoothService.cpp', - 'BluetoothUtils.cpp', 'BluetoothUuid.cpp', 'ipc/BluetoothChild.cpp', 'ipc/BluetoothParent.cpp', @@ -37,6 +36,7 @@ if CONFIG['MOZ_B2G_BT']: 'bluez/BluetoothOppManager.cpp', 'bluez/BluetoothSocket.cpp', 'bluez/BluetoothUnixSocketConnector.cpp', + 'bluez/BluetoothUtils.cpp', 'bluez/gonk/BluetoothGonkService.cpp', 'bluez/linux/BluetoothDBusService.cpp', ] @@ -52,6 +52,7 @@ if CONFIG['MOZ_B2G_BT']: 'bluedroid/BluetoothHfpManager.cpp', 'bluedroid/BluetoothOppManager.cpp', 'bluedroid/BluetoothSocket.cpp', + 'bluedroid/BluetoothUtils.cpp', 'bluedroid/gonk/BluetoothServiceBluedroid.cpp', ] LOCAL_INCLUDES += [