Bumping manifests a=b2g-bump
[gecko.git] / dom / bluetooth / BluetoothDevice.cpp
blob07ade8bb49f12a2484affb4a9b4246e91455216e
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,
27 DOMEventTargetHelper)
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,
33 DOMEventTargetHelper)
34 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
35 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
37 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothDevice,
38 DOMEventTargetHelper)
39 tmp->Unroot();
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)
53 , mJsUuids(nullptr)
54 , mJsServices(nullptr)
55 , mAdapterPath(aAdapterPath)
56 , mIsRooted(false)
58 MOZ_ASSERT(aWindow);
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);
78 Unroot();
81 void
82 BluetoothDevice::DisconnectFromOwner()
84 DOMEventTargetHelper::DisconnectFromOwner();
86 BluetoothService* bs = BluetoothService::Get();
87 NS_ENSURE_TRUE_VOID(bs);
88 bs->UnregisterBluetoothSignalHandler(mAddress, this);
91 void
92 BluetoothDevice::Root()
94 if (!mIsRooted) {
95 mozilla::HoldJSObjects(this);
96 mIsRooted = true;
100 void
101 BluetoothDevice::Unroot()
103 if (mIsRooted) {
104 mJsUuids = nullptr;
105 mJsServices = nullptr;
106 mozilla::DropJSObjects(this);
107 mIsRooted = false;
111 void
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();
134 AutoJSAPI jsapi;
135 if (!jsapi.Init(GetOwner())) {
136 BT_WARNING("Failed to initialise AutoJSAPI!");
137 return;
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!");
143 return;
145 mJsUuids = uuids;
146 Root();
147 } else if (name.EqualsLiteral("Services")) {
148 mServices = value.get_ArrayOfnsString();
150 AutoJSAPI jsapi;
151 if (!jsapi.Init(GetOwner())) {
152 BT_WARNING("Failed to initialise AutoJSAPI!");
153 return;
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!");
159 return;
161 mJsServices = services;
162 Root();
163 } else {
164 nsCString warningMsg;
165 warningMsg.AssignLiteral("Not handling device property: ");
166 warningMsg.Append(NS_ConvertUTF16toUTF8(name));
167 BT_WARNING(warningMsg.get());
171 // static
172 already_AddRefed<BluetoothDevice>
173 BluetoothDevice::Create(nsPIDOMWindow* aWindow,
174 const nsAString& aAdapterPath,
175 const BluetoothValue& aValue)
177 MOZ_ASSERT(NS_IsMainThread());
178 MOZ_ASSERT(aWindow);
180 nsRefPtr<BluetoothDevice> device =
181 new BluetoothDevice(aWindow, aAdapterPath, aValue);
182 return device.forget();
185 void
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]);
200 } else {
201 #ifdef DEBUG
202 nsCString warningMsg;
203 warningMsg.AssignLiteral("Not handling device signal: ");
204 warningMsg.Append(NS_ConvertUTF16toUTF8(aData.name()));
205 BT_WARNING(warningMsg.get());
206 #endif
210 void
211 BluetoothDevice::GetUuids(JSContext* aContext,
212 JS::MutableHandle<JS::Value> aUuids,
213 ErrorResult& aRv)
215 if (!mJsUuids) {
216 BT_WARNING("UUIDs not yet set!");
217 aRv.Throw(NS_ERROR_FAILURE);
218 return;
221 JS::ExposeObjectToActiveJS(mJsUuids);
222 aUuids.setObject(*mJsUuids);
225 void
226 BluetoothDevice::GetServices(JSContext* aCx,
227 JS::MutableHandle<JS::Value> aServices,
228 ErrorResult& aRv)
230 if (!mJsServices) {
231 BT_WARNING("Services not yet set!");
232 aRv.Throw(NS_ERROR_FAILURE);
233 return;
236 JS::ExposeObjectToActiveJS(mJsServices);
237 aServices.setObject(*mJsServices);
240 JSObject*
241 BluetoothDevice::WrapObject(JSContext* aContext)
243 return BluetoothDeviceBinding::Wrap(aContext, this);