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"
9 #include "BluetoothService.h"
11 #include "BluetoothCommon.h"
12 #include "BluetoothA2dpManager.h"
13 #include "BluetoothHfpManager.h"
14 #include "BluetoothHidManager.h"
15 #include "BluetoothManager.h"
16 #include "BluetoothOppManager.h"
17 #include "BluetoothParent.h"
18 #include "BluetoothReplyRunnable.h"
19 #include "BluetoothServiceChildProcess.h"
20 #include "BluetoothUtils.h"
23 #include "mozilla/ClearOnShutdown.h"
24 #include "mozilla/Services.h"
25 #include "mozilla/StaticPtr.h"
26 #include "mozilla/unused.h"
27 #include "mozilla/dom/ContentParent.h"
28 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
29 #include "mozilla/ipc/UnixSocket.h"
30 #include "nsContentUtils.h"
31 #include "nsIObserverService.h"
32 #include "nsISettingsService.h"
33 #include "nsISystemMessagesInternal.h"
35 #include "nsServiceManagerUtils.h"
38 #if defined(MOZ_WIDGET_GONK)
39 #include "cutils/properties.h"
42 #if defined(MOZ_B2G_BT)
43 #if defined(MOZ_B2G_BT_BLUEZ)
46 * MOZ_B2G_BT and MOZ_B2G_BT_BLUEZ are both defined.
48 #include "BluetoothDBusService.h"
49 #elif defined(MOZ_B2G_BT_BLUEDROID)
52 * MOZ_B2G_BT and MOZ_B2G_BT_BLUEDROID are both defined;
53 * MOZ_B2G_BLUEZ is not defined.
55 #include "BluetoothServiceBluedroid.h"
57 #elif defined(MOZ_BLUETOOTH_DBUS)
60 * MOZ_B2G_BT is not defined; MOZ_BLUETOOTH_DBUS is defined.
62 #include "BluetoothDBusService.h"
67 #define MOZSETTINGS_CHANGED_ID "mozsettings-changed"
68 #define BLUETOOTH_ENABLED_SETTING "bluetooth.enabled"
69 #define BLUETOOTH_DEBUGGING_SETTING "bluetooth.debugging.enabled"
71 #define PROP_BLUETOOTH_ENABLED "bluetooth.isEnabled"
73 #define DEFAULT_SHUTDOWN_TIMER_MS 5000
75 bool gBluetoothDebugFlag
= false;
77 using namespace mozilla
;
78 using namespace mozilla::dom
;
79 USING_BLUETOOTH_NAMESPACE
83 StaticRefPtr
<BluetoothService
> sBluetoothService
;
85 bool sInShutdown
= false;
86 bool sToggleInProgress
= false;
91 return XRE_GetProcessType() == GeckoProcessType_Default
;
95 ShutdownTimeExceeded(nsITimer
* aTimer
, void* aClosure
)
97 MOZ_ASSERT(NS_IsMainThread());
98 *static_cast<bool*>(aClosure
) = true;
102 GetAllBluetoothActors(InfallibleTArray
<BluetoothParent
*>& aActors
)
104 MOZ_ASSERT(NS_IsMainThread());
105 MOZ_ASSERT(aActors
.IsEmpty());
107 nsAutoTArray
<ContentParent
*, 20> contentActors
;
108 ContentParent::GetAll(contentActors
);
110 for (uint32_t contentIndex
= 0;
111 contentIndex
< contentActors
.Length();
113 MOZ_ASSERT(contentActors
[contentIndex
]);
115 AutoInfallibleTArray
<PBluetoothParent
*, 5> bluetoothActors
;
116 contentActors
[contentIndex
]->ManagedPBluetoothParent(bluetoothActors
);
118 for (uint32_t bluetoothIndex
= 0;
119 bluetoothIndex
< bluetoothActors
.Length();
121 MOZ_ASSERT(bluetoothActors
[bluetoothIndex
]);
123 BluetoothParent
* actor
=
124 static_cast<BluetoothParent
*>(bluetoothActors
[bluetoothIndex
]);
125 aActors
.AppendElement(actor
);
130 } // anonymous namespace
132 BluetoothService::ToggleBtAck::ToggleBtAck(bool aEnabled
)
137 BluetoothService::ToggleBtAck::Run()
139 MOZ_ASSERT(NS_IsMainThread());
141 // This is requested in Bug 836516. With settings this property, WLAN
142 // firmware could be aware of Bluetooth has been turned on/off, so that the
143 // mecahnism of handling coexistence of WIFI and Bluetooth could be started.
145 // In the future, we may have our own way instead of setting a system
146 // property to let firmware developers be able to sense that Bluetooth has
148 #if defined(MOZ_WIDGET_GONK)
149 if (property_set(PROP_BLUETOOTH_ENABLED
, mEnabled
? "true" : "false") != 0) {
150 BT_WARNING("Failed to set bluetooth enabled property");
154 NS_ENSURE_TRUE(sBluetoothService
, NS_OK
);
157 sBluetoothService
= nullptr;
161 // Update mEnabled of BluetoothService object since
162 // StartInternal/StopInternal have been already done.
163 sBluetoothService
->SetEnabled(mEnabled
);
164 sToggleInProgress
= false;
166 nsAutoString signalName
;
167 signalName
= mEnabled
? NS_LITERAL_STRING("Enabled")
168 : NS_LITERAL_STRING("Disabled");
169 BluetoothSignal
signal(signalName
, NS_LITERAL_STRING(KEY_MANAGER
), true);
170 sBluetoothService
->DistributeSignal(signal
);
172 // Event 'AdapterAdded' has to be fired after firing 'Enabled'
173 sBluetoothService
->TryFiringAdapterAdded();
178 class BluetoothService::StartupTask
: public nsISettingsServiceCallback
183 NS_IMETHOD
Handle(const nsAString
& aName
, JS::Handle
<JS::Value
> aResult
)
185 MOZ_ASSERT(NS_IsMainThread());
187 if (!aResult
.isBoolean()) {
188 BT_WARNING("Setting for '" BLUETOOTH_ENABLED_SETTING
"' is not a boolean!");
192 // It is theoretically possible to shut down before the first settings check
193 // has completed (though extremely unlikely).
194 if (sBluetoothService
) {
195 return sBluetoothService
->HandleStartupSettingsCheck(aResult
.toBoolean());
201 NS_IMETHOD
HandleError(const nsAString
& aName
)
203 BT_WARNING("Unable to get value for '" BLUETOOTH_ENABLED_SETTING
"'");
208 NS_IMPL_ISUPPORTS(BluetoothService::StartupTask
, nsISettingsServiceCallback
);
210 NS_IMPL_ISUPPORTS(BluetoothService
, nsIObserver
)
213 BluetoothService::IsToggling() const
215 return sToggleInProgress
;
218 BluetoothService::~BluetoothService()
224 RemoveObserversExceptBluetoothManager
225 (const nsAString
& key
,
226 nsAutoPtr
<BluetoothSignalObserverList
>& value
,
229 if (!key
.EqualsLiteral(KEY_MANAGER
)) {
230 return PL_DHASH_REMOVE
;
233 return PL_DHASH_NEXT
;
238 BluetoothService::Create()
240 #if defined(MOZ_B2G_BT)
241 if (!IsMainProcess()) {
242 return BluetoothServiceChildProcess::Create();
245 #if defined(MOZ_B2G_BT_BLUEZ)
246 return new BluetoothDBusService();
247 #elif defined(MOZ_B2G_BT_BLUEDROID)
248 return new BluetoothServiceBluedroid();
250 #elif defined(MOZ_BLUETOOTH_DBUS)
251 return new BluetoothDBusService();
254 BT_WARNING("No platform support for bluetooth!");
259 BluetoothService::Init()
261 MOZ_ASSERT(NS_IsMainThread());
263 nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService();
264 NS_ENSURE_TRUE(obs
, false);
266 if (NS_FAILED(obs
->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID
,
268 BT_WARNING("Failed to add shutdown observer!");
272 // Only the main process should observe bluetooth settings changes.
273 if (IsMainProcess() &&
274 NS_FAILED(obs
->AddObserver(this, MOZSETTINGS_CHANGED_ID
, false))) {
275 BT_WARNING("Failed to add settings change observer!");
283 BluetoothService::Cleanup()
285 MOZ_ASSERT(NS_IsMainThread());
287 nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService();
289 (NS_FAILED(obs
->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID
)) ||
290 NS_FAILED(obs
->RemoveObserver(this, MOZSETTINGS_CHANGED_ID
)))) {
291 BT_WARNING("Can't unregister observers!");
296 BluetoothService::RegisterBluetoothSignalHandler(
297 const nsAString
& aNodeName
,
298 BluetoothSignalObserver
* aHandler
)
300 MOZ_ASSERT(NS_IsMainThread());
301 MOZ_ASSERT(aHandler
);
303 BT_LOGD("[S] %s: %s", __FUNCTION__
, NS_ConvertUTF16toUTF8(aNodeName
).get());
305 BluetoothSignalObserverList
* ol
;
306 if (!mBluetoothSignalObserverTable
.Get(aNodeName
, &ol
)) {
307 ol
= new BluetoothSignalObserverList();
308 mBluetoothSignalObserverTable
.Put(aNodeName
, ol
);
311 ol
->AddObserver(aHandler
);
315 BluetoothService::UnregisterBluetoothSignalHandler(
316 const nsAString
& aNodeName
,
317 BluetoothSignalObserver
* aHandler
)
319 MOZ_ASSERT(NS_IsMainThread());
320 MOZ_ASSERT(aHandler
);
322 BT_LOGD("[S] %s: %s", __FUNCTION__
, NS_ConvertUTF16toUTF8(aNodeName
).get());
324 BluetoothSignalObserverList
* ol
;
325 if (mBluetoothSignalObserverTable
.Get(aNodeName
, &ol
)) {
326 ol
->RemoveObserver(aHandler
);
327 // We shouldn't have duplicate instances in the ObserverList, but there's
328 // no appropriate way to do duplication check while registering, so
329 // assertions are added here.
330 MOZ_ASSERT(!ol
->RemoveObserver(aHandler
));
331 if (ol
->Length() == 0) {
332 mBluetoothSignalObserverTable
.Remove(aNodeName
);
336 BT_WARNING("Node was never registered!");
341 RemoveAllSignalHandlers(const nsAString
& aKey
,
342 nsAutoPtr
<BluetoothSignalObserverList
>& aData
,
345 BluetoothSignalObserver
* handler
= static_cast<BluetoothSignalObserver
*>(aUserArg
);
346 aData
->RemoveObserver(handler
);
347 // We shouldn't have duplicate instances in the ObserverList, but there's
348 // no appropriate way to do duplication check while registering, so
349 // assertions are added here.
350 MOZ_ASSERT(!aData
->RemoveObserver(handler
));
351 return aData
->Length() ? PL_DHASH_NEXT
: PL_DHASH_REMOVE
;
355 BluetoothService::UnregisterAllSignalHandlers(BluetoothSignalObserver
* aHandler
)
357 MOZ_ASSERT(NS_IsMainThread());
358 MOZ_ASSERT(aHandler
);
360 mBluetoothSignalObserverTable
.Enumerate(RemoveAllSignalHandlers
, aHandler
);
364 BluetoothService::DistributeSignal(const BluetoothSignal
& aSignal
)
366 MOZ_ASSERT(NS_IsMainThread());
368 if (aSignal
.path().EqualsLiteral(KEY_LOCAL_AGENT
)) {
371 } else if (aSignal
.path().EqualsLiteral(KEY_REMOTE_AGENT
)) {
376 BluetoothSignalObserverList
* ol
;
377 if (!mBluetoothSignalObserverTable
.Get(aSignal
.path(), &ol
)) {
379 nsAutoCString
msg("No observer registered for path ");
380 msg
.Append(NS_ConvertUTF16toUTF8(aSignal
.path()));
381 BT_WARNING(msg
.get());
385 MOZ_ASSERT(ol
->Length());
386 ol
->Broadcast(aSignal
);
390 BluetoothService::StartBluetooth(bool aIsStartup
)
392 MOZ_ASSERT(NS_IsMainThread());
395 // Don't try to start if we're already shutting down.
396 MOZ_ASSERT(false, "Start called while in shutdown!");
397 return NS_ERROR_FAILURE
;
400 mAdapterAddedReceived
= false;
402 /* When IsEnabled() is true, we don't switch on Bluetooth but we still
403 * send ToggleBtAck task. One special case happens at startup stage. At
404 * startup, the initialization of BluetoothService still has to be done
405 * even if Bluetooth is already enabled.
407 * Please see bug 892392 for more information.
409 if (aIsStartup
|| !sBluetoothService
->IsEnabled()) {
410 // Switch Bluetooth on
411 if (NS_FAILED(sBluetoothService
->StartInternal())) {
412 BT_WARNING("Bluetooth service failed to start!");
415 BT_WARNING("Bluetooth has already been enabled before.");
416 nsRefPtr
<nsRunnable
> runnable
= new BluetoothService::ToggleBtAck(true);
417 if (NS_FAILED(NS_DispatchToMainThread(runnable
))) {
418 BT_WARNING("Failed to dispatch to main thread!");
426 BluetoothService::StopBluetooth(bool aIsStartup
)
428 MOZ_ASSERT(NS_IsMainThread());
430 BluetoothProfileManagerBase
* profile
;
431 profile
= BluetoothHfpManager::Get();
432 NS_ENSURE_TRUE(profile
, NS_ERROR_FAILURE
);
433 if (profile
->IsConnected()) {
434 profile
->Disconnect(nullptr);
439 profile
= BluetoothOppManager::Get();
440 NS_ENSURE_TRUE(profile
, NS_ERROR_FAILURE
);
441 if (profile
->IsConnected()) {
442 profile
->Disconnect(nullptr);
445 profile
= BluetoothA2dpManager::Get();
446 NS_ENSURE_TRUE(profile
, NS_ERROR_FAILURE
);
447 if (profile
->IsConnected()) {
448 profile
->Disconnect(nullptr);
453 profile
= BluetoothHidManager::Get();
454 NS_ENSURE_TRUE(profile
, NS_ERROR_FAILURE
);
455 if (profile
->IsConnected()) {
456 profile
->Disconnect(nullptr);
461 mAdapterAddedReceived
= false;
463 /* When IsEnabled() is false, we don't switch off Bluetooth but we still
464 * send ToggleBtAck task. One special case happens at startup stage. At
465 * startup, the initialization of BluetoothService still has to be done
466 * even if Bluetooth is disabled.
468 * Please see bug 892392 for more information.
470 if (aIsStartup
|| sBluetoothService
->IsEnabled()) {
471 // Switch Bluetooth off
472 if (NS_FAILED(sBluetoothService
->StopInternal())) {
473 BT_WARNING("Bluetooth service failed to stop!");
476 BT_WARNING("Bluetooth has already been enabled/disabled before.");
477 nsRefPtr
<nsRunnable
> runnable
= new BluetoothService::ToggleBtAck(false);
478 if (NS_FAILED(NS_DispatchToMainThread(runnable
))) {
479 BT_WARNING("Failed to dispatch to main thread!");
487 BluetoothService::StartStopBluetooth(bool aStart
, bool aIsStartup
)
491 rv
= StartBluetooth(aIsStartup
);
493 rv
= StopBluetooth(aIsStartup
);
499 BluetoothService::SetEnabled(bool aEnabled
)
501 MOZ_ASSERT(NS_IsMainThread());
503 AutoInfallibleTArray
<BluetoothParent
*, 10> childActors
;
504 GetAllBluetoothActors(childActors
);
506 for (uint32_t index
= 0; index
< childActors
.Length(); index
++) {
507 unused
<< childActors
[index
]->SendEnabled(aEnabled
);
512 * Remove all handlers except BluetoothManager when turning off bluetooth
513 * since it is possible that the event 'onAdapterAdded' would be fired after
514 * BluetoothManagers of child process are registered. Please see Bug 827759
517 mBluetoothSignalObserverTable
.Enumerate(
518 RemoveObserversExceptBluetoothManager
, nullptr);
522 * mEnabled: real status of bluetooth
523 * aEnabled: expected status of bluetooth
525 if (mEnabled
== aEnabled
) {
526 BT_WARNING("Bluetooth has already been enabled/disabled before "
527 "or the toggling is failed.");
534 BluetoothService::HandleStartup()
536 MOZ_ASSERT(NS_IsMainThread());
537 MOZ_ASSERT(!sToggleInProgress
);
539 nsCOMPtr
<nsISettingsService
> settings
=
540 do_GetService("@mozilla.org/settingsService;1");
541 NS_ENSURE_TRUE(settings
, NS_ERROR_UNEXPECTED
);
543 nsCOMPtr
<nsISettingsServiceLock
> settingsLock
;
544 nsresult rv
= settings
->CreateLock(nullptr, getter_AddRefs(settingsLock
));
545 NS_ENSURE_SUCCESS(rv
, rv
);
547 nsRefPtr
<StartupTask
> callback
= new StartupTask();
548 rv
= settingsLock
->Get(BLUETOOTH_ENABLED_SETTING
, callback
);
549 NS_ENSURE_SUCCESS(rv
, rv
);
551 sToggleInProgress
= true;
556 BluetoothService::HandleStartupSettingsCheck(bool aEnable
)
558 MOZ_ASSERT(NS_IsMainThread());
559 return StartStopBluetooth(aEnable
, true);
563 BluetoothService::HandleSettingsChanged(const nsAString
& aData
)
565 MOZ_ASSERT(NS_IsMainThread());
567 // The string that we're interested in will be a JSON string that looks like:
568 // {"key":"bluetooth.enabled","value":true}
570 AutoSafeJSContext cx
;
575 JS::Rooted
<JS::Value
> val(cx
);
576 if (!JS_ParseJSON(cx
, aData
.BeginReading(), aData
.Length(), &val
)) {
577 return JS_ReportPendingException(cx
) ? NS_OK
: NS_ERROR_OUT_OF_MEMORY
;
580 if (!val
.isObject()) {
584 JS::Rooted
<JSObject
*> obj(cx
, &val
.toObject());
586 JS::Rooted
<JS::Value
> key(cx
);
587 if (!JS_GetProperty(cx
, obj
, "key", &key
)) {
588 MOZ_ASSERT(!JS_IsExceptionPending(cx
));
589 return NS_ERROR_OUT_OF_MEMORY
;
592 if (!key
.isString()) {
596 // First, check if the string equals to BLUETOOTH_DEBUGGING_SETTING
598 if (!JS_StringEqualsAscii(cx
, key
.toString(), BLUETOOTH_DEBUGGING_SETTING
, &match
)) {
599 MOZ_ASSERT(!JS_IsExceptionPending(cx
));
600 return NS_ERROR_OUT_OF_MEMORY
;
604 JS::Rooted
<JS::Value
> value(cx
);
605 if (!JS_GetProperty(cx
, obj
, "value", &value
)) {
606 MOZ_ASSERT(!JS_IsExceptionPending(cx
));
607 return NS_ERROR_OUT_OF_MEMORY
;
610 if (!value
.isBoolean()) {
611 MOZ_ASSERT(false, "Expecting a boolean for 'bluetooth.debugging.enabled'!");
612 return NS_ERROR_UNEXPECTED
;
615 SWITCH_BT_DEBUG(value
.toBoolean());
620 // Second, check if the string is BLUETOOTH_ENABLED_SETTING
621 if (!JS_StringEqualsAscii(cx
, key
.toString(), BLUETOOTH_ENABLED_SETTING
, &match
)) {
622 MOZ_ASSERT(!JS_IsExceptionPending(cx
));
623 return NS_ERROR_OUT_OF_MEMORY
;
627 JS::Rooted
<JS::Value
> value(cx
);
628 if (!JS_GetProperty(cx
, obj
, "value", &value
)) {
629 MOZ_ASSERT(!JS_IsExceptionPending(cx
));
630 return NS_ERROR_OUT_OF_MEMORY
;
633 if (!value
.isBoolean()) {
634 MOZ_ASSERT(false, "Expecting a boolean for 'bluetooth.enabled'!");
635 return NS_ERROR_UNEXPECTED
;
638 if (sToggleInProgress
|| value
.toBoolean() == IsEnabled()) {
639 // Nothing to do here.
643 sToggleInProgress
= true;
645 nsresult rv
= StartStopBluetooth(value
.toBoolean(), false);
646 NS_ENSURE_SUCCESS(rv
, rv
);
653 BluetoothService::HandleShutdown()
655 MOZ_ASSERT(NS_IsMainThread());
657 // This is a two phase shutdown. First we notify all child processes that
658 // bluetooth is going away, and then we wait for them to acknowledge. Then we
659 // close down all the bluetooth machinery.
665 AutoInfallibleTArray
<BluetoothParent
*, 10> childActors
;
666 GetAllBluetoothActors(childActors
);
668 if (!childActors
.IsEmpty()) {
669 // Notify child processes that they should stop using bluetooth now.
670 for (uint32_t index
= 0; index
< childActors
.Length(); index
++) {
671 childActors
[index
]->BeginShutdown();
674 // Create a timer to ensure that we don't wait forever for a child process
675 // or the bluetooth threads to finish. If we don't get a timer or can't use
676 // it for some reason then we skip all the waiting entirely since we really
677 // can't afford to hang on shutdown.
678 nsCOMPtr
<nsITimer
> timer
= do_CreateInstance(NS_TIMER_CONTRACTID
);
682 bool timeExceeded
= false;
684 if (NS_SUCCEEDED(timer
->InitWithFuncCallback(ShutdownTimeExceeded
,
686 DEFAULT_SHUTDOWN_TIMER_MS
,
687 nsITimer::TYPE_ONE_SHOT
))) {
688 nsIThread
* currentThread
= NS_GetCurrentThread();
689 MOZ_ASSERT(currentThread
);
691 // Wait for those child processes to acknowledge.
692 while (!timeExceeded
&& !childActors
.IsEmpty()) {
693 if (!NS_ProcessNextEvent(currentThread
)) {
694 MOZ_ASSERT(false, "Something horribly wrong here!");
697 GetAllBluetoothActors(childActors
);
700 if (NS_FAILED(timer
->Cancel())) {
701 MOZ_CRASH("Failed to cancel shutdown timer, this will crash!");
705 MOZ_ASSERT(false, "Failed to initialize shutdown timer!");
710 if (IsEnabled() && NS_FAILED(StopBluetooth(false))) {
711 MOZ_ASSERT(false, "Failed to deliver stop message!");
719 BluetoothService::Get()
721 MOZ_ASSERT(NS_IsMainThread());
723 // If we already exist, exit early
724 if (sBluetoothService
) {
725 return sBluetoothService
;
728 // If we're in shutdown, don't create a new instance
730 BT_WARNING("BluetoothService can't be created during shutdown");
734 // Create new instance, register, return
735 sBluetoothService
= BluetoothService::Create();
736 NS_ENSURE_TRUE(sBluetoothService
, nullptr);
738 if (!sBluetoothService
->Init()) {
739 sBluetoothService
->Cleanup();
743 ClearOnShutdown(&sBluetoothService
);
744 return sBluetoothService
;
748 BluetoothService::Observe(nsISupports
* aSubject
, const char* aTopic
,
749 const char16_t
* aData
)
751 MOZ_ASSERT(NS_IsMainThread());
753 if (!strcmp(aTopic
, "profile-after-change")) {
754 return HandleStartup();
757 if (!strcmp(aTopic
, MOZSETTINGS_CHANGED_ID
)) {
758 return HandleSettingsChanged(nsDependentString(aData
));
761 if (!strcmp(aTopic
, NS_XPCOM_SHUTDOWN_OBSERVER_ID
)) {
762 return HandleShutdown();
765 MOZ_ASSERT(false, "BluetoothService got unexpected topic!");
766 return NS_ERROR_UNEXPECTED
;
770 BluetoothService::TryFiringAdapterAdded()
772 MOZ_ASSERT(NS_IsMainThread());
774 if (IsToggling() || !mAdapterAddedReceived
) {
778 BluetoothSignal
signal(NS_LITERAL_STRING("AdapterAdded"),
779 NS_LITERAL_STRING(KEY_MANAGER
), true);
780 DistributeSignal(signal
);
784 BluetoothService::AdapterAddedReceived()
786 MOZ_ASSERT(NS_IsMainThread());
788 mAdapterAddedReceived
= true;
792 BluetoothService::Notify(const BluetoothSignal
& aData
)
794 nsString type
= NS_LITERAL_STRING("bluetooth-pairing-request");
796 AutoSafeJSContext cx
;
797 JS::Rooted
<JSObject
*> obj(cx
, JS_NewObject(cx
, nullptr, JS::NullPtr(),
799 NS_ENSURE_TRUE_VOID(obj
);
801 if (!SetJsObject(cx
, aData
.value(), obj
)) {
802 BT_WARNING("Failed to set properties of system message!");
806 BT_LOGD("[S] %s: %s", __FUNCTION__
, NS_ConvertUTF16toUTF8(aData
.name()).get());
808 if (aData
.name().EqualsLiteral("RequestConfirmation")) {
809 MOZ_ASSERT(aData
.value().get_ArrayOfBluetoothNamedValue().Length() == 4,
810 "RequestConfirmation: Wrong length of parameters");
811 } else if (aData
.name().EqualsLiteral("RequestPinCode")) {
812 MOZ_ASSERT(aData
.value().get_ArrayOfBluetoothNamedValue().Length() == 3,
813 "RequestPinCode: Wrong length of parameters");
814 } else if (aData
.name().EqualsLiteral("RequestPasskey")) {
815 MOZ_ASSERT(aData
.value().get_ArrayOfBluetoothNamedValue().Length() == 3,
816 "RequestPinCode: Wrong length of parameters");
817 } else if (aData
.name().EqualsLiteral("Cancel")) {
818 MOZ_ASSERT(aData
.value().get_ArrayOfBluetoothNamedValue().Length() == 0,
819 "Cancel: Wrong length of parameters");
820 type
.AssignLiteral("bluetooth-cancel");
821 } else if (aData
.name().EqualsLiteral(PAIRED_STATUS_CHANGED_ID
)) {
822 MOZ_ASSERT(aData
.value().get_ArrayOfBluetoothNamedValue().Length() == 1,
823 "pairedstatuschanged: Wrong length of parameters");
824 type
.AssignLiteral("bluetooth-pairedstatuschanged");
826 nsCString warningMsg
;
827 warningMsg
.AssignLiteral("Not handling service signal: ");
828 warningMsg
.Append(NS_ConvertUTF16toUTF8(aData
.name()));
829 BT_WARNING(warningMsg
.get());
833 nsCOMPtr
<nsISystemMessagesInternal
> systemMessenger
=
834 do_GetService("@mozilla.org/system-message-internal;1");
835 NS_ENSURE_TRUE_VOID(systemMessenger
);
837 JS::Rooted
<JS::Value
> value(cx
, JS::ObjectValue(*obj
));
838 systemMessenger
->BroadcastMessage(type
, value
,
839 JS::UndefinedHandleValue
);