Bumping manifests a=b2g-bump
[gecko.git] / dom / bluetooth / BluetoothDevice.cpp
blobee9b510eb7dcda7fdd25d7b9c283b7669e83302a
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,
24 DOMEventTargetHelper)
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,
30 DOMEventTargetHelper)
31 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
32 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
34 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothDevice,
35 DOMEventTargetHelper)
36 tmp->Unroot();
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)
50 , mJsUuids(nullptr)
51 , mJsServices(nullptr)
52 , mAdapterPath(aAdapterPath)
53 , mConnected(false)
54 , mPaired(false)
55 , mIsRooted(false)
57 MOZ_ASSERT(aWindow);
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);
76 Unroot();
79 void
80 BluetoothDevice::DisconnectFromOwner()
82 DOMEventTargetHelper::DisconnectFromOwner();
84 BluetoothService* bs = BluetoothService::Get();
85 NS_ENSURE_TRUE_VOID(bs);
86 bs->UnregisterBluetoothSignalHandler(mAddress, this);
89 void
90 BluetoothDevice::Root()
92 if (!mIsRooted) {
93 mozilla::HoldJSObjects(this);
94 mIsRooted = true;
98 void
99 BluetoothDevice::Unroot()
101 if (mIsRooted) {
102 mJsUuids = nullptr;
103 mJsServices = nullptr;
104 mozilla::DropJSObjects(this);
105 mIsRooted = false;
109 void
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();
132 AutoJSAPI jsapi;
133 if (!jsapi.Init(GetOwner())) {
134 BT_WARNING("Failed to initialise AutoJSAPI!");
135 return;
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!");
141 return;
143 mJsUuids = uuids;
144 Root();
145 } else if (name.EqualsLiteral("Services")) {
146 mServices = value.get_ArrayOfnsString();
148 AutoJSAPI jsapi;
149 if (!jsapi.Init(GetOwner())) {
150 BT_WARNING("Failed to initialise AutoJSAPI!");
151 return;
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!");
157 return;
159 mJsServices = services;
160 Root();
161 } else {
162 nsCString warningMsg;
163 warningMsg.AssignLiteral("Not handling device property: ");
164 warningMsg.Append(NS_ConvertUTF16toUTF8(name));
165 BT_WARNING(warningMsg.get());
169 // static
170 already_AddRefed<BluetoothDevice>
171 BluetoothDevice::Create(nsPIDOMWindow* aWindow,
172 const nsAString& aAdapterPath,
173 const BluetoothValue& aValue)
175 MOZ_ASSERT(NS_IsMainThread());
176 MOZ_ASSERT(aWindow);
178 nsRefPtr<BluetoothDevice> device =
179 new BluetoothDevice(aWindow, aAdapterPath, aValue);
180 return device.forget();
183 void
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]);
198 } else {
199 #ifdef DEBUG
200 nsCString warningMsg;
201 warningMsg.AssignLiteral("Not handling device signal: ");
202 warningMsg.Append(NS_ConvertUTF16toUTF8(aData.name()));
203 BT_WARNING(warningMsg.get());
204 #endif
208 void
209 BluetoothDevice::GetUuids(JSContext* aContext,
210 JS::MutableHandle<JS::Value> aUuids,
211 ErrorResult& aRv)
213 if (!mJsUuids) {
214 BT_WARNING("UUIDs not yet set!");
215 aRv.Throw(NS_ERROR_FAILURE);
216 return;
219 JS::ExposeObjectToActiveJS(mJsUuids);
220 aUuids.setObject(*mJsUuids);
223 void
224 BluetoothDevice::GetServices(JSContext* aCx,
225 JS::MutableHandle<JS::Value> aServices,
226 ErrorResult& aRv)
228 if (!mJsServices) {
229 BT_WARNING("Services not yet set!");
230 aRv.Throw(NS_ERROR_FAILURE);
231 return;
234 JS::ExposeObjectToActiveJS(mJsServices);
235 aServices.setObject(*mJsServices);
238 JSObject*
239 BluetoothDevice::WrapObject(JSContext* aContext)
241 return BluetoothDeviceBinding::Wrap(aContext, this);