dom/bluetooth/BluetoothDevice.cpp

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:9f2cbed9214b
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/. */
6
7 #include "base/basictypes.h"
8 #include "BluetoothDevice.h"
9 #include "BluetoothReplyRunnable.h"
10 #include "BluetoothService.h"
11 #include "BluetoothUtils.h"
12
13 #include "nsDOMClassInfo.h"
14 #include "nsTArrayHelpers.h"
15
16 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
17 #include "mozilla/dom/BluetoothDeviceBinding.h"
18
19 USING_BLUETOOTH_NAMESPACE
20
21 DOMCI_DATA(BluetoothDevice, BluetoothDevice)
22
23 NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothDevice)
24
25 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(BluetoothDevice,
26 DOMEventTargetHelper)
27 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mJsUuids)
28 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mJsServices)
29 NS_IMPL_CYCLE_COLLECTION_TRACE_END
30
31 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothDevice,
32 DOMEventTargetHelper)
33 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
34 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
35
36 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothDevice,
37 DOMEventTargetHelper)
38 tmp->Unroot();
39 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
40
41 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothDevice)
42 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
43
44 NS_IMPL_ADDREF_INHERITED(BluetoothDevice, DOMEventTargetHelper)
45 NS_IMPL_RELEASE_INHERITED(BluetoothDevice, DOMEventTargetHelper)
46
47 BluetoothDevice::BluetoothDevice(nsPIDOMWindow* aWindow,
48 const nsAString& aAdapterPath,
49 const BluetoothValue& aValue)
50 : DOMEventTargetHelper(aWindow)
51 , BluetoothPropertyContainer(BluetoothObjectType::TYPE_DEVICE)
52 , mJsUuids(nullptr)
53 , mJsServices(nullptr)
54 , mAdapterPath(aAdapterPath)
55 , mIsRooted(false)
56 {
57 MOZ_ASSERT(aWindow);
58 MOZ_ASSERT(IsDOMBinding());
59
60 const InfallibleTArray<BluetoothNamedValue>& values =
61 aValue.get_ArrayOfBluetoothNamedValue();
62 for (uint32_t i = 0; i < values.Length(); ++i) {
63 SetPropertyByValue(values[i]);
64 }
65
66 BluetoothService* bs = BluetoothService::Get();
67 NS_ENSURE_TRUE_VOID(bs);
68 bs->RegisterBluetoothSignalHandler(mAddress, this);
69 }
70
71 BluetoothDevice::~BluetoothDevice()
72 {
73 BluetoothService* bs = BluetoothService::Get();
74 // bs can be null on shutdown, where destruction might happen.
75 NS_ENSURE_TRUE_VOID(bs);
76 bs->UnregisterBluetoothSignalHandler(mAddress, this);
77 Unroot();
78 }
79
80 void
81 BluetoothDevice::DisconnectFromOwner()
82 {
83 DOMEventTargetHelper::DisconnectFromOwner();
84
85 BluetoothService* bs = BluetoothService::Get();
86 NS_ENSURE_TRUE_VOID(bs);
87 bs->UnregisterBluetoothSignalHandler(mAddress, this);
88 }
89
90 void
91 BluetoothDevice::Root()
92 {
93 if (!mIsRooted) {
94 mozilla::HoldJSObjects(this);
95 mIsRooted = true;
96 }
97 }
98
99 void
100 BluetoothDevice::Unroot()
101 {
102 if (mIsRooted) {
103 mJsUuids = nullptr;
104 mJsServices = nullptr;
105 mozilla::DropJSObjects(this);
106 mIsRooted = false;
107 }
108 }
109
110 void
111 BluetoothDevice::SetPropertyByValue(const BluetoothNamedValue& aValue)
112 {
113 const nsString& name = aValue.name();
114 const BluetoothValue& value = aValue.value();
115 if (name.EqualsLiteral("Name")) {
116 mName = value.get_nsString();
117 } else if (name.EqualsLiteral("Path")) {
118 MOZ_ASSERT(value.get_nsString().Length() > 0);
119 mPath = value.get_nsString();
120 } else if (name.EqualsLiteral("Address")) {
121 mAddress = value.get_nsString();
122 } else if (name.EqualsLiteral("Class")) {
123 mClass = value.get_uint32_t();
124 } else if (name.EqualsLiteral("Icon")) {
125 mIcon = value.get_nsString();
126 } else if (name.EqualsLiteral("Connected")) {
127 mConnected = value.get_bool();
128 } else if (name.EqualsLiteral("Paired")) {
129 mPaired = value.get_bool();
130 } else if (name.EqualsLiteral("UUIDs")) {
131 mUuids = value.get_ArrayOfnsString();
132 nsresult rv;
133 nsIScriptContext* sc = GetContextForEventHandlers(&rv);
134 NS_ENSURE_SUCCESS_VOID(rv);
135 NS_ENSURE_TRUE_VOID(sc);
136
137 AutoPushJSContext cx(sc->GetNativeContext());
138
139 JS::Rooted<JSObject*> uuids(cx);
140 if (NS_FAILED(nsTArrayToJSArray(cx, mUuids, uuids.address()))) {
141 BT_WARNING("Cannot set JS UUIDs object!");
142 return;
143 }
144 mJsUuids = uuids;
145 Root();
146 } else if (name.EqualsLiteral("Services")) {
147 mServices = value.get_ArrayOfnsString();
148 nsresult rv;
149 nsIScriptContext* sc = GetContextForEventHandlers(&rv);
150 NS_ENSURE_SUCCESS_VOID(rv);
151 NS_ENSURE_TRUE_VOID(sc);
152
153 AutoPushJSContext cx(sc->GetNativeContext());
154
155 JS::Rooted<JSObject*> services(cx);
156 if (NS_FAILED(nsTArrayToJSArray(cx, mServices, services.address()))) {
157 BT_WARNING("Cannot set JS Services object!");
158 return;
159 }
160 mJsServices = services;
161 Root();
162 } else {
163 nsCString warningMsg;
164 warningMsg.AssignLiteral("Not handling device property: ");
165 warningMsg.Append(NS_ConvertUTF16toUTF8(name));
166 BT_WARNING(warningMsg.get());
167 }
168 }
169
170 // static
171 already_AddRefed<BluetoothDevice>
172 BluetoothDevice::Create(nsPIDOMWindow* aWindow,
173 const nsAString& aAdapterPath,
174 const BluetoothValue& aValue)
175 {
176 MOZ_ASSERT(NS_IsMainThread());
177 MOZ_ASSERT(aWindow);
178
179 nsRefPtr<BluetoothDevice> device =
180 new BluetoothDevice(aWindow, aAdapterPath, aValue);
181 return device.forget();
182 }
183
184 void
185 BluetoothDevice::Notify(const BluetoothSignal& aData)
186 {
187 BT_LOGD("[D] %s: %s", __FUNCTION__, NS_ConvertUTF16toUTF8(aData.name()).get());
188
189 BluetoothValue v = aData.value();
190 if (aData.name().EqualsLiteral("PropertyChanged")) {
191 MOZ_ASSERT(v.type() == BluetoothValue::TArrayOfBluetoothNamedValue);
192
193 const InfallibleTArray<BluetoothNamedValue>& arr =
194 v.get_ArrayOfBluetoothNamedValue();
195
196 for (uint32_t i = 0, propCount = arr.Length(); i < propCount; ++i) {
197 SetPropertyByValue(arr[i]);
198 }
199 } else {
200 #ifdef DEBUG
201 nsCString warningMsg;
202 warningMsg.AssignLiteral("Not handling device signal: ");
203 warningMsg.Append(NS_ConvertUTF16toUTF8(aData.name()));
204 BT_WARNING(warningMsg.get());
205 #endif
206 }
207 }
208
209 void
210 BluetoothDevice::GetUuids(JSContext* aContext,
211 JS::MutableHandle<JS::Value> aUuids,
212 ErrorResult& aRv)
213 {
214 if (!mJsUuids) {
215 BT_WARNING("UUIDs not yet set!");
216 aRv.Throw(NS_ERROR_FAILURE);
217 return;
218 }
219
220 JS::ExposeObjectToActiveJS(mJsUuids);
221 aUuids.setObject(*mJsUuids);
222 }
223
224 void
225 BluetoothDevice::GetServices(JSContext* aCx,
226 JS::MutableHandle<JS::Value> aServices,
227 ErrorResult& aRv)
228 {
229 if (!mJsServices) {
230 BT_WARNING("Services not yet set!");
231 aRv.Throw(NS_ERROR_FAILURE);
232 return;
233 }
234
235 JS::ExposeObjectToActiveJS(mJsServices);
236 aServices.setObject(*mJsServices);
237 }
238
239 JSObject*
240 BluetoothDevice::WrapObject(JSContext* aContext)
241 {
242 return BluetoothDeviceBinding::Wrap(aContext, this);
243 }

mercurial