1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "base/basictypes.h"
8 #include "BluetoothDevice.h"
9 #include "BluetoothReplyRunnable.h"
10 #include "BluetoothService.h"
11 #include "BluetoothUtils.h"
13 #include "nsDOMClassInfo.h"
14 #include "nsTArrayHelpers.h"
16 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
17 #include "mozilla/dom/BluetoothDeviceBinding.h"
18 #include "mozilla/dom/ScriptSettings.h"
20 USING_BLUETOOTH_NAMESPACE
22 DOMCI_DATA(BluetoothDevice
, BluetoothDevice
)
24 NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothDevice
)
26 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(BluetoothDevice
,
28 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mJsUuids
)
29 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mJsServices
)
30 NS_IMPL_CYCLE_COLLECTION_TRACE_END
32 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothDevice
,
34 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
35 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
37 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothDevice
,
40 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
42 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothDevice
)
43 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper
)
45 NS_IMPL_ADDREF_INHERITED(BluetoothDevice
, DOMEventTargetHelper
)
46 NS_IMPL_RELEASE_INHERITED(BluetoothDevice
, DOMEventTargetHelper
)
48 BluetoothDevice::BluetoothDevice(nsPIDOMWindow
* aWindow
,
49 const nsAString
& aAdapterPath
,
50 const BluetoothValue
& aValue
)
51 : DOMEventTargetHelper(aWindow
)
52 , BluetoothPropertyContainer(BluetoothObjectType::TYPE_DEVICE
)
54 , mJsServices(nullptr)
55 , mAdapterPath(aAdapterPath
)
59 MOZ_ASSERT(IsDOMBinding());
61 const InfallibleTArray
<BluetoothNamedValue
>& values
=
62 aValue
.get_ArrayOfBluetoothNamedValue();
63 for (uint32_t i
= 0; i
< values
.Length(); ++i
) {
64 SetPropertyByValue(values
[i
]);
67 BluetoothService
* bs
= BluetoothService::Get();
68 NS_ENSURE_TRUE_VOID(bs
);
69 bs
->RegisterBluetoothSignalHandler(mAddress
, this);
72 BluetoothDevice::~BluetoothDevice()
74 BluetoothService
* bs
= BluetoothService::Get();
75 // bs can be null on shutdown, where destruction might happen.
76 NS_ENSURE_TRUE_VOID(bs
);
77 bs
->UnregisterBluetoothSignalHandler(mAddress
, this);
82 BluetoothDevice::DisconnectFromOwner()
84 DOMEventTargetHelper::DisconnectFromOwner();
86 BluetoothService
* bs
= BluetoothService::Get();
87 NS_ENSURE_TRUE_VOID(bs
);
88 bs
->UnregisterBluetoothSignalHandler(mAddress
, this);
92 BluetoothDevice::Root()
95 mozilla::HoldJSObjects(this);
101 BluetoothDevice::Unroot()
105 mJsServices
= nullptr;
106 mozilla::DropJSObjects(this);
112 BluetoothDevice::SetPropertyByValue(const BluetoothNamedValue
& aValue
)
114 const nsString
& name
= aValue
.name();
115 const BluetoothValue
& value
= aValue
.value();
116 if (name
.EqualsLiteral("Name")) {
117 mName
= value
.get_nsString();
118 } else if (name
.EqualsLiteral("Path")) {
119 MOZ_ASSERT(value
.get_nsString().Length() > 0);
120 mPath
= value
.get_nsString();
121 } else if (name
.EqualsLiteral("Address")) {
122 mAddress
= value
.get_nsString();
123 } else if (name
.EqualsLiteral("Class")) {
124 mClass
= value
.get_uint32_t();
125 } else if (name
.EqualsLiteral("Icon")) {
126 mIcon
= value
.get_nsString();
127 } else if (name
.EqualsLiteral("Connected")) {
128 mConnected
= value
.get_bool();
129 } else if (name
.EqualsLiteral("Paired")) {
130 mPaired
= value
.get_bool();
131 } else if (name
.EqualsLiteral("UUIDs")) {
132 mUuids
= value
.get_ArrayOfnsString();
135 if (!jsapi
.Init(GetOwner())) {
136 BT_WARNING("Failed to initialise AutoJSAPI!");
139 JSContext
* cx
= jsapi
.cx();
140 JS::Rooted
<JSObject
*> uuids(cx
);
141 if (NS_FAILED(nsTArrayToJSArray(cx
, mUuids
, &uuids
))) {
142 BT_WARNING("Cannot set JS UUIDs object!");
147 } else if (name
.EqualsLiteral("Services")) {
148 mServices
= value
.get_ArrayOfnsString();
151 if (!jsapi
.Init(GetOwner())) {
152 BT_WARNING("Failed to initialise AutoJSAPI!");
155 JSContext
* cx
= jsapi
.cx();
156 JS::Rooted
<JSObject
*> services(cx
);
157 if (NS_FAILED(nsTArrayToJSArray(cx
, mServices
, &services
))) {
158 BT_WARNING("Cannot set JS Services object!");
161 mJsServices
= services
;
164 nsCString warningMsg
;
165 warningMsg
.AssignLiteral("Not handling device property: ");
166 warningMsg
.Append(NS_ConvertUTF16toUTF8(name
));
167 BT_WARNING(warningMsg
.get());
172 already_AddRefed
<BluetoothDevice
>
173 BluetoothDevice::Create(nsPIDOMWindow
* aWindow
,
174 const nsAString
& aAdapterPath
,
175 const BluetoothValue
& aValue
)
177 MOZ_ASSERT(NS_IsMainThread());
180 nsRefPtr
<BluetoothDevice
> device
=
181 new BluetoothDevice(aWindow
, aAdapterPath
, aValue
);
182 return device
.forget();
186 BluetoothDevice::Notify(const BluetoothSignal
& aData
)
188 BT_LOGD("[D] %s: %s", __FUNCTION__
, NS_ConvertUTF16toUTF8(aData
.name()).get());
190 BluetoothValue v
= aData
.value();
191 if (aData
.name().EqualsLiteral("PropertyChanged")) {
192 MOZ_ASSERT(v
.type() == BluetoothValue::TArrayOfBluetoothNamedValue
);
194 const InfallibleTArray
<BluetoothNamedValue
>& arr
=
195 v
.get_ArrayOfBluetoothNamedValue();
197 for (uint32_t i
= 0, propCount
= arr
.Length(); i
< propCount
; ++i
) {
198 SetPropertyByValue(arr
[i
]);
202 nsCString warningMsg
;
203 warningMsg
.AssignLiteral("Not handling device signal: ");
204 warningMsg
.Append(NS_ConvertUTF16toUTF8(aData
.name()));
205 BT_WARNING(warningMsg
.get());
211 BluetoothDevice::GetUuids(JSContext
* aContext
,
212 JS::MutableHandle
<JS::Value
> aUuids
,
216 BT_WARNING("UUIDs not yet set!");
217 aRv
.Throw(NS_ERROR_FAILURE
);
221 JS::ExposeObjectToActiveJS(mJsUuids
);
222 aUuids
.setObject(*mJsUuids
);
226 BluetoothDevice::GetServices(JSContext
* aCx
,
227 JS::MutableHandle
<JS::Value
> aServices
,
231 BT_WARNING("Services not yet set!");
232 aRv
.Throw(NS_ERROR_FAILURE
);
236 JS::ExposeObjectToActiveJS(mJsServices
);
237 aServices
.setObject(*mJsServices
);
241 BluetoothDevice::WrapObject(JSContext
* aContext
)
243 return BluetoothDeviceBinding::Wrap(aContext
, this);