dom/bluetooth/BluetoothAdapter.cpp

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:539c182149d6
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 "nsCxPusher.h"
9 #include "nsDOMClassInfo.h"
10 #include "nsTArrayHelpers.h"
11 #include "DOMRequest.h"
12 #include "nsThreadUtils.h"
13
14 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
15 #include "mozilla/dom/BluetoothAdapterBinding.h"
16 #include "mozilla/dom/BluetoothDeviceEvent.h"
17 #include "mozilla/dom/BluetoothStatusChangedEvent.h"
18 #include "mozilla/dom/ContentChild.h"
19 #include "mozilla/LazyIdleThread.h"
20
21 #include "BluetoothAdapter.h"
22 #include "BluetoothDevice.h"
23 #include "BluetoothReplyRunnable.h"
24 #include "BluetoothService.h"
25 #include "BluetoothUtils.h"
26
27 using namespace mozilla;
28 using namespace mozilla::dom;
29
30 USING_BLUETOOTH_NAMESPACE
31
32 NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothAdapter)
33
34 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(BluetoothAdapter,
35 DOMEventTargetHelper)
36 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mJsUuids)
37 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mJsDeviceAddresses)
38 NS_IMPL_CYCLE_COLLECTION_TRACE_END
39
40 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothAdapter,
41 DOMEventTargetHelper)
42 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
43 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
44
45 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothAdapter,
46 DOMEventTargetHelper)
47 tmp->Unroot();
48 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
49
50 // QueryInterface implementation for BluetoothAdapter
51 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothAdapter)
52 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
53
54 NS_IMPL_ADDREF_INHERITED(BluetoothAdapter, DOMEventTargetHelper)
55 NS_IMPL_RELEASE_INHERITED(BluetoothAdapter, DOMEventTargetHelper)
56
57 class GetDevicesTask : public BluetoothReplyRunnable
58 {
59 public:
60 GetDevicesTask(BluetoothAdapter* aAdapterPtr,
61 nsIDOMDOMRequest* aReq) :
62 BluetoothReplyRunnable(aReq),
63 mAdapterPtr(aAdapterPtr)
64 {
65 MOZ_ASSERT(aReq && aAdapterPtr);
66 }
67
68 virtual bool ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue)
69 {
70 aValue.setUndefined();
71
72 const BluetoothValue& v = mReply->get_BluetoothReplySuccess().value();
73 if (v.type() != BluetoothValue::TArrayOfBluetoothNamedValue) {
74 BT_WARNING("Not a BluetoothNamedValue array!");
75 SetError(NS_LITERAL_STRING("BluetoothReplyTypeError"));
76 return false;
77 }
78
79 const InfallibleTArray<BluetoothNamedValue>& values =
80 v.get_ArrayOfBluetoothNamedValue();
81
82 nsTArray<nsRefPtr<BluetoothDevice> > devices;
83 for (uint32_t i = 0; i < values.Length(); i++) {
84 const BluetoothValue properties = values[i].value();
85 if (properties.type() != BluetoothValue::TArrayOfBluetoothNamedValue) {
86 BT_WARNING("Not a BluetoothNamedValue array!");
87 SetError(NS_LITERAL_STRING("BluetoothReplyTypeError"));
88 return false;
89 }
90 nsRefPtr<BluetoothDevice> d =
91 BluetoothDevice::Create(mAdapterPtr->GetOwner(),
92 mAdapterPtr->GetPath(),
93 properties);
94 devices.AppendElement(d);
95 }
96
97 nsresult rv;
98 nsIScriptContext* sc = mAdapterPtr->GetContextForEventHandlers(&rv);
99 if (!sc) {
100 BT_WARNING("Cannot create script context!");
101 SetError(NS_LITERAL_STRING("BluetoothScriptContextError"));
102 return false;
103 }
104
105 AutoPushJSContext cx(sc->GetNativeContext());
106 JSObject* JsDevices = nullptr;
107 rv = nsTArrayToJSArray(cx, devices, &JsDevices);
108 if (!JsDevices) {
109 BT_WARNING("Cannot create JS array!");
110 SetError(NS_LITERAL_STRING("BluetoothError"));
111 return false;
112 }
113
114 aValue.setObject(*JsDevices);
115 return true;
116 }
117
118 void
119 ReleaseMembers()
120 {
121 BluetoothReplyRunnable::ReleaseMembers();
122 mAdapterPtr = nullptr;
123 }
124 private:
125 nsRefPtr<BluetoothAdapter> mAdapterPtr;
126 };
127
128 class GetScoConnectionStatusTask : public BluetoothReplyRunnable
129 {
130 public:
131 GetScoConnectionStatusTask(nsIDOMDOMRequest* aReq) :
132 BluetoothReplyRunnable(aReq)
133 {
134 MOZ_ASSERT(aReq);
135 }
136
137 virtual bool ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue)
138 {
139 aValue.setUndefined();
140
141 const BluetoothValue& v = mReply->get_BluetoothReplySuccess().value();
142 if (v.type() != BluetoothValue::Tbool) {
143 BT_WARNING("Not a boolean!");
144 SetError(NS_LITERAL_STRING("BluetoothReplyTypeError"));
145 return false;
146 }
147
148 aValue.setBoolean(v.get_bool());
149 return true;
150 }
151
152 void
153 ReleaseMembers()
154 {
155 BluetoothReplyRunnable::ReleaseMembers();
156 }
157 };
158
159 static int kCreatePairedDeviceTimeout = 50000; // unit: msec
160
161 BluetoothAdapter::BluetoothAdapter(nsPIDOMWindow* aWindow,
162 const BluetoothValue& aValue)
163 : DOMEventTargetHelper(aWindow)
164 , BluetoothPropertyContainer(BluetoothObjectType::TYPE_ADAPTER)
165 , mJsUuids(nullptr)
166 , mJsDeviceAddresses(nullptr)
167 , mDiscoverable(false)
168 , mDiscovering(false)
169 , mPairable(false)
170 , mPowered(false)
171 , mIsRooted(false)
172 {
173 MOZ_ASSERT(aWindow);
174 MOZ_ASSERT(IsDOMBinding());
175
176 const InfallibleTArray<BluetoothNamedValue>& values =
177 aValue.get_ArrayOfBluetoothNamedValue();
178 for (uint32_t i = 0; i < values.Length(); ++i) {
179 SetPropertyByValue(values[i]);
180 }
181
182 BluetoothService* bs = BluetoothService::Get();
183 NS_ENSURE_TRUE_VOID(bs);
184 bs->RegisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_ADAPTER), this);
185 }
186
187 BluetoothAdapter::~BluetoothAdapter()
188 {
189 Unroot();
190 BluetoothService* bs = BluetoothService::Get();
191 // We can be null on shutdown, where this might happen
192 NS_ENSURE_TRUE_VOID(bs);
193 bs->UnregisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_ADAPTER), this);
194 }
195
196 void
197 BluetoothAdapter::DisconnectFromOwner()
198 {
199 DOMEventTargetHelper::DisconnectFromOwner();
200
201 BluetoothService* bs = BluetoothService::Get();
202 NS_ENSURE_TRUE_VOID(bs);
203 bs->UnregisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_ADAPTER), this);
204 }
205
206 void
207 BluetoothAdapter::Unroot()
208 {
209 if (!mIsRooted) {
210 return;
211 }
212 mJsUuids = nullptr;
213 mJsDeviceAddresses = nullptr;
214 mozilla::DropJSObjects(this);
215 mIsRooted = false;
216 }
217
218 void
219 BluetoothAdapter::Root()
220 {
221 if (mIsRooted) {
222 return;
223 }
224 mozilla::HoldJSObjects(this);
225 mIsRooted = true;
226 }
227
228 void
229 BluetoothAdapter::SetPropertyByValue(const BluetoothNamedValue& aValue)
230 {
231 const nsString& name = aValue.name();
232 const BluetoothValue& value = aValue.value();
233 if (name.EqualsLiteral("Name")) {
234 mName = value.get_nsString();
235 } else if (name.EqualsLiteral("Address")) {
236 mAddress = value.get_nsString();
237 } else if (name.EqualsLiteral("Path")) {
238 mPath = value.get_nsString();
239 } else if (name.EqualsLiteral("Discoverable")) {
240 mDiscoverable = value.get_bool();
241 } else if (name.EqualsLiteral("Discovering")) {
242 mDiscovering = value.get_bool();
243 } else if (name.EqualsLiteral("Pairable")) {
244 mPairable = value.get_bool();
245 } else if (name.EqualsLiteral("Powered")) {
246 mPowered = value.get_bool();
247 } else if (name.EqualsLiteral("PairableTimeout")) {
248 mPairableTimeout = value.get_uint32_t();
249 } else if (name.EqualsLiteral("DiscoverableTimeout")) {
250 mDiscoverableTimeout = value.get_uint32_t();
251 } else if (name.EqualsLiteral("Class")) {
252 mClass = value.get_uint32_t();
253 } else if (name.EqualsLiteral("UUIDs")) {
254 mUuids = value.get_ArrayOfnsString();
255 nsresult rv;
256 nsIScriptContext* sc = GetContextForEventHandlers(&rv);
257 NS_ENSURE_SUCCESS_VOID(rv);
258 NS_ENSURE_TRUE_VOID(sc);
259
260 AutoPushJSContext cx(sc->GetNativeContext());
261 JS::Rooted<JSObject*> uuids(cx);
262 if (NS_FAILED(nsTArrayToJSArray(cx, mUuids, uuids.address()))) {
263 BT_WARNING("Cannot set JS UUIDs object!");
264 return;
265 }
266 mJsUuids = uuids;
267 Root();
268 } else if (name.EqualsLiteral("Devices")) {
269 mDeviceAddresses = value.get_ArrayOfnsString();
270
271 nsresult rv;
272 nsIScriptContext* sc = GetContextForEventHandlers(&rv);
273 NS_ENSURE_SUCCESS_VOID(rv);
274 NS_ENSURE_TRUE_VOID(sc);
275
276 AutoPushJSContext cx(sc->GetNativeContext());
277 JS::Rooted<JSObject*> deviceAddresses(cx);
278 if (NS_FAILED(nsTArrayToJSArray(cx, mDeviceAddresses,
279 deviceAddresses.address()))) {
280 BT_WARNING("Cannot set JS Devices object!");
281 return;
282 }
283 mJsDeviceAddresses = deviceAddresses;
284 Root();
285 } else {
286 #ifdef DEBUG
287 nsCString warningMsg;
288 warningMsg.AssignLiteral("Not handling adapter property: ");
289 warningMsg.Append(NS_ConvertUTF16toUTF8(name));
290 BT_WARNING(warningMsg.get());
291 #endif
292 }
293 }
294
295 // static
296 already_AddRefed<BluetoothAdapter>
297 BluetoothAdapter::Create(nsPIDOMWindow* aWindow, const BluetoothValue& aValue)
298 {
299 MOZ_ASSERT(NS_IsMainThread());
300 MOZ_ASSERT(aWindow);
301
302 nsRefPtr<BluetoothAdapter> adapter = new BluetoothAdapter(aWindow, aValue);
303 return adapter.forget();
304 }
305
306 void
307 BluetoothAdapter::Notify(const BluetoothSignal& aData)
308 {
309 InfallibleTArray<BluetoothNamedValue> arr;
310
311 BT_LOGD("[A] %s: %s", __FUNCTION__, NS_ConvertUTF16toUTF8(aData.name()).get());
312
313 BluetoothValue v = aData.value();
314 if (aData.name().EqualsLiteral("DeviceFound")) {
315 nsRefPtr<BluetoothDevice> device = BluetoothDevice::Create(GetOwner(), mPath, aData.value());
316
317 BluetoothDeviceEventInit init;
318 init.mBubbles = false;
319 init.mCancelable = false;
320 init.mDevice = device;
321 nsRefPtr<BluetoothDeviceEvent> event =
322 BluetoothDeviceEvent::Constructor(this, NS_LITERAL_STRING("devicefound"), init);
323 DispatchTrustedEvent(event);
324 } else if (aData.name().EqualsLiteral("PropertyChanged")) {
325 MOZ_ASSERT(v.type() == BluetoothValue::TArrayOfBluetoothNamedValue);
326
327 const InfallibleTArray<BluetoothNamedValue>& arr =
328 v.get_ArrayOfBluetoothNamedValue();
329
330 for (uint32_t i = 0, propCount = arr.Length(); i < propCount; ++i) {
331 SetPropertyByValue(arr[i]);
332 }
333 } else if (aData.name().EqualsLiteral(PAIRED_STATUS_CHANGED_ID) ||
334 aData.name().EqualsLiteral(HFP_STATUS_CHANGED_ID) ||
335 aData.name().EqualsLiteral(SCO_STATUS_CHANGED_ID) ||
336 aData.name().EqualsLiteral(A2DP_STATUS_CHANGED_ID)) {
337 MOZ_ASSERT(v.type() == BluetoothValue::TArrayOfBluetoothNamedValue);
338 const InfallibleTArray<BluetoothNamedValue>& arr =
339 v.get_ArrayOfBluetoothNamedValue();
340
341 MOZ_ASSERT(arr.Length() == 2 &&
342 arr[0].value().type() == BluetoothValue::TnsString &&
343 arr[1].value().type() == BluetoothValue::Tbool);
344 nsString address = arr[0].value().get_nsString();
345 bool status = arr[1].value().get_bool();
346
347 BluetoothStatusChangedEventInit init;
348 init.mBubbles = false;
349 init.mCancelable = false;
350 init.mAddress = address;
351 init.mStatus = status;
352 nsRefPtr<BluetoothStatusChangedEvent> event =
353 BluetoothStatusChangedEvent::Constructor(this, aData.name(), init);
354 DispatchTrustedEvent(event);
355 } else if (aData.name().EqualsLiteral(REQUEST_MEDIA_PLAYSTATUS_ID)) {
356 nsCOMPtr<nsIDOMEvent> event;
357 nsresult rv = NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr);
358 NS_ENSURE_SUCCESS_VOID(rv);
359
360 rv = event->InitEvent(aData.name(), false, false);
361 NS_ENSURE_SUCCESS_VOID(rv);
362
363 DispatchTrustedEvent(event);
364 } else {
365 #ifdef DEBUG
366 nsCString warningMsg;
367 warningMsg.AssignLiteral("Not handling adapter signal: ");
368 warningMsg.Append(NS_ConvertUTF16toUTF8(aData.name()));
369 BT_WARNING(warningMsg.get());
370 #endif
371 }
372 }
373
374 already_AddRefed<DOMRequest>
375 BluetoothAdapter::StartStopDiscovery(bool aStart, ErrorResult& aRv)
376 {
377 nsCOMPtr<nsPIDOMWindow> win = GetOwner();
378 if (!win) {
379 aRv.Throw(NS_ERROR_FAILURE);
380 return nullptr;
381 }
382
383 nsRefPtr<DOMRequest> request = new DOMRequest(win);
384 nsRefPtr<BluetoothVoidReplyRunnable> results =
385 new BluetoothVoidReplyRunnable(request);
386
387 BluetoothService* bs = BluetoothService::Get();
388 if (!bs) {
389 aRv.Throw(NS_ERROR_FAILURE);
390 return nullptr;
391 }
392 nsresult rv;
393 if (aStart) {
394 rv = bs->StartDiscoveryInternal(results);
395 } else {
396 rv = bs->StopDiscoveryInternal(results);
397 }
398 if (NS_FAILED(rv)) {
399 BT_WARNING("Start/Stop Discovery failed!");
400 aRv.Throw(rv);
401 return nullptr;
402 }
403
404 // mDiscovering is not set here, we'll get a Property update from our external
405 // protocol to tell us that it's been set.
406
407 return request.forget();
408 }
409
410 already_AddRefed<DOMRequest>
411 BluetoothAdapter::StartDiscovery(ErrorResult& aRv)
412 {
413 return StartStopDiscovery(true, aRv);
414 }
415
416 already_AddRefed<DOMRequest>
417 BluetoothAdapter::StopDiscovery(ErrorResult& aRv)
418 {
419 return StartStopDiscovery(false, aRv);
420 }
421
422 void
423 BluetoothAdapter::GetDevices(JSContext* aContext,
424 JS::MutableHandle<JS::Value> aDevices,
425 ErrorResult& aRv)
426 {
427 if (!mJsDeviceAddresses) {
428 BT_WARNING("Devices not yet set!\n");
429 aRv.Throw(NS_ERROR_FAILURE);
430 return;
431 }
432
433 JS::ExposeObjectToActiveJS(mJsDeviceAddresses);
434 aDevices.setObject(*mJsDeviceAddresses);
435 }
436
437 void
438 BluetoothAdapter::GetUuids(JSContext* aContext,
439 JS::MutableHandle<JS::Value> aUuids,
440 ErrorResult& aRv)
441 {
442 if (!mJsUuids) {
443 BT_WARNING("UUIDs not yet set!\n");
444 aRv.Throw(NS_ERROR_FAILURE);
445 return;
446 }
447
448 JS::ExposeObjectToActiveJS(mJsUuids);
449 aUuids.setObject(*mJsUuids);
450 }
451
452 already_AddRefed<DOMRequest>
453 BluetoothAdapter::SetName(const nsAString& aName, ErrorResult& aRv)
454 {
455 if (mName.Equals(aName)) {
456 return FirePropertyAlreadySet(GetOwner(), aRv);
457 }
458 nsString name(aName);
459 BluetoothValue value(name);
460 BluetoothNamedValue property(NS_LITERAL_STRING("Name"), value);
461 return SetProperty(GetOwner(), property, aRv);
462 }
463
464 already_AddRefed<DOMRequest>
465 BluetoothAdapter::SetDiscoverable(bool aDiscoverable, ErrorResult& aRv)
466 {
467 if (aDiscoverable == mDiscoverable) {
468 return FirePropertyAlreadySet(GetOwner(), aRv);
469 }
470 BluetoothValue value(aDiscoverable);
471 BluetoothNamedValue property(NS_LITERAL_STRING("Discoverable"), value);
472 return SetProperty(GetOwner(), property, aRv);
473 }
474
475 already_AddRefed<DOMRequest>
476 BluetoothAdapter::SetDiscoverableTimeout(uint32_t aDiscoverableTimeout, ErrorResult& aRv)
477 {
478 if (aDiscoverableTimeout == mDiscoverableTimeout) {
479 return FirePropertyAlreadySet(GetOwner(), aRv);
480 }
481 BluetoothValue value(aDiscoverableTimeout);
482 BluetoothNamedValue property(NS_LITERAL_STRING("DiscoverableTimeout"), value);
483 return SetProperty(GetOwner(), property, aRv);
484 }
485
486 already_AddRefed<DOMRequest>
487 BluetoothAdapter::GetConnectedDevices(uint16_t aServiceUuid, ErrorResult& aRv)
488 {
489 MOZ_ASSERT(NS_IsMainThread());
490
491 nsCOMPtr<nsPIDOMWindow> win = GetOwner();
492 if (!win) {
493 aRv.Throw(NS_ERROR_FAILURE);
494 return nullptr;
495 }
496
497 nsRefPtr<DOMRequest> request = new DOMRequest(win);
498 nsRefPtr<BluetoothReplyRunnable> results =
499 new GetDevicesTask(this, request);
500
501 BluetoothService* bs = BluetoothService::Get();
502 if (!bs) {
503 aRv.Throw(NS_ERROR_FAILURE);
504 return nullptr;
505 }
506 nsresult rv = bs->GetConnectedDevicePropertiesInternal(aServiceUuid, results);
507 if (NS_FAILED(rv)) {
508 aRv.Throw(rv);
509 return nullptr;
510 }
511
512 return request.forget();
513 }
514
515 already_AddRefed<DOMRequest>
516 BluetoothAdapter::GetPairedDevices(ErrorResult& aRv)
517 {
518 nsCOMPtr<nsPIDOMWindow> win = GetOwner();
519 if (!win) {
520 aRv.Throw(NS_ERROR_FAILURE);
521 return nullptr;
522 }
523
524 nsRefPtr<DOMRequest> request = new DOMRequest(win);
525 nsRefPtr<BluetoothReplyRunnable> results =
526 new GetDevicesTask(this, request);
527
528 BluetoothService* bs = BluetoothService::Get();
529 if (!bs) {
530 aRv.Throw(NS_ERROR_FAILURE);
531 return nullptr;
532 }
533 nsresult rv = bs->GetPairedDevicePropertiesInternal(mDeviceAddresses, results);
534 if (NS_FAILED(rv)) {
535 aRv.Throw(rv);
536 return nullptr;
537 }
538
539 return request.forget();
540 }
541
542 already_AddRefed<DOMRequest>
543 BluetoothAdapter::PairUnpair(bool aPair, const nsAString& aDeviceAddress,
544 ErrorResult& aRv)
545 {
546 nsCOMPtr<nsPIDOMWindow> win = GetOwner();
547 if (!win) {
548 aRv.Throw(NS_ERROR_FAILURE);
549 return nullptr;
550 }
551
552 nsRefPtr<DOMRequest> request = new DOMRequest(win);
553 nsRefPtr<BluetoothVoidReplyRunnable> results =
554 new BluetoothVoidReplyRunnable(request);
555
556 BluetoothService* bs = BluetoothService::Get();
557 if (!bs) {
558 aRv.Throw(NS_ERROR_FAILURE);
559 return nullptr;
560 }
561 nsresult rv;
562 if (aPair) {
563 rv = bs->CreatePairedDeviceInternal(aDeviceAddress,
564 kCreatePairedDeviceTimeout,
565 results);
566 } else {
567 rv = bs->RemoveDeviceInternal(aDeviceAddress, results);
568 }
569 if (NS_FAILED(rv)) {
570 BT_WARNING("Pair/Unpair failed!");
571 aRv.Throw(rv);
572 return nullptr;
573 }
574
575 return request.forget();
576 }
577
578 already_AddRefed<DOMRequest>
579 BluetoothAdapter::Pair(const nsAString& aDeviceAddress, ErrorResult& aRv)
580 {
581 return PairUnpair(true, aDeviceAddress, aRv);
582 }
583
584 already_AddRefed<DOMRequest>
585 BluetoothAdapter::Unpair(const nsAString& aDeviceAddress, ErrorResult& aRv)
586 {
587 return PairUnpair(false, aDeviceAddress, aRv);
588 }
589
590 already_AddRefed<DOMRequest>
591 BluetoothAdapter::SetPinCode(const nsAString& aDeviceAddress,
592 const nsAString& aPinCode, ErrorResult& aRv)
593 {
594 nsCOMPtr<nsPIDOMWindow> win = GetOwner();
595 if (!win) {
596 aRv.Throw(NS_ERROR_FAILURE);
597 return nullptr;
598 }
599
600 nsRefPtr<DOMRequest> request = new DOMRequest(win);
601 nsRefPtr<BluetoothVoidReplyRunnable> results =
602 new BluetoothVoidReplyRunnable(request);
603
604 BluetoothService* bs = BluetoothService::Get();
605 if (!bs) {
606 aRv.Throw(NS_ERROR_FAILURE);
607 return nullptr;
608 }
609 if (!bs->SetPinCodeInternal(aDeviceAddress, aPinCode, results)) {
610 BT_WARNING("SetPinCode failed!");
611 aRv.Throw(NS_ERROR_FAILURE);
612 return nullptr;
613 }
614
615 return request.forget();
616 }
617
618 already_AddRefed<DOMRequest>
619 BluetoothAdapter::SetPasskey(const nsAString& aDeviceAddress, uint32_t aPasskey,
620 ErrorResult& aRv)
621 {
622 nsCOMPtr<nsPIDOMWindow> win = GetOwner();
623 if (!win) {
624 aRv.Throw(NS_ERROR_FAILURE);
625 return nullptr;
626 }
627
628 nsRefPtr<DOMRequest> request = new DOMRequest(win);
629 nsRefPtr<BluetoothVoidReplyRunnable> results =
630 new BluetoothVoidReplyRunnable(request);
631
632 BluetoothService* bs = BluetoothService::Get();
633 if (!bs) {
634 aRv.Throw(NS_ERROR_FAILURE);
635 return nullptr;
636 }
637 if (bs->SetPasskeyInternal(aDeviceAddress, aPasskey, results)) {
638 BT_WARNING("SetPasskeyInternal failed!");
639 aRv.Throw(NS_ERROR_FAILURE);
640 return nullptr;
641 }
642
643 return request.forget();
644 }
645
646 already_AddRefed<DOMRequest>
647 BluetoothAdapter::SetPairingConfirmation(const nsAString& aDeviceAddress,
648 bool aConfirmation, ErrorResult& aRv)
649 {
650 nsCOMPtr<nsPIDOMWindow> win = GetOwner();
651 if (!win) {
652 aRv.Throw(NS_ERROR_FAILURE);
653 return nullptr;
654 }
655
656 nsRefPtr<DOMRequest> request = new DOMRequest(win);
657 nsRefPtr<BluetoothVoidReplyRunnable> results =
658 new BluetoothVoidReplyRunnable(request);
659
660 BluetoothService* bs = BluetoothService::Get();
661 if (!bs) {
662 aRv.Throw(NS_ERROR_FAILURE);
663 return nullptr;
664 }
665 if (!bs->SetPairingConfirmationInternal(aDeviceAddress,
666 aConfirmation,
667 results)) {
668 BT_WARNING("SetPairingConfirmation failed!");
669 aRv.Throw(NS_ERROR_FAILURE);
670 return nullptr;
671 }
672
673 return request.forget();
674 }
675
676 already_AddRefed<DOMRequest>
677 BluetoothAdapter::Connect(BluetoothDevice& aDevice,
678 const Optional<short unsigned int>& aServiceUuid,
679 ErrorResult& aRv)
680 {
681 nsCOMPtr<nsPIDOMWindow> win = GetOwner();
682 if (!win) {
683 aRv.Throw(NS_ERROR_FAILURE);
684 return nullptr;
685 }
686
687 nsRefPtr<DOMRequest> request = new DOMRequest(win);
688 nsRefPtr<BluetoothVoidReplyRunnable> results =
689 new BluetoothVoidReplyRunnable(request);
690
691 nsAutoString address;
692 aDevice.GetAddress(address);
693 uint32_t deviceClass = aDevice.Class();
694 uint16_t serviceUuid = 0;
695 if (aServiceUuid.WasPassed()) {
696 serviceUuid = aServiceUuid.Value();
697 }
698
699 BluetoothService* bs = BluetoothService::Get();
700 if (!bs) {
701 aRv.Throw(NS_ERROR_FAILURE);
702 return nullptr;
703 }
704 bs->Connect(address, deviceClass, serviceUuid, results);
705
706 return request.forget();
707 }
708
709 already_AddRefed<DOMRequest>
710 BluetoothAdapter::Disconnect(BluetoothDevice& aDevice,
711 const Optional<short unsigned int>& aServiceUuid,
712 ErrorResult& aRv)
713 {
714 nsCOMPtr<nsPIDOMWindow> win = GetOwner();
715 if (!win) {
716 aRv.Throw(NS_ERROR_FAILURE);
717 return nullptr;
718 }
719
720 nsRefPtr<DOMRequest> request = new DOMRequest(win);
721 nsRefPtr<BluetoothVoidReplyRunnable> results =
722 new BluetoothVoidReplyRunnable(request);
723
724 nsAutoString address;
725 aDevice.GetAddress(address);
726 uint16_t serviceUuid = 0;
727 if (aServiceUuid.WasPassed()) {
728 serviceUuid = aServiceUuid.Value();
729 }
730
731 BluetoothService* bs = BluetoothService::Get();
732 if (!bs) {
733 aRv.Throw(NS_ERROR_FAILURE);
734 return nullptr;
735 }
736 bs->Disconnect(address, serviceUuid, results);
737
738 return request.forget();
739 }
740
741 already_AddRefed<DOMRequest>
742 BluetoothAdapter::SendFile(const nsAString& aDeviceAddress,
743 nsIDOMBlob* aBlob, ErrorResult& aRv)
744 {
745 nsCOMPtr<nsPIDOMWindow> win = GetOwner();
746 if (!win) {
747 aRv.Throw(NS_ERROR_FAILURE);
748 return nullptr;
749 }
750
751 nsRefPtr<DOMRequest> request = new DOMRequest(win);
752 nsRefPtr<BluetoothVoidReplyRunnable> results =
753 new BluetoothVoidReplyRunnable(request);
754
755 BluetoothService* bs = BluetoothService::Get();
756 if (!bs) {
757 aRv.Throw(NS_ERROR_FAILURE);
758 return nullptr;
759 }
760
761 if (XRE_GetProcessType() == GeckoProcessType_Default) {
762 // In-process transfer
763 bs->SendFile(aDeviceAddress, aBlob, results);
764 } else {
765 ContentChild *cc = ContentChild::GetSingleton();
766 if (!cc) {
767 aRv.Throw(NS_ERROR_FAILURE);
768 return nullptr;
769 }
770
771 BlobChild* actor = cc->GetOrCreateActorForBlob(aBlob);
772 if (!actor) {
773 aRv.Throw(NS_ERROR_FAILURE);
774 return nullptr;
775 }
776
777 bs->SendFile(aDeviceAddress, nullptr, actor, results);
778 }
779
780 return request.forget();
781 }
782
783 already_AddRefed<DOMRequest>
784 BluetoothAdapter::StopSendingFile(const nsAString& aDeviceAddress, ErrorResult& aRv)
785 {
786 nsCOMPtr<nsPIDOMWindow> win = GetOwner();
787 if (!win) {
788 aRv.Throw(NS_ERROR_FAILURE);
789 return nullptr;
790 }
791
792 nsRefPtr<DOMRequest> request = new DOMRequest(win);
793 nsRefPtr<BluetoothVoidReplyRunnable> results =
794 new BluetoothVoidReplyRunnable(request);
795
796 BluetoothService* bs = BluetoothService::Get();
797 if (!bs) {
798 aRv.Throw(NS_ERROR_FAILURE);
799 return nullptr;
800 }
801 bs->StopSendingFile(aDeviceAddress, results);
802
803 return request.forget();
804 }
805
806 already_AddRefed<DOMRequest>
807 BluetoothAdapter::ConfirmReceivingFile(const nsAString& aDeviceAddress,
808 bool aConfirmation, ErrorResult& aRv)
809 {
810 nsCOMPtr<nsPIDOMWindow> win = GetOwner();
811 if (!win) {
812 aRv.Throw(NS_ERROR_FAILURE);
813 return nullptr;
814 }
815
816 nsRefPtr<DOMRequest> request = new DOMRequest(win);
817 nsRefPtr<BluetoothVoidReplyRunnable> results =
818 new BluetoothVoidReplyRunnable(request);
819
820 BluetoothService* bs = BluetoothService::Get();
821 if (!bs) {
822 aRv.Throw(NS_ERROR_FAILURE);
823 return nullptr;
824 }
825 bs->ConfirmReceivingFile(aDeviceAddress, aConfirmation, results);
826
827 return request.forget();
828 }
829
830 already_AddRefed<DOMRequest>
831 BluetoothAdapter::ConnectSco(ErrorResult& aRv)
832 {
833 nsCOMPtr<nsPIDOMWindow> win = GetOwner();
834 if (!win) {
835 aRv.Throw(NS_ERROR_FAILURE);
836 return nullptr;
837 }
838
839 nsRefPtr<DOMRequest> request = new DOMRequest(win);
840 nsRefPtr<BluetoothVoidReplyRunnable> results =
841 new BluetoothVoidReplyRunnable(request);
842
843 BluetoothService* bs = BluetoothService::Get();
844 if (!bs) {
845 aRv.Throw(NS_ERROR_FAILURE);
846 return nullptr;
847 }
848 bs->ConnectSco(results);
849
850 return request.forget();
851 }
852
853 already_AddRefed<DOMRequest>
854 BluetoothAdapter::DisconnectSco(ErrorResult& aRv)
855 {
856 nsCOMPtr<nsPIDOMWindow> win = GetOwner();
857 if (!win) {
858 aRv.Throw(NS_ERROR_FAILURE);
859 return nullptr;
860 }
861
862 nsRefPtr<DOMRequest> request = new DOMRequest(win);
863 nsRefPtr<BluetoothVoidReplyRunnable> results =
864 new BluetoothVoidReplyRunnable(request);
865
866 BluetoothService* bs = BluetoothService::Get();
867 if (!bs) {
868 aRv.Throw(NS_ERROR_FAILURE);
869 return nullptr;
870 }
871 bs->DisconnectSco(results);
872
873 return request.forget();
874 }
875
876 already_AddRefed<DOMRequest>
877 BluetoothAdapter::IsScoConnected(ErrorResult& aRv)
878 {
879 nsCOMPtr<nsPIDOMWindow> win = GetOwner();
880 if (!win) {
881 aRv.Throw(NS_ERROR_FAILURE);
882 return nullptr;
883 }
884
885 nsRefPtr<DOMRequest> request = new DOMRequest(win);
886 nsRefPtr<BluetoothReplyRunnable> results =
887 new GetScoConnectionStatusTask(request);
888
889 BluetoothService* bs = BluetoothService::Get();
890 if (!bs) {
891 aRv.Throw(NS_ERROR_FAILURE);
892 return nullptr;
893 }
894 bs->IsScoConnected(results);
895
896 return request.forget();
897 }
898
899 already_AddRefed<DOMRequest>
900 BluetoothAdapter::AnswerWaitingCall(ErrorResult& aRv)
901 {
902 #ifdef MOZ_B2G_RIL
903 nsCOMPtr<nsPIDOMWindow> win = GetOwner();
904 if (!win) {
905 aRv.Throw(NS_ERROR_FAILURE);
906 return nullptr;
907 }
908
909 nsRefPtr<DOMRequest> request = new DOMRequest(win);
910 nsRefPtr<BluetoothVoidReplyRunnable> results =
911 new BluetoothVoidReplyRunnable(request);
912
913 BluetoothService* bs = BluetoothService::Get();
914 if (!bs) {
915 aRv.Throw(NS_ERROR_FAILURE);
916 return nullptr;
917 }
918 bs->AnswerWaitingCall(results);
919
920 return request.forget();
921 #else
922 aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
923 return nullptr;
924 #endif // MOZ_B2G_RIL
925 }
926
927 already_AddRefed<DOMRequest>
928 BluetoothAdapter::IgnoreWaitingCall(ErrorResult& aRv)
929 {
930 #ifdef MOZ_B2G_RIL
931 nsCOMPtr<nsPIDOMWindow> win = GetOwner();
932 if (!win) {
933 aRv.Throw(NS_ERROR_FAILURE);
934 return nullptr;
935 }
936
937 nsRefPtr<DOMRequest> request = new DOMRequest(win);
938 nsRefPtr<BluetoothVoidReplyRunnable> results =
939 new BluetoothVoidReplyRunnable(request);
940
941 BluetoothService* bs = BluetoothService::Get();
942 if (!bs) {
943 aRv.Throw(NS_ERROR_FAILURE);
944 return nullptr;
945 }
946 bs->IgnoreWaitingCall(results);
947
948 return request.forget();
949 #else
950 aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
951 return nullptr;
952 #endif // MOZ_B2G_RIL
953 }
954
955 already_AddRefed<DOMRequest>
956 BluetoothAdapter::ToggleCalls(ErrorResult& aRv)
957 {
958 #ifdef MOZ_B2G_RIL
959 nsCOMPtr<nsPIDOMWindow> win = GetOwner();
960 if (!win) {
961 aRv.Throw(NS_ERROR_FAILURE);
962 return nullptr;
963 }
964
965 nsRefPtr<DOMRequest> request = new DOMRequest(win);
966 nsRefPtr<BluetoothVoidReplyRunnable> results =
967 new BluetoothVoidReplyRunnable(request);
968
969 BluetoothService* bs = BluetoothService::Get();
970 if (!bs) {
971 aRv.Throw(NS_ERROR_FAILURE);
972 return nullptr;
973 }
974 bs->ToggleCalls(results);
975
976 return request.forget();
977 #else
978 aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
979 return nullptr;
980 #endif // MOZ_B2G_RIL
981 }
982
983 already_AddRefed<DOMRequest>
984 BluetoothAdapter::SendMediaMetaData(const MediaMetaData& aMediaMetaData, ErrorResult& aRv)
985 {
986 nsCOMPtr<nsPIDOMWindow> win = GetOwner();
987 if (!win) {
988 aRv.Throw(NS_ERROR_FAILURE);
989 return nullptr;
990 }
991
992 nsRefPtr<DOMRequest> request = new DOMRequest(win);
993 nsRefPtr<BluetoothReplyRunnable> results =
994 new BluetoothVoidReplyRunnable(request);
995
996 BluetoothService* bs = BluetoothService::Get();
997 if (!bs) {
998 aRv.Throw(NS_ERROR_FAILURE);
999 return nullptr;
1000 }
1001 bs->SendMetaData(aMediaMetaData.mTitle,
1002 aMediaMetaData.mArtist,
1003 aMediaMetaData.mAlbum,
1004 aMediaMetaData.mMediaNumber,
1005 aMediaMetaData.mTotalMediaCount,
1006 aMediaMetaData.mDuration,
1007 results);
1008
1009 return request.forget();
1010 }
1011
1012 already_AddRefed<DOMRequest>
1013 BluetoothAdapter::SendMediaPlayStatus(const MediaPlayStatus& aMediaPlayStatus, ErrorResult& aRv)
1014 {
1015 nsCOMPtr<nsPIDOMWindow> win = GetOwner();
1016 if (!win) {
1017 aRv.Throw(NS_ERROR_FAILURE);
1018 return nullptr;
1019 }
1020
1021 nsRefPtr<DOMRequest> request = new DOMRequest(win);
1022 nsRefPtr<BluetoothReplyRunnable> results =
1023 new BluetoothVoidReplyRunnable(request);
1024
1025 BluetoothService* bs = BluetoothService::Get();
1026 if (!bs) {
1027 aRv.Throw(NS_ERROR_FAILURE);
1028 return nullptr;
1029 }
1030 bs->SendPlayStatus(aMediaPlayStatus.mDuration,
1031 aMediaPlayStatus.mPosition,
1032 aMediaPlayStatus.mPlayStatus,
1033 results);
1034
1035 return request.forget();
1036 }
1037
1038 JSObject*
1039 BluetoothAdapter::WrapObject(JSContext* aCx)
1040 {
1041 return BluetoothAdapterBinding::Wrap(aCx, this);
1042 }

mercurial