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 "nsTArrayHelpers.h"
15 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
16 #include "mozilla/dom/BluetoothDeviceBinding.h"
17 #include "mozilla/dom/ScriptSettings.h"
19 USING_BLUETOOTH_NAMESPACE
21 NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothDevice
)
23 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(BluetoothDevice
,
25 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mJsUuids
)
26 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mJsServices
)
27 NS_IMPL_CYCLE_COLLECTION_TRACE_END
29 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothDevice
,
31 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
32 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
34 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothDevice
,
37 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
39 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothDevice
)
40 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper
)
42 NS_IMPL_ADDREF_INHERITED(BluetoothDevice
, DOMEventTargetHelper
)
43 NS_IMPL_RELEASE_INHERITED(BluetoothDevice
, DOMEventTargetHelper
)
45 BluetoothDevice::BluetoothDevice(nsPIDOMWindow
* aWindow
,
46 const nsAString
& aAdapterPath
,
47 const BluetoothValue
& aValue
)
48 : DOMEventTargetHelper(aWindow
)
49 , BluetoothPropertyContainer(BluetoothObjectType::TYPE_DEVICE
)
51 , mJsServices(nullptr)
52 , mAdapterPath(aAdapterPath
)
59 const InfallibleTArray
<BluetoothNamedValue
>& values
=
60 aValue
.get_ArrayOfBluetoothNamedValue();
61 for (uint32_t i
= 0; i
< values
.Length(); ++i
) {
62 SetPropertyByValue(values
[i
]);
65 BluetoothService
* bs
= BluetoothService::Get();
66 NS_ENSURE_TRUE_VOID(bs
);
67 bs
->RegisterBluetoothSignalHandler(mAddress
, this);
70 BluetoothDevice::~BluetoothDevice()
72 BluetoothService
* bs
= BluetoothService::Get();
73 // bs can be null on shutdown, where destruction might happen.
74 NS_ENSURE_TRUE_VOID(bs
);
75 bs
->UnregisterBluetoothSignalHandler(mAddress
, this);
80 BluetoothDevice::DisconnectFromOwner()
82 DOMEventTargetHelper::DisconnectFromOwner();
84 BluetoothService
* bs
= BluetoothService::Get();
85 NS_ENSURE_TRUE_VOID(bs
);
86 bs
->UnregisterBluetoothSignalHandler(mAddress
, this);
90 BluetoothDevice::Root()
93 mozilla::HoldJSObjects(this);
99 BluetoothDevice::Unroot()
103 mJsServices
= nullptr;
104 mozilla::DropJSObjects(this);
110 BluetoothDevice::SetPropertyByValue(const BluetoothNamedValue
& aValue
)
112 const nsString
& name
= aValue
.name();
113 const BluetoothValue
& value
= aValue
.value();
114 if (name
.EqualsLiteral("Name")) {
115 mName
= value
.get_nsString();
116 } else if (name
.EqualsLiteral("Path")) {
117 MOZ_ASSERT(value
.get_nsString().Length() > 0);
118 mPath
= value
.get_nsString();
119 } else if (name
.EqualsLiteral("Address")) {
120 mAddress
= value
.get_nsString();
121 } else if (name
.EqualsLiteral("Class")) {
122 mClass
= value
.get_uint32_t();
123 } else if (name
.EqualsLiteral("Icon")) {
124 mIcon
= value
.get_nsString();
125 } else if (name
.EqualsLiteral("Connected")) {
126 mConnected
= value
.get_bool();
127 } else if (name
.EqualsLiteral("Paired")) {
128 mPaired
= value
.get_bool();
129 } else if (name
.EqualsLiteral("UUIDs")) {
130 mUuids
= value
.get_ArrayOfnsString();
133 if (!jsapi
.Init(GetOwner())) {
134 BT_WARNING("Failed to initialise AutoJSAPI!");
137 JSContext
* cx
= jsapi
.cx();
138 JS::Rooted
<JSObject
*> uuids(cx
);
139 if (NS_FAILED(nsTArrayToJSArray(cx
, mUuids
, &uuids
))) {
140 BT_WARNING("Cannot set JS UUIDs object!");
145 } else if (name
.EqualsLiteral("Services")) {
146 mServices
= value
.get_ArrayOfnsString();
149 if (!jsapi
.Init(GetOwner())) {
150 BT_WARNING("Failed to initialise AutoJSAPI!");
153 JSContext
* cx
= jsapi
.cx();
154 JS::Rooted
<JSObject
*> services(cx
);
155 if (NS_FAILED(nsTArrayToJSArray(cx
, mServices
, &services
))) {
156 BT_WARNING("Cannot set JS Services object!");
159 mJsServices
= services
;
162 nsCString warningMsg
;
163 warningMsg
.AssignLiteral("Not handling device property: ");
164 warningMsg
.Append(NS_ConvertUTF16toUTF8(name
));
165 BT_WARNING(warningMsg
.get());
170 already_AddRefed
<BluetoothDevice
>
171 BluetoothDevice::Create(nsPIDOMWindow
* aWindow
,
172 const nsAString
& aAdapterPath
,
173 const BluetoothValue
& aValue
)
175 MOZ_ASSERT(NS_IsMainThread());
178 nsRefPtr
<BluetoothDevice
> device
=
179 new BluetoothDevice(aWindow
, aAdapterPath
, aValue
);
180 return device
.forget();
184 BluetoothDevice::Notify(const BluetoothSignal
& aData
)
186 BT_LOGD("[D] %s: %s", __FUNCTION__
, NS_ConvertUTF16toUTF8(aData
.name()).get());
188 BluetoothValue v
= aData
.value();
189 if (aData
.name().EqualsLiteral("PropertyChanged")) {
190 MOZ_ASSERT(v
.type() == BluetoothValue::TArrayOfBluetoothNamedValue
);
192 const InfallibleTArray
<BluetoothNamedValue
>& arr
=
193 v
.get_ArrayOfBluetoothNamedValue();
195 for (uint32_t i
= 0, propCount
= arr
.Length(); i
< propCount
; ++i
) {
196 SetPropertyByValue(arr
[i
]);
200 nsCString warningMsg
;
201 warningMsg
.AssignLiteral("Not handling device signal: ");
202 warningMsg
.Append(NS_ConvertUTF16toUTF8(aData
.name()));
203 BT_WARNING(warningMsg
.get());
209 BluetoothDevice::GetUuids(JSContext
* aContext
,
210 JS::MutableHandle
<JS::Value
> aUuids
,
214 BT_WARNING("UUIDs not yet set!");
215 aRv
.Throw(NS_ERROR_FAILURE
);
219 JS::ExposeObjectToActiveJS(mJsUuids
);
220 aUuids
.setObject(*mJsUuids
);
224 BluetoothDevice::GetServices(JSContext
* aCx
,
225 JS::MutableHandle
<JS::Value
> aServices
,
229 BT_WARNING("Services not yet set!");
230 aRv
.Throw(NS_ERROR_FAILURE
);
234 JS::ExposeObjectToActiveJS(mJsServices
);
235 aServices
.setObject(*mJsServices
);
239 BluetoothDevice::WrapObject(JSContext
* aContext
)
241 return BluetoothDeviceBinding::Wrap(aContext
, this);