diff --git a/dom/bluetooth/BluetoothAdapter.cpp b/dom/bluetooth/BluetoothAdapter.cpp index 7d6a484d367..05c79070321 100644 --- a/dom/bluetooth/BluetoothAdapter.cpp +++ b/dom/bluetooth/BluetoothAdapter.cpp @@ -293,7 +293,7 @@ BluetoothAdapter::Notify(const BluetoothSignal& aData) bool dummy; DispatchEvent(event, &dummy); } else if (aData.name().EqualsLiteral("DeviceDisappeared")) { - const nsAString& deviceAddress = aData.value().get_nsString(); + const nsAString& deviceAddress = aData.value().get_nsString(); nsCOMPtr event; NS_NewDOMBluetoothDeviceAddressEvent(getter_AddRefs(event), nullptr, nullptr); @@ -404,7 +404,7 @@ BluetoothAdapter::Notify(const BluetoothSignal& aData) } else { #ifdef DEBUG nsCString warningMsg; - warningMsg.AssignLiteral("Not handling manager signal: "); + warningMsg.AssignLiteral("Not handling adapter signal: "); warningMsg.Append(NS_ConvertUTF16toUTF8(aData.name())); NS_WARNING(warningMsg.get()); #endif diff --git a/dom/bluetooth/BluetoothCommon.h b/dom/bluetooth/BluetoothCommon.h index f64bfe33510..cd3ac98cf4b 100644 --- a/dom/bluetooth/BluetoothCommon.h +++ b/dom/bluetooth/BluetoothCommon.h @@ -24,12 +24,14 @@ // Bluetooth address format: xx:xx:xx:xx:xx:xx (or xx_xx_xx_xx_xx_xx) #define BLUETOOTH_ADDRESS_LENGTH 17 -#define DOM_BLUETOOTH_URL_PREF "dom.mozBluetooth.whitelist" - -class nsCString; - BEGIN_BLUETOOTH_NAMESPACE +enum BluetoothSocketType { + RFCOMM = 1, + SCO = 2, + L2CAP = 3 +}; + class BluetoothSignal; typedef mozilla::Observer BluetoothSignalObserver; diff --git a/dom/bluetooth/BluetoothDevice.cpp b/dom/bluetooth/BluetoothDevice.cpp index 22e4d78ebb6..cc26604aa30 100644 --- a/dom/bluetooth/BluetoothDevice.cpp +++ b/dom/bluetooth/BluetoothDevice.cpp @@ -11,6 +11,7 @@ #include "BluetoothReplyRunnable.h" #include "BluetoothService.h" #include "BluetoothUtils.h" +#include "BluetoothServiceUuid.h" #include "nsIDOMDOMRequest.h" #include "nsDOMClassInfo.h" @@ -25,6 +26,7 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothDevice) NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(BluetoothDevice, nsDOMEventTargetHelper) NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mJsUuids) + NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mJsServices) NS_IMPL_CYCLE_COLLECTION_TRACE_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothDevice, @@ -50,6 +52,7 @@ BluetoothDevice::BluetoothDevice(nsPIDOMWindow* aOwner, const BluetoothValue& aValue) : BluetoothPropertyContainer(BluetoothObjectType::TYPE_DEVICE), mJsUuids(nullptr), + mJsServices(nullptr), mAdapterPath(aAdapterPath), mIsRooted(false) { @@ -90,7 +93,7 @@ BluetoothDevice::Unroot() mIsRooted = false; } } - + void BluetoothDevice::SetPropertyByValue(const BluetoothNamedValue& aValue) { @@ -98,15 +101,17 @@ BluetoothDevice::SetPropertyByValue(const BluetoothNamedValue& aValue) const BluetoothValue& value = aValue.value(); if (name.EqualsLiteral("Name")) { mName = value.get_nsString(); - } else if (name.EqualsLiteral("Address")) { - mAddress = value.get_nsString(); + } else if (name.EqualsLiteral("Path")) { + mPath = value.get_nsString(); + NS_WARNING(NS_ConvertUTF16toUTF8(mPath).get()); BluetoothService* bs = BluetoothService::Get(); if (!bs) { NS_WARNING("BluetoothService not available!"); - return; + } else if (NS_FAILED(bs->RegisterBluetoothSignalHandler(mPath, this))) { + NS_WARNING("Failed to register object with observer!"); } - // We can't actually set up our path until we know our address - bs->GetDevicePath(mAdapterPath, mAddress, mPath); + } else if (name.EqualsLiteral("Address")) { + mAddress = value.get_nsString(); } else if (name.EqualsLiteral("Class")) { mClass = value.get_uint32_t(); } else if (name.EqualsLiteral("Icon")) { @@ -131,6 +136,22 @@ BluetoothDevice::SetPropertyByValue(const BluetoothNamedValue& aValue) } else { NS_WARNING("Could not get context!"); } + } else if (name.EqualsLiteral("Services")) { + mServices = value.get_ArrayOfnsString(); + nsresult rv; + nsIScriptContext* sc = GetContextForEventHandlers(&rv); + if (sc) { + rv = + StringArrayToJSArray(sc->GetNativeContext(), + sc->GetNativeGlobal(), mServices, &mJsServices); + if (NS_FAILED(rv)) { + NS_WARNING("Cannot set JS Services object!"); + return; + } + Root(); + } else { + NS_WARNING("Could not get context!"); + } #ifdef DEBUG } else { nsCString warningMsg; @@ -253,7 +274,18 @@ BluetoothDevice::GetUuids(JSContext* aCx, jsval* aUuids) } else { NS_WARNING("UUIDs not yet set!\n"); return NS_ERROR_FAILURE; - } + } + return NS_OK; +} + +NS_IMETHODIMP +BluetoothDevice::GetServices(JSContext* aCx, jsval* aServices) +{ + if (mJsServices) { + aServices->setObject(*mJsServices); + } else { + NS_WARNING("Services not yet set!\n"); + } return NS_OK; } diff --git a/dom/bluetooth/BluetoothDevice.h b/dom/bluetooth/BluetoothDevice.h index 3c6806c859d..9bfe74b166b 100644 --- a/dom/bluetooth/BluetoothDevice.h +++ b/dom/bluetooth/BluetoothDevice.h @@ -20,6 +20,7 @@ BEGIN_BLUETOOTH_NAMESPACE class BluetoothNamedValue; class BluetoothValue; class BluetoothSignal; +class BluetoothSocket; class BluetoothDevice : public nsDOMEventTargetHelper , public nsIDOMBluetoothDevice @@ -64,6 +65,7 @@ private: void Root(); JSObject* mJsUuids; + JSObject* mJsServices; nsString mAdapterPath; nsString mAddress; @@ -74,6 +76,8 @@ private: bool mPaired; bool mIsRooted; nsTArray mUuids; + nsTArray mServices; + }; END_BLUETOOTH_NAMESPACE diff --git a/dom/bluetooth/BluetoothService.cpp b/dom/bluetooth/BluetoothService.cpp index dd2421c0f13..6880866f03d 100644 --- a/dom/bluetooth/BluetoothService.cpp +++ b/dom/bluetooth/BluetoothService.cpp @@ -145,8 +145,19 @@ BluetoothService::DistributeSignal(const BluetoothSignal& signal) // Notify observers that a message has been sent BluetoothSignalObserverList* ol; if (!mBluetoothSignalObserverTable.Get(signal.path(), &ol)) { +#if DEBUG + nsString msg; + msg.AssignLiteral("No observer registered for path"); + msg.Append(signal.path()); + NS_WARNING(NS_ConvertUTF16toUTF8(msg).get()); +#endif return NS_OK; } +#if DEBUG + if (ol->Length() == 0) { + NS_WARNING("Distributing to observer list of 0"); + } +#endif ol->Broadcast(signal); return NS_OK; } diff --git a/dom/bluetooth/BluetoothService.h b/dom/bluetooth/BluetoothService.h index f84d44c92b8..468403b2b1c 100644 --- a/dom/bluetooth/BluetoothService.h +++ b/dom/bluetooth/BluetoothService.h @@ -197,12 +197,7 @@ public: const nsAString& aDeviceAddress, nsAString& aDevicePath) = 0; - virtual int - GetDeviceServiceChannelInternal(const nsAString& aObjectPath, - const nsAString& aPattern, - int aAttributeId) = 0; - - virtual nsTArray + virtual nsTArray AddReservedServicesInternal(const nsAString& aAdapterPath, const nsTArray& aServices) = 0; @@ -221,6 +216,17 @@ public: const nsAString& aObjectPath, BluetoothReplyRunnable* aRunnable) = 0; + virtual nsresult + GetSocketViaService(const nsAString& aObjectPath, + const nsAString& aService, + int aType, + bool aAuth, + bool aEncrypt, + BluetoothReplyRunnable* aRunnable) = 0; + + virtual bool + CloseSocket(int aFd, BluetoothReplyRunnable* aRunnable) = 0; + virtual bool SetPinCodeInternal(const nsAString& aDeviceAddress, const nsAString& aPinCode) = 0; virtual bool SetPasskeyInternal(const nsAString& aDeviceAddress, uint32_t aPasskey) = 0; virtual bool SetPairingConfirmationInternal(const nsAString& aDeviceAddress, bool aConfirm) = 0; diff --git a/dom/bluetooth/BluetoothServiceUuid.h b/dom/bluetooth/BluetoothServiceUuid.h new file mode 100644 index 00000000000..8bd67e76825 --- /dev/null +++ b/dom/bluetooth/BluetoothServiceUuid.h @@ -0,0 +1,39 @@ +/* -*- 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_bluetoothuuid_h__ +#define mozilla_dom_bluetooth_bluetoothuuid_h__ + +namespace mozilla { +namespace dom { +namespace bluetooth { + +namespace BluetoothServiceUuid { + static unsigned long long AudioSink = 0x0000110B00000000; + static unsigned long long AudioSource = 0x0000110A00000000; + static unsigned long long AdvAudioDist = 0x0000110D00000000; + static unsigned long long Headset = 0x0000110800000000; + static unsigned long long HandsfreeAG = 0x0000111F00000000; + + static unsigned long long BaseMSB = 0x0000000000001000; + static unsigned long long BaseLSB = 0x800000805F9B34FB; +} + +namespace BluetoothServiceUuidStr { + static const char* AudioSink = "0000110B-0000-1000-8000-00805F9B34FB"; + static const char* AudioSource = "0000110A-0000-1000-8000-00805F9B34FB"; + static const char* AdvAudioDist = "0000110D-0000-1000-8000-00805F9B34FB"; + static const char* Headset = "00001108-0000-1000-8000-00805F9B34FB"; + static const char* Handsfree = "0000111E-0000-1000-8000-00805F9B34FB"; + static const char* HandsfreeAG = "0000111F-0000-1000-8000-00805F9B34FB"; +} + +} +} +} + +#endif + diff --git a/dom/bluetooth/linux/BluetoothDBusService.cpp b/dom/bluetooth/linux/BluetoothDBusService.cpp index 8ab2ab2bb00..5051320c4bc 100644 --- a/dom/bluetooth/linux/BluetoothDBusService.cpp +++ b/dom/bluetooth/linux/BluetoothDBusService.cpp @@ -29,6 +29,7 @@ #include "nsThreadUtils.h" #include "nsDebug.h" #include "nsDataHashtable.h" +#include "mozilla/ipc/Socket.h" #include "mozilla/ipc/DBusThread.h" #include "mozilla/ipc/DBusUtils.h" #include "mozilla/ipc/RawDBusConnection.h" @@ -140,6 +141,39 @@ static nsAutoPtr gThreadConnection; static nsDataHashtable sPairingReqTable; static nsDataHashtable sAuthorizeReqTable; +typedef void (*UnpackFunc)(DBusMessage*, DBusError*, BluetoothValue&, nsAString&); + +static 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; +} + +static 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 == address.Length()); + + address.Cut(0, addressHead); + address.ReplaceChar('_', ':'); + + return address; +} + class DistributeBluetoothSignalTask : public nsRunnable { BluetoothSignal mSignal; public: @@ -156,15 +190,15 @@ public: if (!bs) { NS_WARNING("BluetoothService not available!"); return NS_ERROR_FAILURE; - } + } return bs->DistributeSignal(mSignal); - } + } }; static bool IsDBusMessageError(DBusMessage* aMsg, DBusError* aErr, nsAString& aErrorStr) { - if(aErr && dbus_error_is_set(aErr)) { + if (aErr && dbus_error_is_set(aErr)) { aErrorStr = NS_ConvertUTF8toUTF16(aErr->message); LOG_AND_FREE_DBUS_ERROR(aErr); return true; @@ -212,6 +246,28 @@ DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable, } } +static void +UnpackIntMessage(DBusMessage* aMsg, DBusError* aErr, + BluetoothValue& aValue, nsAString& aErrorStr) +{ + DBusError err; + dbus_error_init(&err); + if (!IsDBusMessageError(aMsg, aErr, aErrorStr)) { + NS_ASSERTION(dbus_message_get_type(aMsg) == DBUS_MESSAGE_TYPE_METHOD_RETURN, + "Got dbus callback that's not a METHOD_RETURN!"); + int i; + if (!dbus_message_get_args(aMsg, &err, DBUS_TYPE_INT32, + &i, DBUS_TYPE_INVALID)) { + if (dbus_error_is_set(&err)) { + aErrorStr = NS_ConvertUTF8toUTF16(err.message); + LOG_AND_FREE_DBUS_ERROR(&err); + } + } else { + aValue = (uint32_t)i; + } + } +} + static void UnpackObjectPathMessage(DBusMessage* aMsg, DBusError* aErr, BluetoothValue& aValue, nsAString& aErrorStr) @@ -235,39 +291,6 @@ UnpackObjectPathMessage(DBusMessage* aMsg, DBusError* aErr, } } -typedef void (*UnpackFunc)(DBusMessage*, DBusError*, BluetoothValue&, nsAString&); - -static 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, accoring - // to the example above, it's /org/bluez/2906/hci0. - nsString devicePath(aAdapterPath); - devicePath.AppendLiteral("/dev_"); - devicePath.Append(aDeviceAddress); - devicePath.ReplaceChar(':', '_'); - return devicePath; -} - -static 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, accoring - // to the example above, it's /org/bluez/2906/hci0. - nsString address(aObjectPath); - int addressHead = address.RFind("/") + 5; - - MOZ_ASSERT(addressHead + BLUETOOTH_ADDRESS_LENGTH == address.Length()); - - address.Cut(0, addressHead); - address.ReplaceChar('_', ':'); - - return address; -} - static void KeepDBusPairingMessage(const nsString& aDeviceAddress, DBusMessage* aMsg) { @@ -485,7 +508,7 @@ RegisterLocalAgent(const char* adapterPath, if (!reply) { if (dbus_error_is_set(&err)) { - if(!strcmp(err.name, "org.bluez.Error.AlreadyExists")) { + if (!strcmp(err.name, "org.bluez.Error.AlreadyExists")) { LOG_AND_FREE_DBUS_ERROR(&err); #ifdef DEBUG LOG("Agent already registered, still returning true"); @@ -577,6 +600,13 @@ GetVoidCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable) UnpackVoidMessage); } +void +GetIntCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable) +{ + RunDBusCallback(aMsg, aBluetoothReplyRunnable, + UnpackIntMessage); +} + bool GetProperty(DBusMessageIter aIter, Properties* aPropertyTypes, int aPropertyTypeLen, int* aPropIndex, @@ -789,7 +819,7 @@ ParsePropertyChange(DBusMessage* aMsg, BluetoothValue& aValue, dbus_error_init(&err); if (!dbus_message_iter_init(aMsg, &iter)) { - LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, aMsg); + NS_WARNING("Can't create iterator!"); return; } @@ -811,7 +841,8 @@ EventFilter(DBusConnection* aConn, DBusMessage* aMsg, void* aData) NS_ASSERTION(!NS_IsMainThread(), "Shouldn't be called from Main Thread!"); if (dbus_message_get_type(aMsg) != DBUS_MESSAGE_TYPE_SIGNAL) { - LOG("%s: not interested (not a signal).\n", __FUNCTION__); + LOG("%s: event handler not interested in %s (not a signal).\n", + __FUNCTION__, dbus_message_get_member(aMsg)); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } @@ -868,8 +899,9 @@ EventFilter(DBusConnection* aConn, DBusMessage* aMsg, void* aData) DBUS_TYPE_INVALID)) { LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, aMsg); errorStr.AssignLiteral("Cannot parse device address!"); + } else { + v = NS_ConvertUTF8toUTF16(str); } - v = NS_ConvertUTF8toUTF16(str); } else if (dbus_message_is_signal(aMsg, DBUS_ADAPTER_IFACE, "DeviceCreated")) { const char* str; if (!dbus_message_get_args(aMsg, &err, @@ -877,8 +909,19 @@ EventFilter(DBusConnection* aConn, DBusMessage* aMsg, void* aData) DBUS_TYPE_INVALID)) { LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, aMsg); errorStr.AssignLiteral("Cannot parse device path!"); + } else { + v = NS_ConvertUTF8toUTF16(str); + } + } else if (dbus_message_is_signal(aMsg, DBUS_ADAPTER_IFACE, "DeviceRemoved")) { + const char* str; + if (!dbus_message_get_args(aMsg, &err, + DBUS_TYPE_OBJECT_PATH, &str, + DBUS_TYPE_INVALID)) { + LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, aMsg); + errorStr.AssignLiteral("Cannot parse device path!"); + } else { + v = NS_ConvertUTF8toUTF16(str); } - v = NS_ConvertUTF8toUTF16(str); } else if (dbus_message_is_signal(aMsg, DBUS_ADAPTER_IFACE, "PropertyChanged")) { ParsePropertyChange(aMsg, v, @@ -1071,10 +1114,10 @@ public: "DefaultAdapter", DBUS_TYPE_INVALID); UnpackObjectPathMessage(msg, &err, v, replyError); - if(msg) { + if (msg) { dbus_message_unref(msg); } - if(!replyError.IsEmpty()) { + if (!replyError.IsEmpty()) { DispatchBluetoothReply(mRunnable, v, replyError); return NS_ERROR_FAILURE; } @@ -1093,11 +1136,11 @@ public: DBUS_TYPE_INVALID); UnpackAdapterPropertiesMessage(msg, &err, v, replyError); - if(!replyError.IsEmpty()) { + if (!replyError.IsEmpty()) { DispatchBluetoothReply(mRunnable, v, replyError); return NS_ERROR_FAILURE; } - if(msg) { + if (msg) { dbus_message_unref(msg); } // We have to manually attach the path to the rest of the elements @@ -1145,6 +1188,7 @@ BluetoothDBusService::SendDiscoveryMessage(const nsAString& aAdapterPath, NS_WARNING("Bluetooth service not started yet!"); return NS_ERROR_FAILURE; } + NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!"); nsRefPtr runnable = aRunnable; @@ -1385,9 +1429,9 @@ BluetoothDBusService::GetDevicePath(const nsAString& aAdapterPath, } int -BluetoothDBusService::GetDeviceServiceChannelInternal(const nsAString& aObjectPath, - const nsAString& aPattern, - int aAttributeId) +GetDeviceServiceChannel(const nsAString& aObjectPath, + const nsAString& aPattern, + int aAttributeId) { // This is a blocking call, should not be run on main thread. MOZ_ASSERT(!NS_IsMainThread()); @@ -1690,3 +1734,133 @@ BluetoothDBusService::SetAuthorizationInternal(const nsAString& aDeviceAddress, return result; } + +class CreateBluetoothSocketRunnable : public nsRunnable +{ +public: + CreateBluetoothSocketRunnable(BluetoothReplyRunnable* aRunnable, + const nsAString& aObjectPath, + const nsAString& aServiceUUID, + int aType, + bool aAuth, + bool aEncrypt) + : mRunnable(dont_AddRef(aRunnable)), + mObjectPath(aObjectPath), + mServiceUUID(aServiceUUID), + mType(aType), + mAuth(aAuth), + mEncrypt(aEncrypt) + { + } + + nsresult + Run() + { + NS_WARNING("Running create socket!\n"); + MOZ_ASSERT(!NS_IsMainThread()); + + nsString address = GetAddressFromObjectPath(mObjectPath); + int channel = GetDeviceServiceChannel(mObjectPath, mServiceUUID, 0x0004); + int fd = mozilla::ipc::GetNewSocket(mType, NS_ConvertUTF16toUTF8(address).get(), + channel, mAuth, mEncrypt); + BluetoothValue v; + nsString replyError; + if (fd < 0) { + replyError.AssignLiteral("SocketConnectionError"); + DispatchBluetoothReply(mRunnable, v, replyError); + return NS_ERROR_FAILURE; + } + + v = (uint32_t)fd; + + DispatchBluetoothReply(mRunnable, v, replyError); + + return NS_OK; + } + +private: + nsRefPtr mRunnable; + nsString mObjectPath; + nsString mServiceUUID; + int mType; + bool mAuth; + bool mEncrypt; +}; + +nsresult +BluetoothDBusService::GetSocketViaService(const nsAString& aObjectPath, + const nsAString& aService, + int aType, + bool aAuth, + bool aEncrypt, + BluetoothReplyRunnable* aRunnable) +{ + NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!"); + if (!mConnection || !gThreadConnection) { + NS_ERROR("Bluetooth service not started yet!"); + return NS_ERROR_FAILURE; + } + nsRefPtr runnable = aRunnable; + + nsRefPtr func(new CreateBluetoothSocketRunnable(runnable, aObjectPath, + aService, aType, + aAuth, aEncrypt)); + if (NS_FAILED(mBluetoothCommandThread->Dispatch(func, NS_DISPATCH_NORMAL))) { + NS_WARNING("Cannot dispatch firmware loading task!"); + return NS_ERROR_FAILURE; + } + + runnable.forget(); + return NS_OK; +} + +class CloseBluetoothSocketRunnable : public nsRunnable +{ +public: + CloseBluetoothSocketRunnable(BluetoothReplyRunnable* aRunnable, + int aFd) + : mRunnable(dont_AddRef(aRunnable)), + mFd(aFd) + { + } + + nsresult + Run() + { + BluetoothValue v; + nsString replyError; + if (mozilla::ipc::CloseSocket(mFd) != 0) { + replyError.AssignLiteral("SocketConnectionError"); + DispatchBluetoothReply(mRunnable, v, replyError); + return NS_ERROR_FAILURE; + } + + DispatchBluetoothReply(mRunnable, v, replyError); + + return NS_OK; + } + +private: + nsRefPtr mRunnable; + int mFd; +}; + +bool +BluetoothDBusService::CloseSocket(int aFd, BluetoothReplyRunnable* aRunnable) +{ + NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!"); + if (!mConnection || !gThreadConnection) { + NS_ERROR("Bluetooth service not started yet!"); + return false; + } + nsRefPtr runnable = aRunnable; + + nsRefPtr func(new CloseBluetoothSocketRunnable(runnable, aFd)); + if (NS_FAILED(mBluetoothCommandThread->Dispatch(func, NS_DISPATCH_NORMAL))) { + NS_WARNING("Cannot dispatch firmware loading task!"); + return false; + } + + runnable.forget(); + return true; +} diff --git a/dom/bluetooth/linux/BluetoothDBusService.h b/dom/bluetooth/linux/BluetoothDBusService.h index 391e6e9e4c7..7428c50c057 100644 --- a/dom/bluetooth/linux/BluetoothDBusService.h +++ b/dom/bluetooth/linux/BluetoothDBusService.h @@ -46,10 +46,6 @@ public: GetDevicePath(const nsAString& aAdapterPath, const nsAString& aDeviceAddress, nsAString& aDevicePath); - virtual int - GetDeviceServiceChannelInternal(const nsAString& aObjectPath, - const nsAString& aPattern, - int aAttributeId); virtual nsTArray AddReservedServicesInternal(const nsAString& aAdapterPath, @@ -59,6 +55,16 @@ public: RemoveReservedServicesInternal(const nsAString& aAdapterPath, const nsTArray& aServiceHandles); + virtual nsresult + GetSocketViaService(const nsAString& aObjectPath, + const nsAString& aService, + int aType, + bool aAuth, + bool aEncrypt, + BluetoothReplyRunnable* aRunnable); + + virtual bool CloseSocket(int aFd, BluetoothReplyRunnable* aRunnable); + virtual nsresult CreatePairedDeviceInternal(const nsAString& aAdapterPath, const nsAString& aDeviceAddress, diff --git a/dom/bluetooth/nsIDOMBluetoothDevice.idl b/dom/bluetooth/nsIDOMBluetoothDevice.idl index 20b1361a9f0..95991bee4b1 100644 --- a/dom/bluetooth/nsIDOMBluetoothDevice.idl +++ b/dom/bluetooth/nsIDOMBluetoothDevice.idl @@ -14,6 +14,7 @@ interface nsIDOMBluetoothDevice : nsIDOMEventTarget readonly attribute DOMString icon; [binaryname(DeviceClass)] readonly attribute unsigned long class; [implicit_jscontext] readonly attribute jsval uuids; + [implicit_jscontext] readonly attribute jsval services; readonly attribute bool connected; readonly attribute bool paired; [implicit_jscontext] attribute jsval onpropertychanged;