Bug 755943 - 'Electrolysize b2g-bluetooth'. r=qDot+cjones.

This commit is contained in:
Ben Turner 2012-09-13 09:37:14 -07:00
parent df5b48bf82
commit 4fa4606698
35 changed files with 2039 additions and 319 deletions

View File

@ -46,6 +46,7 @@ PARALLEL_DIRS += \
activities \
bindings \
battery \
bluetooth \
browser-element \
contacts \
alarm \
@ -80,12 +81,6 @@ PARALLEL_DIRS += \
$(NULL)
endif
ifdef MOZ_B2G_BT
PARALLEL_DIRS += \
bluetooth \
$(NULL)
endif
ifdef MOZ_PAY
PARALLEL_DIRS += \
payment \

View File

@ -9,7 +9,6 @@
#include "BluetoothDevice.h"
#include "BluetoothPropertyEvent.h"
#include "BluetoothService.h"
#include "BluetoothTypes.h"
#include "BluetoothReplyRunnable.h"
#include "BluetoothUtils.h"
#include "GeneratedEvents.h"
@ -25,6 +24,7 @@
#include "mozilla/LazyIdleThread.h"
#include "mozilla/Util.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
using namespace mozilla;
@ -149,9 +149,9 @@ BluetoothAdapter::~BluetoothAdapter()
BluetoothService* bs = BluetoothService::Get();
// We can be null on shutdown, where this might happen
if (bs) {
if (NS_FAILED(bs->UnregisterBluetoothSignalHandler(mPath, this))) {
NS_WARNING("Failed to unregister object with observer!");
}
// XXXbent I don't see anything about LOCAL_AGENT_PATH or REMOTE_AGENT_PATH
// here. Probably a bug? Maybe use UnregisterAll.
bs->UnregisterBluetoothSignalHandler(mPath, this);
}
Unroot();
}
@ -256,15 +256,9 @@ BluetoothAdapter::Create(nsPIDOMWindow* aOwner, const BluetoothValue& aValue)
}
nsRefPtr<BluetoothAdapter> adapter = new BluetoothAdapter(aOwner, aValue);
if (NS_FAILED(bs->RegisterBluetoothSignalHandler(adapter->GetPath(), adapter))) {
NS_WARNING("Failed to register object with observer!");
return nullptr;
}
if (NS_FAILED(bs->RegisterBluetoothSignalHandler(NS_LITERAL_STRING(REMOTE_AGENT_PATH), adapter))) {
NS_WARNING("Failed to register remote agent object with observer!");
return nullptr;
}
bs->RegisterBluetoothSignalHandler(adapter->GetPath(), adapter);
bs->RegisterBluetoothSignalHandler(NS_LITERAL_STRING(REMOTE_AGENT_PATH), adapter);
return adapter.forget();
}

View File

@ -7,9 +7,9 @@
#ifndef mozilla_dom_bluetooth_bluetoothcommon_h__
#define mozilla_dom_bluetooth_bluetoothcommon_h__
#include "nsString.h"
#include "nsTArray.h"
#include "mozilla/Observer.h"
#include "nsStringGlue.h"
#include "nsTArray.h"
#define BEGIN_BLUETOOTH_NAMESPACE \
namespace mozilla { namespace dom { namespace bluetooth {
@ -41,7 +41,9 @@ typedef mozilla::Observer<BluetoothSignal> BluetoothSignalObserver;
enum BluetoothObjectType {
TYPE_MANAGER = 0,
TYPE_ADAPTER = 1,
TYPE_DEVICE = 2
TYPE_DEVICE = 2,
TYPE_INVALID
};
END_BLUETOOTH_NAMESPACE

View File

@ -7,7 +7,6 @@
#include "base/basictypes.h"
#include "BluetoothDevice.h"
#include "BluetoothPropertyEvent.h"
#include "BluetoothTypes.h"
#include "BluetoothReplyRunnable.h"
#include "BluetoothService.h"
#include "BluetoothUtils.h"
@ -16,6 +15,7 @@
#include "nsIDOMDOMRequest.h"
#include "nsDOMClassInfo.h"
#include "nsContentUtils.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
USING_BLUETOOTH_NAMESPACE
@ -69,9 +69,7 @@ BluetoothDevice::~BluetoothDevice()
BluetoothService* bs = BluetoothService::Get();
// bs can be null on shutdown, where destruction might happen.
if (bs) {
if (NS_FAILED(bs->UnregisterBluetoothSignalHandler(mPath, this))) {
NS_WARNING("Failed to unregister object with observer!");
}
bs->UnregisterBluetoothSignalHandler(mPath, this);
}
Unroot();
}
@ -107,8 +105,8 @@ BluetoothDevice::SetPropertyByValue(const BluetoothNamedValue& aValue)
BluetoothService* bs = BluetoothService::Get();
if (!bs) {
NS_WARNING("BluetoothService not available!");
} else if (NS_FAILED(bs->RegisterBluetoothSignalHandler(mPath, this))) {
NS_WARNING("Failed to register object with observer!");
} else {
bs->RegisterBluetoothSignalHandler(mPath, this);
}
} else if (name.EqualsLiteral("Address")) {
mAddress = value.get_nsString();
@ -177,10 +175,9 @@ BluetoothDevice::Create(nsPIDOMWindow* aOwner,
nsRefPtr<BluetoothDevice> device = new BluetoothDevice(aOwner, aAdapterPath,
aValue);
if (NS_FAILED(bs->RegisterBluetoothSignalHandler(device->mPath, device))) {
NS_WARNING("Failed to register object with observer!");
return nullptr;
}
bs->RegisterBluetoothSignalHandler(device->mPath, device);
return device.forget();
}

View File

@ -9,7 +9,6 @@
#include "BluetoothCommon.h"
#include "BluetoothAdapter.h"
#include "BluetoothService.h"
#include "BluetoothTypes.h"
#include "BluetoothReplyRunnable.h"
#include "nsContentUtils.h"
@ -20,6 +19,7 @@
#include "nsThreadUtils.h"
#include "nsXPCOMCIDInternal.h"
#include "mozilla/Util.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
using namespace mozilla;

View File

@ -1,16 +0,0 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "BluetoothService.h"
USING_BLUETOOTH_NAMESPACE
BluetoothService*
BluetoothService::Create()
{
NS_WARNING("Bluetooth not implemented for this platform!");
return nullptr;
}

View File

@ -7,8 +7,8 @@
#include "base/basictypes.h"
#include "BluetoothPropertyContainer.h"
#include "BluetoothService.h"
#include "BluetoothTypes.h"
#include "nsIDOMDOMRequest.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
USING_BLUETOOTH_NAMESPACE

View File

@ -6,9 +6,9 @@
#include "base/basictypes.h"
#include "BluetoothPropertyEvent.h"
#include "BluetoothTypes.h"
#include "nsDOMClassInfo.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
USING_BLUETOOTH_NAMESPACE

View File

@ -5,9 +5,9 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "base/basictypes.h"
#include "BluetoothTypes.h"
#include "BluetoothReplyRunnable.h"
#include "nsIDOMDOMRequest.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
USING_BLUETOOTH_NAMESPACE
@ -86,9 +86,9 @@ BluetoothReplyRunnable::Run()
}
ReleaseMembers();
if (mDOMRequest) {
NS_WARNING("mDOMRequest still alive! Deriving class should call BluetoothReplyRunnable::ReleaseMembers()!");
}
MOZ_ASSERT(!mDOMRequest,
"mDOMRequest still alive! Deriving class should call "
"BluetoothReplyRunnable::ReleaseMembers()!");
return rv;
}

View File

@ -7,33 +7,107 @@
#include "base/basictypes.h"
#include "BluetoothService.h"
#include "BluetoothManager.h"
#include "BluetoothTypes.h"
#include "BluetoothParent.h"
#include "BluetoothReplyRunnable.h"
#include "BluetoothServiceChildProcess.h"
#include "jsapi.h"
#include "mozilla/Services.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/unused.h"
#include "mozilla/Util.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
#include "nsContentUtils.h"
#include "nsIDOMDOMRequest.h"
#include "nsIObserverService.h"
#include "nsISettingsService.h"
#include "nsISystemMessagesInternal.h"
#include "nsITimer.h"
#include "nsThreadUtils.h"
#include "nsXPCOM.h"
#include "nsXPCOMCIDInternal.h"
#include "nsISystemMessagesInternal.h"
#include "nsXULAppAPI.h"
#if defined(MOZ_B2G_BT)
# if defined(MOZ_BLUETOOTH_GONK)
# include "BluetoothGonkService.h"
# elif defined(MOZ_BLUETOOTH_DBUS)
# include "BluetoothDBusService.h"
# else
# error No_suitable_backend_for_bluetooth!
# endif
#endif
#define MOZSETTINGS_CHANGED_ID "mozsettings-changed"
#define BLUETOOTH_ENABLED_SETTING "bluetooth.enabled"
using namespace mozilla;
#define DEFAULT_SHUTDOWN_TIMER_MS 5000
using namespace mozilla;
using namespace mozilla::dom;
USING_BLUETOOTH_NAMESPACE
static nsRefPtr<BluetoothService> gBluetoothService;
static bool gInShutdown = false;
namespace {
NS_IMPL_ISUPPORTS1(BluetoothService, nsIObserver)
StaticRefPtr<BluetoothService> gBluetoothService;
bool gInShutdown = false;
bool
IsMainProcess()
{
return XRE_GetProcessType() == GeckoProcessType_Default;
}
PLDHashOperator
RemoveAllSignalHandlers(const nsAString& aKey,
nsAutoPtr<BluetoothSignalObserverList>& aData,
void* aUserArg)
{
aData->RemoveObserver(static_cast<BluetoothSignalObserver*>(aUserArg));
return aData->Length() ? PL_DHASH_NEXT : PL_DHASH_REMOVE;
}
void
ShutdownTimeExceeded(nsITimer* aTimer, void* aClosure)
{
MOZ_ASSERT(NS_IsMainThread());
*static_cast<bool*>(aClosure) = true;
}
void
GetAllBluetoothActors(InfallibleTArray<BluetoothParent*>& aActors)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aActors.IsEmpty());
nsAutoTArray<ContentParent*, 20> contentActors;
ContentParent::GetAll(contentActors);
for (uint32_t contentIndex = 0;
contentIndex < contentActors.Length();
contentIndex++) {
MOZ_ASSERT(contentActors[contentIndex]);
AutoInfallibleTArray<PBluetoothParent*, 5> bluetoothActors;
contentActors[contentIndex]->ManagedPBluetoothParent(bluetoothActors);
for (uint32_t bluetoothIndex = 0;
bluetoothIndex < bluetoothActors.Length();
bluetoothIndex++) {
MOZ_ASSERT(bluetoothActors[bluetoothIndex]);
BluetoothParent* actor =
static_cast<BluetoothParent*>(bluetoothActors[bluetoothIndex]);
aActors.AppendElement(actor);
}
}
}
} // anonymous namespace
class BluetoothService::ToggleBtAck : public nsRunnable
{
@ -123,14 +197,19 @@ public:
NS_IMETHOD Handle(const nsAString& aName, const jsval& aResult, JSContext* aCx)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(gBluetoothService);
if (!aResult.isBoolean()) {
NS_WARNING("Setting for '" BLUETOOTH_ENABLED_SETTING "' is not a boolean!");
return NS_OK;
}
return aResult.toBoolean() ? gBluetoothService->Start() : NS_OK;
// It is theoretically possible to shut down before the first settings check
// has completed (though extremely unlikely).
if (gBluetoothService) {
return gBluetoothService->HandleStartupSettingsCheck(aResult.toBoolean());
}
return NS_OK;
}
NS_IMETHOD HandleError(const nsAString& aName, JSContext* aCx)
@ -142,71 +221,137 @@ public:
NS_IMPL_ISUPPORTS1(BluetoothService::StartupTask, nsISettingsServiceCallback);
NS_IMPL_ISUPPORTS1(BluetoothService, nsIObserver)
BluetoothService::~BluetoothService()
{
if (!gBluetoothService) {
return;
Cleanup();
}
// static
BluetoothService*
BluetoothService::Create()
{
#if defined(MOZ_B2G_BT)
if (!IsMainProcess()) {
return BluetoothServiceChildProcess::Create();
}
#endif
#if defined(MOZ_BLUETOOTH_GONK)
return new BluetoothGonkService();
#elif defined(MOZ_BLUETOOTH_DBUS)
return new BluetoothDBusService();
#else
NS_WARNING("No platform support for bluetooth!");
return nullptr;
#endif
}
bool
BluetoothService::Init()
{
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
NS_ENSURE_TRUE(obs, false);
if (NS_FAILED(obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID,
false))) {
NS_WARNING("Failed to add shutdown observer!");
return false;
}
if (NS_FAILED(gBluetoothService->UnregisterBluetoothSignalHandler(
NS_LITERAL_STRING(LOCAL_AGENT_PATH), gBluetoothService))) {
NS_WARNING("Unresgister observer to register local agent failed!");
// Only the main process should observe bluetooth settings changes.
if (IsMainProcess() &&
NS_FAILED(obs->AddObserver(this, MOZSETTINGS_CHANGED_ID, false))) {
NS_WARNING("Failed to add settings change observer!");
return false;
}
RegisterBluetoothSignalHandler(NS_LITERAL_STRING(LOCAL_AGENT_PATH), this);
mRegisteredForLocalAgent = true;
return true;
}
void
BluetoothService::Cleanup()
{
MOZ_ASSERT(NS_IsMainThread());
if (mRegisteredForLocalAgent) {
UnregisterBluetoothSignalHandler(NS_LITERAL_STRING(LOCAL_AGENT_PATH), this);
mRegisteredForLocalAgent = false;
}
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
if (obs &&
(NS_FAILED(obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) ||
NS_FAILED(obs->RemoveObserver(this, MOZSETTINGS_CHANGED_ID)))) {
NS_WARNING("Can't unregister observers!");
}
}
nsresult
void
BluetoothService::RegisterBluetoothSignalHandler(const nsAString& aNodeName,
BluetoothSignalObserver* aHandler)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aHandler);
BluetoothSignalObserverList* ol;
if (!mBluetoothSignalObserverTable.Get(aNodeName, &ol)) {
ol = new BluetoothSignalObserverList();
mBluetoothSignalObserverTable.Put(aNodeName, ol);
}
ol->AddObserver(aHandler);
return NS_OK;
}
nsresult
void
BluetoothService::UnregisterBluetoothSignalHandler(const nsAString& aNodeName,
BluetoothSignalObserver* aHandler)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aHandler);
BluetoothSignalObserverList* ol;
if (!mBluetoothSignalObserverTable.Get(aNodeName, &ol)) {
NS_WARNING("Node does not exist to remove BluetoothSignalListener from!");
return NS_OK;
if (mBluetoothSignalObserverTable.Get(aNodeName, &ol)) {
ol->RemoveObserver(aHandler);
if (ol->Length() == 0) {
mBluetoothSignalObserverTable.Remove(aNodeName);
}
}
ol->RemoveObserver(aHandler);
if (ol->Length() == 0) {
mBluetoothSignalObserverTable.Remove(aNodeName);
else {
NS_WARNING("Node was never registered!");
}
return NS_OK;
}
nsresult
BluetoothService::DistributeSignal(const BluetoothSignal& signal)
void
BluetoothService::UnregisterAllSignalHandlers(BluetoothSignalObserver* aHandler)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aHandler);
mBluetoothSignalObserverTable.Enumerate(RemoveAllSignalHandlers, aHandler);
}
void
BluetoothService::DistributeSignal(const BluetoothSignal& aSignal)
{
MOZ_ASSERT(NS_IsMainThread());
// Notify observers that a message has been sent
BluetoothSignalObserverList* ol;
if (!mBluetoothSignalObserverTable.Get(signal.path(), &ol)) {
if (!mBluetoothSignalObserverTable.Get(aSignal.path(), &ol)) {
#if DEBUG
nsString msg;
msg.AssignLiteral("No observer registered for path");
msg.Append(signal.path());
NS_WARNING(NS_ConvertUTF16toUTF8(msg).get());
nsAutoCString msg("No observer registered for path ");
msg.Append(NS_ConvertUTF16toUTF8(aSignal.path()));
NS_WARNING(msg.get());
#endif
return NS_OK;
return;
}
#if DEBUG
if (ol->Length() == 0) {
NS_WARNING("Distributing to observer list of 0");
}
#endif
ol->Broadcast(signal);
return NS_OK;
MOZ_ASSERT(ol->Length());
ol->Broadcast(aSignal);
}
nsresult
@ -267,32 +412,26 @@ BluetoothService::SetEnabled(bool aEnabled)
mEnabled = aEnabled;
AutoInfallibleTArray<BluetoothParent*, 10> childActors;
GetAllBluetoothActors(childActors);
for (uint32_t index = 0; index < childActors.Length(); index++) {
unused << childActors[index]->SendEnabled(aEnabled);
}
BluetoothManagerList::ForwardIterator iter(mLiveManagers);
while (iter.HasMore()) {
if (NS_FAILED(iter.GetNext()->FireEnabledDisabledEvent(mEnabled))) {
if (NS_FAILED(iter.GetNext()->FireEnabledDisabledEvent(aEnabled))) {
NS_WARNING("FireEnabledDisabledEvent failed!");
}
}
}
nsresult
BluetoothService::Start()
{
MOZ_ASSERT(NS_IsMainThread());
return StartStopBluetooth(true);
}
nsresult
BluetoothService::Stop()
{
MOZ_ASSERT(NS_IsMainThread());
return StartStopBluetooth(false);
}
nsresult
BluetoothService::HandleStartup()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mSettingsCheckInProgress);
nsCOMPtr<nsISettingsService> settings =
do_GetService("@mozilla.org/settingsService;1");
@ -306,6 +445,27 @@ BluetoothService::HandleStartup()
rv = settingsLock->Get(BLUETOOTH_ENABLED_SETTING, callback);
NS_ENSURE_SUCCESS(rv, rv);
mSettingsCheckInProgress = true;
return NS_OK;
}
nsresult
BluetoothService::HandleStartupSettingsCheck(bool aEnable)
{
MOZ_ASSERT(NS_IsMainThread());
if (!mSettingsCheckInProgress) {
// Somehow the enabled setting was changed before our first settings check
// completed. Don't do anything.
return NS_OK;
}
MOZ_ASSERT(!IsEnabled());
if (aEnable) {
return StartStopBluetooth(true);
}
return NS_OK;
}
@ -365,6 +525,13 @@ BluetoothService::HandleSettingsChanged(const nsAString& aData)
return NS_ERROR_UNEXPECTED;
}
if (mSettingsCheckInProgress) {
// Somehow the setting for bluetooth has been flipped before our first
// settings check completed. Flip this flag so that we ignore the result
// of that check whenever it finishes.
mSettingsCheckInProgress = false;
}
if (value.toBoolean() == IsEnabled()) {
// Nothing to do here.
return NS_OK;
@ -373,13 +540,13 @@ BluetoothService::HandleSettingsChanged(const nsAString& aData)
nsresult rv;
if (IsEnabled()) {
rv = Stop();
rv = StartStopBluetooth(false);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
rv = Start();
rv = StartStopBluetooth(true);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
@ -390,16 +557,64 @@ BluetoothService::HandleShutdown()
{
MOZ_ASSERT(NS_IsMainThread());
// This is a two phase shutdown. First we notify all child processes that
// bluetooth is going away, and then we wait for them to acknowledge. Then we
// close down all the bluetooth machinery.
gInShutdown = true;
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
if (obs &&
(NS_FAILED(obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) ||
NS_FAILED(obs->RemoveObserver(this, MOZSETTINGS_CHANGED_ID)))) {
NS_WARNING("Can't unregister observers!");
Cleanup();
AutoInfallibleTArray<BluetoothParent*, 10> childActors;
GetAllBluetoothActors(childActors);
if (!childActors.IsEmpty()) {
// Notify child processes that they should stop using bluetooth now.
for (uint32_t index = 0; index < childActors.Length(); index++) {
childActors[index]->BeginShutdown();
}
// Create a timer to ensure that we don't wait forever for a child process
// or the bluetooth threads to finish. If we don't get a timer or can't use
// it for some reason then we skip all the waiting entirely since we really
// can't afford to hang on shutdown.
nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID);
MOZ_ASSERT(timer);
if (timer) {
bool timeExceeded = false;
if (NS_SUCCEEDED(timer->InitWithFuncCallback(ShutdownTimeExceeded,
&timeExceeded,
DEFAULT_SHUTDOWN_TIMER_MS,
nsITimer::TYPE_ONE_SHOT))) {
nsIThread* currentThread = NS_GetCurrentThread();
MOZ_ASSERT(currentThread);
// Wait for those child processes to acknowledge.
while (!timeExceeded && !childActors.IsEmpty()) {
if (!NS_ProcessNextEvent(currentThread)) {
MOZ_ASSERT(false, "Something horribly wrong here!");
break;
}
GetAllBluetoothActors(childActors);
}
if (NS_FAILED(timer->Cancel())) {
MOZ_NOT_REACHED("Failed to cancel shutdown timer, this will crash!");
}
}
else {
MOZ_ASSERT(false, "Failed to initialize shutdown timer!");
}
}
}
return Stop();
if (IsEnabled() && NS_FAILED(StartStopBluetooth(false))) {
MOZ_ASSERT(false, "Failed to deliver stop message!");
}
return NS_OK;
}
void
@ -445,24 +660,12 @@ BluetoothService::Get()
nsRefPtr<BluetoothService> service = BluetoothService::Create();
NS_ENSURE_TRUE(service, nullptr);
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
NS_ENSURE_TRUE(obs, nullptr);
if (NS_FAILED(obs->AddObserver(service, NS_XPCOM_SHUTDOWN_OBSERVER_ID,
false)) ||
NS_FAILED(obs->AddObserver(service, MOZSETTINGS_CHANGED_ID, false))) {
NS_WARNING("AddObserver failed!");
return nullptr;
}
gBluetoothService.swap(service);
if (NS_FAILED(gBluetoothService->RegisterBluetoothSignalHandler(
NS_LITERAL_STRING(LOCAL_AGENT_PATH), gBluetoothService))) {
NS_WARNING("Resgister observer to register local agent failed!");
if (!service->Init()) {
service->Cleanup();
return nullptr;
}
gBluetoothService = service;
return gBluetoothService;
}

View File

@ -21,6 +21,8 @@ class BluetoothNamedValue;
class BluetoothReplyRunnable;
class BluetoothSignal;
typedef mozilla::ObserverList<BluetoothSignal> BluetoothSignalObserverList;
class BluetoothService : public nsIObserver
, public BluetoothSignalObserver
{
@ -43,12 +45,10 @@ public:
*
* @param aNodeName Node name of the object
* @param aMsgHandler Weak pointer to the object
*
* @return NS_OK on successful addition to observer, NS_ERROR_FAILED
* otherwise
*/
nsresult RegisterBluetoothSignalHandler(const nsAString& aNodeName,
BluetoothSignalObserver* aMsgHandler);
virtual void
RegisterBluetoothSignalHandler(const nsAString& aNodeName,
BluetoothSignalObserver* aMsgHandler);
/**
* Remove a message handler object from message distribution observer.
@ -56,12 +56,19 @@ public:
*
* @param aNodeName Node name of the object
* @param aMsgHandler Weak pointer to the object
*
* @return NS_OK on successful removal from observer service,
* NS_ERROR_FAILED otherwise
*/
nsresult UnregisterBluetoothSignalHandler(const nsAString& aNodeName,
BluetoothSignalObserver* aMsgHandler);
virtual void
UnregisterBluetoothSignalHandler(const nsAString& aNodeName,
BluetoothSignalObserver* aMsgHandler);
/**
* Remove a message handlers for the given observer.
* Must be called from the main thread.
*
* @param aMsgHandler Weak pointer to the object
*/
void
UnregisterAllSignalHandlers(BluetoothSignalObserver* aMsgHandler);
/**
* Distribute a signal to the observer list
@ -70,59 +77,27 @@ public:
*
* @return NS_OK if signal distributed, NS_ERROR_FAILURE on error
*/
nsresult DistributeSignal(const BluetoothSignal& aEvent);
/**
* Start bluetooth services. Starts up any threads and connections that
* bluetooth needs to operate on the current platform. Assumed to be run on
* the main thread with delayed return for blocking startup functions via
* runnable.
* @return NS_OK on initialization starting correctly, NS_ERROR_FAILURE
* otherwise
*/
nsresult Start();
/**
* Stop bluetooth services. Starts up any threads and connections that
* bluetooth needs to operate on the current platform. Assumed to be run on
* the main thread with delayed return for blocking startup functions via
* runnable.
*
* @return NS_OK on initialization starting correctly, NS_ERROR_FAILURE
* otherwise
*/
nsresult Stop();
/**
* Called when XPCOM first creates this service.
*/
nsresult HandleStartup();
/**
* Called when "mozsettings-changed" observer topic fires.
*/
nsresult HandleSettingsChanged(const nsAString& aData);
/**
* Called when XPCOM is shutting down.
*/
nsresult HandleShutdown();
void
DistributeSignal(const BluetoothSignal& aEvent);
/**
* Called when a BluetoothManager is created.
*/
void RegisterManager(BluetoothManager* aManager);
void
RegisterManager(BluetoothManager* aManager);
/**
* Called when a BluetoothManager is destroyed.
*/
void UnregisterManager(BluetoothManager* aManager);
void
UnregisterManager(BluetoothManager* aManager);
/**
* Called when get a Bluetooth Signal from BluetoothDBusService
*
*/
void Notify(const BluetoothSignal& aParam);
void
Notify(const BluetoothSignal& aParam);
/**
* Returns the BluetoothService singleton. Only to be called from main thread.
@ -132,9 +107,11 @@ public:
* @return NS_OK on proper assignment, NS_ERROR_FAILURE otherwise (if service
* has not yet been started, for instance)
*/
static BluetoothService* Get();
static BluetoothService*
Get();
static already_AddRefed<BluetoothService> FactoryCreate()
static already_AddRefed<BluetoothService>
FactoryCreate()
{
nsRefPtr<BluetoothService> service = Get();
return service.forget();
@ -146,7 +123,8 @@ public:
*
* @return Default adapter path/name on success, NULL otherwise
*/
virtual nsresult GetDefaultAdapterPathInternal(BluetoothReplyRunnable* aRunnable) = 0;
virtual nsresult
GetDefaultAdapterPathInternal(BluetoothReplyRunnable* aRunnable) = 0;
/**
* Returns the properties of paired devices, implemented via a platform
@ -154,8 +132,9 @@ public:
*
* @return NS_OK on success, NS_ERROR_FAILURE otherwise
*/
virtual nsresult GetPairedDevicePropertiesInternal(const nsTArray<nsString>& aDeviceAddresses,
BluetoothReplyRunnable* aRunnable) = 0;
virtual nsresult
GetPairedDevicePropertiesInternal(const nsTArray<nsString>& aDeviceAddresses,
BluetoothReplyRunnable* aRunnable) = 0;
/**
* Stop device discovery (platform specific implementation)
@ -164,8 +143,9 @@ public:
*
* @return NS_OK if discovery stopped correctly, false otherwise
*/
virtual nsresult StopDiscoveryInternal(const nsAString& aAdapterPath,
BluetoothReplyRunnable* aRunnable) = 0;
virtual nsresult
StopDiscoveryInternal(const nsAString& aAdapterPath,
BluetoothReplyRunnable* aRunnable) = 0;
/**
* Start device discovery (platform specific implementation)
@ -174,24 +154,9 @@ public:
*
* @return NS_OK if discovery stopped correctly, false otherwise
*/
virtual nsresult StartDiscoveryInternal(const nsAString& aAdapterPath,
BluetoothReplyRunnable* aRunnable) = 0;
/**
* Platform specific startup functions go here. Usually deals with member
* variables, so not static. Guaranteed to be called outside of main thread.
*
* @return NS_OK on correct startup, NS_ERROR_FAILURE otherwise
*/
virtual nsresult StartInternal() = 0;
/**
* Platform specific startup functions go here. Usually deals with member
* variables, so not static. Guaranteed to be called outside of main thread.
*
* @return NS_OK on correct startup, NS_ERROR_FAILURE otherwise
*/
virtual nsresult StopInternal() = 0;
virtual nsresult
StartDiscoveryInternal(const nsAString& aAdapterPath,
BluetoothReplyRunnable* aRunnable) = 0;
/**
* Fetches the propertes for the specified object
@ -268,19 +233,28 @@ public:
virtual bool
CloseSocket(int aFd, BluetoothReplyRunnable* aRunnable) = 0;
virtual bool SetPinCodeInternal(const nsAString& aDeviceAddress, const nsAString& aPinCode) = 0;
virtual bool SetPasskeyInternal(const nsAString& aDeviceAddress, uint32_t aPasskey) = 0;
virtual bool SetPairingConfirmationInternal(const nsAString& aDeviceAddress, bool aConfirm) = 0;
virtual bool SetAuthorizationInternal(const nsAString& aDeviceAddress, bool aAllow) = 0;
virtual bool
SetPinCodeInternal(const nsAString& aDeviceAddress, const nsAString& aPinCode) = 0;
virtual bool IsEnabled()
virtual bool
SetPasskeyInternal(const nsAString& aDeviceAddress, uint32_t aPasskey) = 0;
virtual bool
SetPairingConfirmationInternal(const nsAString& aDeviceAddress, bool aConfirm) = 0;
virtual bool
SetAuthorizationInternal(const nsAString& aDeviceAddress, bool aAllow) = 0;
bool
IsEnabled() const
{
return mEnabled;
}
protected:
BluetoothService()
: mEnabled(false)
: mEnabled(false), mSettingsCheckInProgress(false),
mRegisteredForLocalAgent(false)
#ifdef DEBUG
, mLastRequestedEnable(false)
#endif
@ -288,16 +262,66 @@ protected:
mBluetoothSignalObserverTable.Init();
}
~BluetoothService();
virtual ~BluetoothService();
nsresult StartStopBluetooth(bool aStart);
bool
Init();
void
Cleanup();
nsresult
StartStopBluetooth(bool aStart);
/**
* Platform specific startup functions go here. Usually deals with member
* variables, so not static. Guaranteed to be called outside of main thread.
*
* @return NS_OK on correct startup, NS_ERROR_FAILURE otherwise
*/
virtual nsresult
StartInternal() = 0;
/**
* Platform specific startup functions go here. Usually deals with member
* variables, so not static. Guaranteed to be called outside of main thread.
*
* @return NS_OK on correct startup, NS_ERROR_FAILURE otherwise
*/
virtual nsresult
StopInternal() = 0;
/**
* Called when XPCOM first creates this service.
*/
virtual nsresult
HandleStartup();
/**
* Called when the startup settings check has completed.
*/
nsresult
HandleStartupSettingsCheck(bool aEnable);
/**
* Called when "mozsettings-changed" observer topic fires.
*/
nsresult
HandleSettingsChanged(const nsAString& aData);
/**
* Called when XPCOM is shutting down.
*/
virtual nsresult
HandleShutdown();
// Called by ToggleBtAck.
void SetEnabled(bool aEnabled);
void
SetEnabled(bool aEnabled);
// This function is implemented in platform-specific BluetoothServiceFactory
// files
static BluetoothService* Create();
// Called by Get().
static BluetoothService*
Create();
/**
* Due to the fact that some operations require multiple calls, a
@ -313,7 +337,6 @@ protected:
*/
nsCOMPtr<nsIThread> mBluetoothCommandThread;
typedef mozilla::ObserverList<BluetoothSignal> BluetoothSignalObserverList;
typedef nsClassHashtable<nsStringHashKey, BluetoothSignalObserverList >
BluetoothSignalObserverTable;
@ -323,6 +346,9 @@ protected:
BluetoothManagerList mLiveManagers;
bool mEnabled;
bool mSettingsCheckInProgress;
bool mRegisteredForLocalAgent;
#ifdef DEBUG
bool mLastRequestedEnable;
#endif

View File

@ -18,6 +18,19 @@ srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/dom/dom-config.mk
VPATH += $(srcdir)/ipc
EXPORTS_NAMESPACES = \
mozilla/dom/bluetooth \
mozilla/dom/bluetooth/ipc \
$(NULL)
EXPORTS_mozilla/dom/bluetooth = BluetoothCommon.h
EXPORTS_mozilla/dom/bluetooth/ipc = BluetoothMessageUtils.h
ifneq (,$(MOZ_B2G_BT))
MODULE = dom
LIBRARY_NAME = dombluetooth_s
@ -25,8 +38,6 @@ XPIDL_MODULE = dom_bluetooth
LIBXUL_LIBRARY = 1
FORCE_STATIC_LIB = 1
include $(topsrcdir)/dom/dom-config.mk
CPPSRCS += \
BluetoothService.cpp \
BluetoothManager.cpp \
@ -36,6 +47,9 @@ CPPSRCS += \
BluetoothReplyRunnable.cpp \
BluetoothPropertyContainer.cpp \
BluetoothUtils.cpp \
BluetoothChild.cpp \
BluetoothParent.cpp \
BluetoothServiceChildProcess.cpp \
$(NULL)
XPIDLSRCS = \
@ -50,42 +64,32 @@ XPIDLSRCS = \
ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
VPATH += \
$(srcdir)/linux \
$(srcdir)/gonk \
$(NULL)
$(srcdir)/linux \
$(srcdir)/gonk \
$(NULL)
LOCAL_INCLUDES += $(MOZ_DBUS_CFLAGS)
CPPSRCS += \
BluetoothDBusService.cpp \
BluetoothGonkService.cpp \
BluetoothGonkServiceFactory.cpp \
$(NULL)
BluetoothDBusService.cpp \
BluetoothGonkService.cpp \
$(NULL)
DEFINES += -DMOZ_BLUETOOTH_GONK
else
ifdef MOZ_ENABLE_DBUS
VPATH += $(srcdir)/linux
LOCAL_INCLUDES += $(MOZ_DBUS_CFLAGS)
CPPSRCS += \
BluetoothDBusService.cpp \
BluetoothDBusServiceFactory.cpp \
$(NULL)
CPPSRCS += BluetoothDBusService.cpp
CFLAGS += $(MOZ_DBUS_GLIB_CFLAGS)
CXXFLAGS += $(MOZ_DBUS_GLIB_CFLAGS) -DHAVE_PTHREADS
else
CPPSRCS += BluetoothNullServiceFactory.cpp
DEFINES += -DMOZ_BLUETOOTH_DBUS
endif
endif
LOCAL_INCLUDES += -I$(DEPTH)/ipc/ipdl/_ipdlheaders/mozilla/dom/bluetooth/
# Add VPATH to LOCAL_INCLUDES so we are going to include the correct backend
# subdirectory
# subdirectory.
LOCAL_INCLUDES += $(VPATH:%=-I%)
endif # MOZ_B2G_BT
include $(topsrcdir)/config/config.mk
include $(topsrcdir)/ipc/chromium/chromium-config.mk
include $(topsrcdir)/config/rules.mk
XPIDL_FLAGS += \
-I$(topsrcdir)/dom/interfaces/base \
-I$(topsrcdir)/dom/interfaces/events \
$(NULL)

View File

@ -129,16 +129,6 @@ StartStopGonkBluetooth(bool aShouldEnable)
return NS_OK;
}
int
BluetoothGonkService::IsEnabledInternal()
{
if (!EnsureBluetoothInit()) {
NS_ERROR("Failed to load bluedroid library.\n");
return false;
}
return IsBluetoothEnabled();
}
nsresult
BluetoothGonkService::StartInternal()
{
@ -149,7 +139,7 @@ BluetoothGonkService::StartInternal()
ret = StartStopGonkBluetooth(true);
if (NS_FAILED(ret)) {
return ret;
return ret;
}
return BluetoothDBusService::StartInternal();
@ -165,7 +155,7 @@ BluetoothGonkService::StopInternal()
ret = BluetoothDBusService::StopInternal();
if (NS_FAILED(ret)) {
return ret;
return ret;
}
return StartStopGonkBluetooth(false);

View File

@ -25,7 +25,7 @@ BEGIN_BLUETOOTH_NAMESPACE
/**
* BluetoothService functions are used to dispatch messages to Bluetooth DOM
* objects on the main thread, as well as provide platform indenpendent access
* objects on the main thread, as well as provide platform independent access
* to BT functionality. Tasks for polling for outside messages will usually
* happen on the IO Thread (see ipc/dbus for instance), and these messages will
* be encased in runnables that will then be distributed via observers managed
@ -52,11 +52,6 @@ public:
* otherwise
*/
virtual nsresult StopInternal();
/**
* @return true if bluetooth daemon is enabled, false otherwise
*/
virtual int IsEnabledInternal();
};
END_BLUETOOTH_NAMESPACE

View File

@ -1,26 +0,0 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* Copyright 2012 Mozilla Foundation and Mozilla contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "BluetoothGonkService.h"
USING_BLUETOOTH_NAMESPACE
BluetoothService*
BluetoothService::Create()
{
return new BluetoothGonkService();
}

View File

@ -0,0 +1,168 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "base/basictypes.h"
#include "BluetoothChild.h"
#include "mozilla/Assertions.h"
#include "nsDebug.h"
#include "nsThreadUtils.h"
#include "nsTraceRefcnt.h"
#include "BluetoothReplyRunnable.h"
#include "BluetoothService.h"
#include "BluetoothServiceChildProcess.h"
USING_BLUETOOTH_NAMESPACE
namespace {
BluetoothServiceChildProcess* gBluetoothService;
} // anonymous namespace
/*******************************************************************************
* BluetoothChild
******************************************************************************/
BluetoothChild::BluetoothChild(BluetoothServiceChildProcess* aBluetoothService)
: mShutdownState(Running)
{
MOZ_COUNT_CTOR(BluetoothChild);
MOZ_ASSERT(!gBluetoothService);
MOZ_ASSERT(aBluetoothService);
gBluetoothService = aBluetoothService;
}
BluetoothChild::~BluetoothChild()
{
MOZ_COUNT_DTOR(BluetoothChild);
MOZ_ASSERT(gBluetoothService);
MOZ_ASSERT(mShutdownState == Dead);
gBluetoothService = nullptr;
}
void
BluetoothChild::BeginShutdown()
{
// Only do something here if we haven't yet begun the shutdown sequence.
if (mShutdownState == Running) {
SendStopNotifying();
mShutdownState = SentStopNotifying;
}
}
void
BluetoothChild::ActorDestroy(ActorDestroyReason aWhy)
{
MOZ_ASSERT(gBluetoothService);
gBluetoothService->NoteDeadActor();
#ifdef DEBUG
mShutdownState = Dead;
#endif
}
bool
BluetoothChild::RecvNotify(const BluetoothSignal& aSignal)
{
MOZ_ASSERT(gBluetoothService);
gBluetoothService->DistributeSignal(aSignal);
return true;
}
bool
BluetoothChild::RecvEnabled(const bool& aEnabled)
{
MOZ_ASSERT(gBluetoothService);
gBluetoothService->SetEnabled(aEnabled);
return true;
}
bool
BluetoothChild::RecvBeginShutdown()
{
if (mShutdownState != Running && mShutdownState != SentStopNotifying) {
MOZ_ASSERT(false, "Bad state!");
return false;
}
SendStopNotifying();
mShutdownState = SentStopNotifying;
return true;
}
bool
BluetoothChild::RecvNotificationsStopped()
{
if (mShutdownState != SentStopNotifying) {
MOZ_ASSERT(false, "Bad state!");
return false;
}
Send__delete__(this);
return true;
}
PBluetoothRequestChild*
BluetoothChild::AllocPBluetoothRequest(const Request& aRequest)
{
MOZ_NOT_REACHED("Caller is supposed to manually construct a request!");
return nullptr;
}
bool
BluetoothChild::DeallocPBluetoothRequest(PBluetoothRequestChild* aActor)
{
delete aActor;
return true;
}
/*******************************************************************************
* BluetoothRequestChild
******************************************************************************/
BluetoothRequestChild::BluetoothRequestChild(
BluetoothReplyRunnable* aReplyRunnable)
: mReplyRunnable(aReplyRunnable)
{
MOZ_COUNT_CTOR(BluetoothRequestChild);
MOZ_ASSERT(aReplyRunnable);
}
BluetoothRequestChild::~BluetoothRequestChild()
{
MOZ_COUNT_DTOR(BluetoothRequestChild);
}
void
BluetoothRequestChild::ActorDestroy(ActorDestroyReason aWhy)
{
// Nothing needed here.
}
bool
BluetoothRequestChild::Recv__delete__(const BluetoothReply& aReply)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mReplyRunnable);
nsRefPtr<BluetoothReplyRunnable> replyRunnable;
mReplyRunnable.swap(replyRunnable);
if (replyRunnable) {
// XXXbent Need to fix this, it copies unnecessarily.
replyRunnable->SetReply(new BluetoothReply(aReply));
return NS_SUCCEEDED(NS_DispatchToCurrentThread(replyRunnable));
}
return true;
}

View File

@ -0,0 +1,103 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_bluetooth_ipc_bluetoothchild_h__
#define mozilla_dom_bluetooth_ipc_bluetoothchild_h__
#include "mozilla/dom/bluetooth/BluetoothCommon.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
#include "mozilla/dom/bluetooth/PBluetoothChild.h"
#include "mozilla/dom/bluetooth/PBluetoothRequestChild.h"
#include "mozilla/Attributes.h"
#include "nsAutoPtr.h"
namespace mozilla {
namespace dom {
namespace bluetooth {
class BluetoothServiceChildProcess;
} // namespace bluetooth
} // namespace dom
} // namespace mozilla
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothReplyRunnable;
/*******************************************************************************
* BluetoothChild
******************************************************************************/
class BluetoothChild : public PBluetoothChild
{
friend class mozilla::dom::bluetooth::BluetoothServiceChildProcess;
enum ShutdownState
{
Running = 0,
SentStopNotifying,
ReceivedNotificationsStopped,
Dead
};
ShutdownState mShutdownState;
protected:
BluetoothChild(BluetoothServiceChildProcess* aBluetoothService);
virtual ~BluetoothChild();
void
BeginShutdown();
virtual void
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
virtual bool
RecvNotify(const BluetoothSignal& aSignal);
virtual bool
RecvEnabled(const bool& aEnabled) MOZ_OVERRIDE;
virtual bool
RecvBeginShutdown() MOZ_OVERRIDE;
virtual bool
RecvNotificationsStopped() MOZ_OVERRIDE;
virtual PBluetoothRequestChild*
AllocPBluetoothRequest(const Request& aRequest) MOZ_OVERRIDE;
virtual bool
DeallocPBluetoothRequest(PBluetoothRequestChild* aActor) MOZ_OVERRIDE;
};
/*******************************************************************************
* BluetoothRequestChild
******************************************************************************/
class BluetoothRequestChild : public PBluetoothRequestChild
{
friend class mozilla::dom::bluetooth::BluetoothChild;
nsRefPtr<BluetoothReplyRunnable> mReplyRunnable;
public:
BluetoothRequestChild(BluetoothReplyRunnable* aReplyRunnable);
protected:
virtual ~BluetoothRequestChild();
virtual void
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
virtual bool
Recv__delete__(const BluetoothReply& aReply) MOZ_OVERRIDE;
};
END_BLUETOOTH_NAMESPACE
#endif // mozilla_dom_bluetooth_ipc_bluetoothchild_h__

View File

@ -0,0 +1,22 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_bluetooth_ipc_bluetoothmessageutils_h__
#define mozilla_dom_bluetooth_ipc_bluetoothmessageutils_h__
#include "mozilla/dom/bluetooth/BluetoothCommon.h"
#include "ipc/IPCMessageUtils.h"
namespace IPC {
template <>
struct ParamTraits<mozilla::dom::bluetooth::BluetoothObjectType>
: public EnumSerializer<mozilla::dom::bluetooth::BluetoothObjectType,
mozilla::dom::bluetooth::TYPE_MANAGER,
mozilla::dom::bluetooth::TYPE_INVALID>
{ };
} // namespace IPC
#endif // mozilla_dom_bluetooth_ipc_bluetoothchild_h__

View File

@ -0,0 +1,377 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "base/basictypes.h"
#include "BluetoothParent.h"
#include "mozilla/Assertions.h"
#include "mozilla/unused.h"
#include "mozilla/Util.h"
#include "nsDebug.h"
#include "nsThreadUtils.h"
#include "nsTraceRefcnt.h"
#include "BluetoothReplyRunnable.h"
#include "BluetoothService.h"
using mozilla::unused;
USING_BLUETOOTH_NAMESPACE
/*******************************************************************************
* BluetoothRequestParent::ReplyRunnable
******************************************************************************/
class BluetoothRequestParent::ReplyRunnable : public BluetoothReplyRunnable
{
BluetoothRequestParent* mRequest;
public:
ReplyRunnable(BluetoothRequestParent* aRequest)
: BluetoothReplyRunnable(nullptr), mRequest(aRequest)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aRequest);
}
NS_IMETHOD
Run() MOZ_OVERRIDE
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mReply);
if (mRequest) {
// Must do this first because Send__delete__ will delete mRequest.
mRequest->RequestComplete();
if (!mRequest->Send__delete__(mRequest, *mReply)) {
NS_WARNING("Failed to send response to child process!");
return NS_ERROR_FAILURE;
}
}
ReleaseMembers();
return NS_OK;
}
void
Revoke()
{
MOZ_ASSERT(NS_IsMainThread());
mRequest = nullptr;
}
virtual bool
ParseSuccessfulReply(jsval* aValue) MOZ_OVERRIDE
{
MOZ_NOT_REACHED("This should never be called!");
return false;
}
};
/*******************************************************************************
* BluetoothParent
******************************************************************************/
BluetoothParent::BluetoothParent()
: mShutdownState(Running)
{
MOZ_COUNT_CTOR(BluetoothParent);
}
BluetoothParent::~BluetoothParent()
{
MOZ_COUNT_DTOR(BluetoothParent);
MOZ_ASSERT(!mService);
MOZ_ASSERT(mShutdownState == Dead);
}
void
BluetoothParent::BeginShutdown()
{
// Only do something here if we haven't yet begun the shutdown sequence.
if (mShutdownState == Running) {
unused << SendBeginShutdown();
mShutdownState = SentBeginShutdown;
}
}
bool
BluetoothParent::InitWithService(BluetoothService* aService)
{
MOZ_ASSERT(aService);
MOZ_ASSERT(!mService);
if (!SendEnabled(aService->IsEnabled())) {
return false;
}
mService = aService;
return true;
}
void
BluetoothParent::UnregisterAllSignalHandlers()
{
MOZ_ASSERT(mService);
mService->UnregisterAllSignalHandlers(this);
}
void
BluetoothParent::ActorDestroy(ActorDestroyReason aWhy)
{
if (mService) {
UnregisterAllSignalHandlers();
#ifdef DEBUG
mService = nullptr;
#endif
}
#ifdef DEBUG
mShutdownState = Dead;
#endif
}
bool
BluetoothParent::RecvRegisterSignalHandler(const nsString& aNode)
{
MOZ_ASSERT(mService);
mService->RegisterBluetoothSignalHandler(aNode, this);
return true;
}
bool
BluetoothParent::RecvUnregisterSignalHandler(const nsString& aNode)
{
MOZ_ASSERT(mService);
mService->UnregisterBluetoothSignalHandler(aNode, this);
return true;
}
bool
BluetoothParent::RecvStopNotifying()
{
MOZ_ASSERT(mService);
if (mShutdownState != Running && mShutdownState != SentBeginShutdown) {
MOZ_ASSERT(false, "Bad state!");
return false;
}
mShutdownState = ReceivedStopNotifying;
UnregisterAllSignalHandlers();
if (SendNotificationsStopped()) {
mShutdownState = SentNotificationsStopped;
return true;
}
return false;
}
bool
BluetoothParent::RecvPBluetoothRequestConstructor(
PBluetoothRequestParent* aActor,
const Request& aRequest)
{
BluetoothRequestParent* actor = static_cast<BluetoothRequestParent*>(aActor);
#ifdef DEBUG
actor->mRequestType = aRequest.type();
#endif
switch (aRequest.type()) {
case Request::TDefaultAdapterPathRequest:
return actor->DoRequest(aRequest.get_DefaultAdapterPathRequest());
case Request::TSetPropertyRequest:
return actor->DoRequest(aRequest.get_SetPropertyRequest());
case Request::TGetPropertyRequest:
return actor->DoRequest(aRequest.get_GetPropertyRequest());
case Request::TStartDiscoveryRequest:
return actor->DoRequest(aRequest.get_StartDiscoveryRequest());
case Request::TStopDiscoveryRequest:
return actor->DoRequest(aRequest.get_StopDiscoveryRequest());
case Request::TPairRequest:
return actor->DoRequest(aRequest.get_PairRequest());
case Request::TUnpairRequest:
return actor->DoRequest(aRequest.get_UnpairRequest());
case Request::TDevicePropertiesRequest:
return actor->DoRequest(aRequest.get_DevicePropertiesRequest());
default:
MOZ_NOT_REACHED("Unknown type!");
return false;
}
MOZ_NOT_REACHED("Should never get here!");
return false;
}
PBluetoothRequestParent*
BluetoothParent::AllocPBluetoothRequest(const Request& aRequest)
{
MOZ_ASSERT(mService);
return new BluetoothRequestParent(mService);
}
bool
BluetoothParent::DeallocPBluetoothRequest(PBluetoothRequestParent* aActor)
{
delete aActor;
return true;
}
void
BluetoothParent::Notify(const BluetoothSignal& aSignal)
{
unused << SendNotify(aSignal);
}
/*******************************************************************************
* BluetoothRequestParent
******************************************************************************/
BluetoothRequestParent::BluetoothRequestParent(BluetoothService* aService)
: mService(aService)
#ifdef DEBUG
, mRequestType(Request::T__None)
#endif
{
MOZ_COUNT_CTOR(BluetoothRequestParent);
MOZ_ASSERT(aService);
mReplyRunnable = new ReplyRunnable(this);
}
BluetoothRequestParent::~BluetoothRequestParent()
{
MOZ_COUNT_DTOR(BluetoothRequestParent);
// mReplyRunnable will be automatically revoked.
}
void
BluetoothRequestParent::ActorDestroy(ActorDestroyReason aWhy)
{
mReplyRunnable.Revoke();
}
void
BluetoothRequestParent::RequestComplete()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mReplyRunnable.IsPending());
mReplyRunnable.Forget();
}
bool
BluetoothRequestParent::DoRequest(const DefaultAdapterPathRequest& aRequest)
{
MOZ_ASSERT(mService);
MOZ_ASSERT(mRequestType == Request::TDefaultAdapterPathRequest);
nsresult rv = mService->GetDefaultAdapterPathInternal(mReplyRunnable.get());
NS_ENSURE_SUCCESS(rv, false);
return true;
}
bool
BluetoothRequestParent::DoRequest(const SetPropertyRequest& aRequest)
{
MOZ_ASSERT(mService);
MOZ_ASSERT(mRequestType == Request::TSetPropertyRequest);
nsresult rv =
mService->SetProperty(aRequest.type(), aRequest.path(), aRequest.value(),
mReplyRunnable.get());
NS_ENSURE_SUCCESS(rv, false);
return true;
}
bool
BluetoothRequestParent::DoRequest(const GetPropertyRequest& aRequest)
{
MOZ_ASSERT(mService);
MOZ_ASSERT(mRequestType == Request::TGetPropertyRequest);
nsresult rv =
mService->GetProperties(aRequest.type(), aRequest.path(),
mReplyRunnable.get());
NS_ENSURE_SUCCESS(rv, false);
return true;
}
bool
BluetoothRequestParent::DoRequest(const StartDiscoveryRequest& aRequest)
{
MOZ_ASSERT(mService);
MOZ_ASSERT(mRequestType == Request::TStartDiscoveryRequest);
nsresult rv =
mService->StartDiscoveryInternal(aRequest.path(), mReplyRunnable.get());
NS_ENSURE_SUCCESS(rv, false);
return true;
}
bool
BluetoothRequestParent::DoRequest(const StopDiscoveryRequest& aRequest)
{
MOZ_ASSERT(mService);
MOZ_ASSERT(mRequestType == Request::TStopDiscoveryRequest);
nsresult rv =
mService->StopDiscoveryInternal(aRequest.path(), mReplyRunnable.get());
NS_ENSURE_SUCCESS(rv, false);
return true;
}
bool
BluetoothRequestParent::DoRequest(const PairRequest& aRequest)
{
MOZ_ASSERT(mService);
MOZ_ASSERT(mRequestType == Request::TPairRequest);
nsresult rv =
mService->CreatePairedDeviceInternal(aRequest.path(), aRequest.address(),
aRequest.timeoutMS(),
mReplyRunnable.get());
NS_ENSURE_SUCCESS(rv, false);
return true;
}
bool
BluetoothRequestParent::DoRequest(const UnpairRequest& aRequest)
{
MOZ_ASSERT(mService);
MOZ_ASSERT(mRequestType == Request::TUnpairRequest);
nsresult rv =
mService->RemoveDeviceInternal(aRequest.path(), aRequest.address(),
mReplyRunnable.get());
NS_ENSURE_SUCCESS(rv, false);
return true;
}
bool
BluetoothRequestParent::DoRequest(const DevicePropertiesRequest& aRequest)
{
MOZ_ASSERT(mService);
MOZ_ASSERT(mRequestType == Request::TDevicePropertiesRequest);
nsresult rv =
mService->GetPairedDevicePropertiesInternal(aRequest.addresses(),
mReplyRunnable.get());
NS_ENSURE_SUCCESS(rv, false);
return true;
}

View File

@ -0,0 +1,152 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_bluetooth_ipc_bluetoothparent_h__
#define mozilla_dom_bluetooth_ipc_bluetoothparent_h__
#include "mozilla/dom/bluetooth/BluetoothCommon.h"
#include "mozilla/dom/bluetooth/PBluetoothParent.h"
#include "mozilla/dom/bluetooth/PBluetoothRequestParent.h"
#include "mozilla/Attributes.h"
#include "mozilla/Observer.h"
#include "nsAutoPtr.h"
#include "nsTArray.h"
template <class T>
class nsRevocableEventPtr;
namespace mozilla {
namespace dom {
class ContentParent;
} // namespace dom
} // namespace mozilla
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothService;
/*******************************************************************************
* BluetoothParent
******************************************************************************/
class BluetoothParent : public PBluetoothParent,
public mozilla::Observer<BluetoothSignal>
{
friend class mozilla::dom::ContentParent;
enum ShutdownState
{
Running = 0,
SentBeginShutdown,
ReceivedStopNotifying,
SentNotificationsStopped,
Dead
};
nsRefPtr<BluetoothService> mService;
ShutdownState mShutdownState;
bool mReceivedStopNotifying;
bool mSentBeginShutdown;
public:
void
BeginShutdown();
protected:
BluetoothParent();
virtual ~BluetoothParent();
bool
InitWithService(BluetoothService* aService);
virtual void
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
virtual bool
RecvRegisterSignalHandler(const nsString& aNode) MOZ_OVERRIDE;
virtual bool
RecvUnregisterSignalHandler(const nsString& aNode) MOZ_OVERRIDE;
virtual bool
RecvStopNotifying() MOZ_OVERRIDE;
virtual bool
RecvPBluetoothRequestConstructor(PBluetoothRequestParent* aActor,
const Request& aRequest) MOZ_OVERRIDE;
virtual PBluetoothRequestParent*
AllocPBluetoothRequest(const Request& aRequest) MOZ_OVERRIDE;
virtual bool
DeallocPBluetoothRequest(PBluetoothRequestParent* aActor) MOZ_OVERRIDE;
virtual void
Notify(const BluetoothSignal& aSignal) MOZ_OVERRIDE;
private:
void
UnregisterAllSignalHandlers();
};
/*******************************************************************************
* BluetoothAdapterRequestParent
******************************************************************************/
class BluetoothRequestParent : public PBluetoothRequestParent
{
class ReplyRunnable;
friend class BluetoothParent;
friend class ReplyRunnable;
nsRefPtr<BluetoothService> mService;
nsRevocableEventPtr<ReplyRunnable> mReplyRunnable;
#ifdef DEBUG
Request::Type mRequestType;
#endif
protected:
BluetoothRequestParent(BluetoothService* aService);
virtual ~BluetoothRequestParent();
virtual void
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
void
RequestComplete();
bool
DoRequest(const DefaultAdapterPathRequest& aRequest);
bool
DoRequest(const SetPropertyRequest& aRequest);
bool
DoRequest(const GetPropertyRequest& aRequest);
bool
DoRequest(const StartDiscoveryRequest& aRequest);
bool
DoRequest(const StopDiscoveryRequest& aRequest);
bool
DoRequest(const PairRequest& aRequest);
bool
DoRequest(const UnpairRequest& aRequest);
bool
DoRequest(const DevicePropertiesRequest& aRequest);
};
END_BLUETOOTH_NAMESPACE
#endif // mozilla_dom_bluetooth_ipc_bluetoothparent_h__

View File

@ -0,0 +1,303 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "base/basictypes.h"
#include "BluetoothServiceChildProcess.h"
#include "mozilla/Assertions.h"
#include "mozilla/dom/ContentChild.h"
#include "BluetoothChild.h"
USING_BLUETOOTH_NAMESPACE
namespace {
BluetoothChild* gBluetoothChild;
inline
void
SendRequest(BluetoothReplyRunnable* aRunnable, const Request& aRequest)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aRunnable);
NS_WARN_IF_FALSE(gBluetoothChild,
"Calling methods on BluetoothServiceChildProcess during "
"shutdown!");
if (gBluetoothChild) {
BluetoothRequestChild* actor = new BluetoothRequestChild(aRunnable);
gBluetoothChild->SendPBluetoothRequestConstructor(actor, aRequest);
}
}
} // anonymous namespace
// static
BluetoothServiceChildProcess*
BluetoothServiceChildProcess::Create()
{
MOZ_ASSERT(!gBluetoothChild);
mozilla::dom::ContentChild* contentChild =
mozilla::dom::ContentChild::GetSingleton();
MOZ_ASSERT(contentChild);
BluetoothServiceChildProcess* btService = new BluetoothServiceChildProcess();
gBluetoothChild = new BluetoothChild(btService);
contentChild->SendPBluetoothConstructor(gBluetoothChild);
return btService;
}
BluetoothServiceChildProcess::BluetoothServiceChildProcess()
{
}
BluetoothServiceChildProcess::~BluetoothServiceChildProcess()
{
gBluetoothChild = nullptr;
}
void
BluetoothServiceChildProcess::NoteDeadActor()
{
MOZ_ASSERT(gBluetoothChild);
gBluetoothChild = nullptr;
}
void
BluetoothServiceChildProcess::RegisterBluetoothSignalHandler(
const nsAString& aNodeName,
BluetoothSignalObserver* aHandler)
{
if (gBluetoothChild) {
gBluetoothChild->SendRegisterSignalHandler(nsString(aNodeName));
}
BluetoothService::RegisterBluetoothSignalHandler(aNodeName, aHandler);
}
void
BluetoothServiceChildProcess::UnregisterBluetoothSignalHandler(
const nsAString& aNodeName,
BluetoothSignalObserver* aHandler)
{
if (gBluetoothChild) {
gBluetoothChild->SendUnregisterSignalHandler(nsString(aNodeName));
}
BluetoothService::UnregisterBluetoothSignalHandler(aNodeName, aHandler);
}
nsresult
BluetoothServiceChildProcess::GetDefaultAdapterPathInternal(
BluetoothReplyRunnable* aRunnable)
{
SendRequest(aRunnable, DefaultAdapterPathRequest());
return NS_OK;
}
nsresult
BluetoothServiceChildProcess::GetPairedDevicePropertiesInternal(
const nsTArray<nsString>& aDeviceAddresses,
BluetoothReplyRunnable* aRunnable)
{
DevicePropertiesRequest request;
request.addresses().AppendElements(aDeviceAddresses);
SendRequest(aRunnable, request);
return NS_OK;
}
nsresult
BluetoothServiceChildProcess::StopDiscoveryInternal(
const nsAString& aAdapterPath,
BluetoothReplyRunnable* aRunnable)
{
SendRequest(aRunnable, StopDiscoveryRequest(nsString(aAdapterPath)));
return NS_OK;
}
nsresult
BluetoothServiceChildProcess::StartDiscoveryInternal(
const nsAString& aAdapterPath,
BluetoothReplyRunnable* aRunnable)
{
SendRequest(aRunnable, StartDiscoveryRequest(nsString(aAdapterPath)));
return NS_OK;
}
nsresult
BluetoothServiceChildProcess::GetProperties(BluetoothObjectType aType,
const nsAString& aPath,
BluetoothReplyRunnable* aRunnable)
{
SendRequest(aRunnable, GetPropertyRequest(aType, nsString(aPath)));
return NS_OK;
}
nsresult
BluetoothServiceChildProcess::SetProperty(BluetoothObjectType aType,
const nsAString& aPath,
const BluetoothNamedValue& aValue,
BluetoothReplyRunnable* aRunnable)
{
SendRequest(aRunnable, SetPropertyRequest(aType, nsString(aPath), aValue));
return NS_OK;
}
bool
BluetoothServiceChildProcess::GetDevicePath(const nsAString& aAdapterPath,
const nsAString& aDeviceAddress,
nsAString& aDevicePath)
{
// XXXbent Right now this is adapted from BluetoothDBusService's
// GetObjectPathFromAddress. This is basically a sync call that cannot
// be forwarded to the parent process without blocking. Hopefully this
// can be reworked.
nsAutoString path(aAdapterPath);
path.AppendLiteral("/dev_");
path.Append(aDeviceAddress);
path.ReplaceChar(':', '_');
aDevicePath = path;
return NS_OK;
}
bool
BluetoothServiceChildProcess::AddReservedServicesInternal(
const nsAString& aAdapterPath,
const nsTArray<uint32_t>& aServices,
nsTArray<uint32_t>& aServiceHandlesContainer)
{
MOZ_NOT_REACHED("This function isn't used!");
return false;
}
bool
BluetoothServiceChildProcess::RemoveReservedServicesInternal(
const nsAString& aAdapterPath,
const nsTArray<uint32_t>& aServiceHandles)
{
MOZ_NOT_REACHED("This function isn't used!");
return false;
}
nsresult
BluetoothServiceChildProcess::CreatePairedDeviceInternal(
const nsAString& aAdapterPath,
const nsAString& aAddress,
int aTimeout,
BluetoothReplyRunnable* aRunnable)
{
SendRequest(aRunnable,
PairRequest(nsString(aAdapterPath), nsString(aAddress), aTimeout));
return NS_OK;
}
nsresult
BluetoothServiceChildProcess::RemoveDeviceInternal(
const nsAString& aAdapterPath,
const nsAString& aObjectPath,
BluetoothReplyRunnable* aRunnable)
{
SendRequest(aRunnable,
UnpairRequest(nsString(aAdapterPath), nsString(aObjectPath)));
return NS_OK;
}
nsresult
BluetoothServiceChildProcess::GetSocketViaService(
const nsAString& aObjectPath,
const nsAString& aService,
int aType,
bool aAuth,
bool aEncrypt,
BluetoothReplyRunnable* aRunnable)
{
MOZ_NOT_REACHED("Implement me!");
return NS_ERROR_NOT_IMPLEMENTED;
}
bool
BluetoothServiceChildProcess::CloseSocket(int aFd,
BluetoothReplyRunnable* aRunnable)
{
MOZ_NOT_REACHED("Implement me!");
return false;
}
bool
BluetoothServiceChildProcess::SetPinCodeInternal(
const nsAString& aDeviceAddress,
const nsAString& aPinCode)
{
MOZ_NOT_REACHED("Implement me!");
return false;
}
bool
BluetoothServiceChildProcess::SetPasskeyInternal(
const nsAString& aDeviceAddress,
uint32_t aPasskey)
{
MOZ_NOT_REACHED("Implement me!");
return false;
}
bool
BluetoothServiceChildProcess::SetPairingConfirmationInternal(
const nsAString& aDeviceAddress,
bool aConfirm)
{
MOZ_NOT_REACHED("Implement me!");
return false;
}
bool
BluetoothServiceChildProcess::SetAuthorizationInternal(
const nsAString& aDeviceAddress,
bool aAllow)
{
MOZ_NOT_REACHED("Implement me!");
return false;
}
nsresult
BluetoothServiceChildProcess::HandleStartup()
{
// Don't need to do anything here for startup since our Create function takes
// care of the actor machinery.
return NS_OK;
}
nsresult
BluetoothServiceChildProcess::HandleShutdown()
{
// If this process is shutting down then we need to disconnect ourselves from
// the parent.
if (gBluetoothChild) {
gBluetoothChild->BeginShutdown();
}
return NS_OK;
}
nsresult
BluetoothServiceChildProcess::StartInternal()
{
MOZ_NOT_REACHED("This should never be called!");
return NS_ERROR_FAILURE;
}
nsresult
BluetoothServiceChildProcess::StopInternal()
{
MOZ_NOT_REACHED("This should never be called!");
return NS_ERROR_FAILURE;
}

View File

@ -0,0 +1,152 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_bluetooth_ipc_bluetoothservicechildprocess_h__
#define mozilla_dom_bluetooth_ipc_bluetoothservicechildprocess_h__
#include "BluetoothService.h"
namespace mozilla {
namespace dom {
namespace bluetooth {
class BluetoothChild;
} // namespace bluetooth
} // namespace dom
} // namespace mozilla
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothServiceChildProcess : public BluetoothService
{
friend class mozilla::dom::bluetooth::BluetoothChild;
public:
static BluetoothServiceChildProcess*
Create();
virtual void
RegisterBluetoothSignalHandler(const nsAString& aNodeName,
BluetoothSignalObserver* aMsgHandler)
MOZ_OVERRIDE;
virtual void
UnregisterBluetoothSignalHandler(const nsAString& aNodeName,
BluetoothSignalObserver* aMsgHandler)
MOZ_OVERRIDE;
virtual nsresult
GetDefaultAdapterPathInternal(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual nsresult
GetPairedDevicePropertiesInternal(const nsTArray<nsString>& aDeviceAddresses,
BluetoothReplyRunnable* aRunnable)
MOZ_OVERRIDE;
virtual nsresult
StopDiscoveryInternal(const nsAString& aAdapterPath,
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual nsresult
StartDiscoveryInternal(const nsAString& aAdapterPath,
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual nsresult
GetProperties(BluetoothObjectType aType,
const nsAString& aPath,
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual nsresult
SetProperty(BluetoothObjectType aType,
const nsAString& aPath,
const BluetoothNamedValue& aValue,
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual bool
GetDevicePath(const nsAString& aAdapterPath,
const nsAString& aDeviceAddress,
nsAString& aDevicePath) MOZ_OVERRIDE;
virtual bool
AddReservedServicesInternal(const nsAString& aAdapterPath,
const nsTArray<uint32_t>& aServices,
nsTArray<uint32_t>& aServiceHandlesContainer)
MOZ_OVERRIDE;
virtual bool
RemoveReservedServicesInternal(const nsAString& aAdapterPath,
const nsTArray<uint32_t>& aServiceHandles)
MOZ_OVERRIDE;
virtual nsresult
CreatePairedDeviceInternal(const nsAString& aAdapterPath,
const nsAString& aAddress,
int aTimeout,
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual nsresult
RemoveDeviceInternal(const nsAString& aAdapterPath,
const nsAString& aObjectPath,
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual nsresult
GetSocketViaService(const nsAString& aObjectPath,
const nsAString& aService,
int aType,
bool aAuth,
bool aEncrypt,
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual bool
CloseSocket(int aFd, BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual bool
SetPinCodeInternal(const nsAString& aDeviceAddress,
const nsAString& aPinCode) MOZ_OVERRIDE;
virtual bool
SetPasskeyInternal(const nsAString& aDeviceAddress,
uint32_t aPasskey) MOZ_OVERRIDE;
virtual bool
SetPairingConfirmationInternal(const nsAString& aDeviceAddress,
bool aConfirm) MOZ_OVERRIDE;
virtual bool
SetAuthorizationInternal(const nsAString& aDeviceAddress,
bool aAllow) MOZ_OVERRIDE;
protected:
BluetoothServiceChildProcess();
virtual ~BluetoothServiceChildProcess();
void
NoteDeadActor();
void
NoteShutdownInitiated();
virtual nsresult
HandleStartup() MOZ_OVERRIDE;
virtual nsresult
HandleShutdown() MOZ_OVERRIDE;
private:
// This method should never be called.
virtual nsresult
StartInternal() MOZ_OVERRIDE;
// This method should never be called.
virtual nsresult
StopInternal() MOZ_OVERRIDE;
};
END_BLUETOOTH_NAMESPACE
#endif // mozilla_dom_bluetooth_ipc_bluetoothservicechildprocess_h__

View File

@ -0,0 +1,178 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBluetoothRequest;
include protocol PContent;
include BluetoothTypes;
include "mozilla/dom/bluetooth/ipc/BluetoothMessageUtils.h";
using mozilla::dom::bluetooth::BluetoothObjectType;
namespace mozilla {
namespace dom {
namespace bluetooth {
/**
* Bluetooth request types.
*/
struct DefaultAdapterPathRequest
{ };
struct SetPropertyRequest
{
BluetoothObjectType type;
nsString path;
BluetoothNamedValue value;
};
struct GetPropertyRequest
{
BluetoothObjectType type;
nsString path;
};
struct StartDiscoveryRequest
{
nsString path;
};
struct StopDiscoveryRequest
{
nsString path;
};
struct PairRequest
{
nsString path;
nsString address;
uint32_t timeoutMS;
};
struct UnpairRequest
{
nsString path;
nsString address;
};
struct DevicePropertiesRequest
{
nsString[] addresses;
};
union Request
{
DefaultAdapterPathRequest;
SetPropertyRequest;
GetPropertyRequest;
StartDiscoveryRequest;
StopDiscoveryRequest;
PairRequest;
UnpairRequest;
DevicePropertiesRequest;
};
protocol PBluetooth
{
manager PContent;
manages PBluetoothRequest;
/**
* The potential exists for a racy shutdown so the following sequence of
* messages is used to shutdown safely:
*
* 1. [BeginShutdown] (Parent -> Child [Optional])
* 2. StopNotifying (Child -> Parent)
* 3. NotificationsStopped (Parent -> Child)
* 4. __delete__() (Child -> Parent)
*/
child:
/**
* Sent when a settings change has enabled or disabled the bluetooth firmware.
*/
Enabled(bool enabled);
/**
* Sent when a bluetooth signal is broadcasted to child processes.
*/
Notify(BluetoothSignal signal);
/**
* Sent when the parent process is about to be shut down. See shutdown note
* above.
*/
BeginShutdown();
/**
* Sent to inform the child process that it will no longer receive any
* messages from the parent. See shutdown note above.
*/
NotificationsStopped();
parent:
/**
* Sent when the child no longer needs to use bluetooth. See shutdown note
* above.
*/
__delete__();
/**
* Sent when the child needs to receive signals related to the given node.
*/
RegisterSignalHandler(nsString node);
/**
* Sent when the child no longer needs to receive signals related to the given
* node.
*/
UnregisterSignalHandler(nsString node);
/**
* Sent when the child no longer needs to receive any messages from the
* parent. See shutdown note above.
*/
StopNotifying();
/**
* Sent when the child makes an asynchronous request to the parent.
*/
PBluetoothRequest(Request request);
/**
* FIXME: Bug 547703.
*
* This is the state machine we want:
*
* start state NOTIFYING:
* send Enabled goto NOTIFYING;
* send Notify goto NOTIFYING;
* recv RegisterSignalHandler goto NOTIFYING;
* recv UnregisterSignalHandler goto NOTIFYING;
* send BeginShutdown goto PARENT_DONE;
* recv StopNotifying goto CHILD_DONE;
*
* state PARENT_DONE:
* recv RegisterSignalHandler goto PARENT_DONE;
* recv UnregisterSignalHandler goto PARENT_DONE;
* recv StopNotifying goto CHILD_DONE;
*
* state CHILD_DONE:
* send Enabled goto CHILD_DONE;
* send Notify goto CHILD_DONE;
* send BeginShutdown goto CHILD_DONE;
* send NotificationsStopped goto DONE;
*
* state DONE:
* recv __delete__;
*/
};
} // namespace bluetooth
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,28 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBluetooth;
include BluetoothTypes;
namespace mozilla {
namespace dom {
namespace bluetooth {
protocol PBluetoothRequest
{
manager PBluetooth;
child:
/**
* Sent when the asynchronous request has completed.
*/
__delete__(BluetoothReply response);
};
} // namespace bluetooth
} // namespace dom
} // namespace mozilla

View File

@ -4,4 +4,6 @@
IPDLSRCS = \
BluetoothTypes.ipdlh \
PBluetooth.ipdl \
PBluetoothRequest.ipdl \
$(NULL)

View File

@ -19,7 +19,6 @@
#include "base/basictypes.h"
#include "BluetoothDBusService.h"
#include "BluetoothServiceUuid.h"
#include "BluetoothTypes.h"
#include "BluetoothReplyRunnable.h"
#include <cstdio>
@ -35,6 +34,7 @@
#include "mozilla/ipc/DBusUtils.h"
#include "mozilla/ipc/RawDBusConnection.h"
#include "mozilla/Util.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
/**
* Some rules for dealing with memory in DBus:
@ -194,7 +194,8 @@ public:
NS_WARNING("BluetoothService not available!");
return NS_ERROR_FAILURE;
}
return bs->DistributeSignal(mSignal);
bs->DistributeSignal(mSignal);
return NS_OK;
}
};
@ -240,6 +241,7 @@ DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable,
nsString err(aErrorStr);
reply = new BluetoothReply(BluetoothReplyError(err));
} else {
MOZ_ASSERT(aValue.type() != BluetoothValue::T__None);
reply = new BluetoothReply(BluetoothReplySuccess(aValue));
}
@ -614,6 +616,10 @@ UnpackVoidMessage(DBusMessage* aMsg, DBusError* aErr, BluetoothValue& aValue,
LOG_AND_FREE_DBUS_ERROR(&err);
}
}
// XXXbent Need to figure out something better than this here.
if (aErrorStr.IsEmpty()) {
aValue = true;
}
}
void
@ -1106,14 +1112,6 @@ BluetoothDBusService::StopInternal()
return NS_OK;
}
int
BluetoothDBusService::IsEnabledInternal()
{
// assume bluetooth is always enabled on desktop
return true;
}
class DefaultAdapterPropertiesRunnable : public nsRunnable
{
public:
@ -1211,12 +1209,8 @@ BluetoothDBusService::SendDiscoveryMessage(const nsAString& aAdapterPath,
const char* aMessageName,
BluetoothReplyRunnable* aRunnable)
{
if (!mConnection) {
NS_WARNING("Bluetooth service not started yet!");
return NS_ERROR_FAILURE;
}
NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!");
NS_ASSERTION(mConnection, "Must have a connection here!");
nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
@ -1240,6 +1234,10 @@ nsresult
BluetoothDBusService::StopDiscoveryInternal(const nsAString& aAdapterPath,
BluetoothReplyRunnable* aRunnable)
{
if (!mConnection) {
NS_WARNING("Bluetooth service not started yet, no need to stop discovery.");
return NS_OK;
}
return SendDiscoveryMessage(aAdapterPath, "StopDiscovery", aRunnable);
}
@ -1247,6 +1245,10 @@ nsresult
BluetoothDBusService::StartDiscoveryInternal(const nsAString& aAdapterPath,
BluetoothReplyRunnable* aRunnable)
{
if (!mConnection) {
NS_WARNING("Bluetooth service not started yet, cannot start discovery!");
return NS_ERROR_FAILURE;
}
return SendDiscoveryMessage(aAdapterPath, "StartDiscovery", aRunnable);
}

View File

@ -89,8 +89,6 @@ public:
virtual bool
SetAuthorizationInternal(const nsAString& aDeviceAddress, bool aAllow);
virtual int IsEnabledInternal();
private:
nsresult SendGetPropertyMessage(const nsAString& aPath,
const char* aInterface,

View File

@ -1,15 +0,0 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "BluetoothDBusService.h"
USING_BLUETOOTH_NAMESPACE
BluetoothService*
BluetoothService::Create()
{
return new BluetoothDBusService();
}

View File

@ -92,6 +92,7 @@
#include "mozilla/dom/indexedDB/PIndexedDBChild.h"
#include "mozilla/dom/sms/SmsChild.h"
#include "mozilla/dom/devicestorage/DeviceStorageRequestChild.h"
#include "mozilla/dom/bluetooth/PBluetoothChild.h"
#include "nsDOMFile.h"
#include "nsIRemoteBlob.h"
@ -104,6 +105,7 @@
using namespace base;
using namespace mozilla::docshell;
using namespace mozilla::dom::bluetooth;
using namespace mozilla::dom::devicestorage;
using namespace mozilla::dom::sms;
using namespace mozilla::dom::indexedDB;
@ -700,6 +702,30 @@ ContentChild::DeallocPStorage(PStorageChild* aActor)
return true;
}
PBluetoothChild*
ContentChild::AllocPBluetooth()
{
#ifdef MOZ_B2G_BT
MOZ_NOT_REACHED("No one should be allocating PBluetoothChild actors");
return nullptr;
#else
MOZ_NOT_REACHED("No support for bluetooth on this platform!");
return nullptr;
#endif
}
bool
ContentChild::DeallocPBluetooth(PBluetoothChild* aActor)
{
#ifdef MOZ_B2G_BT
delete aActor;
return true;
#else
MOZ_NOT_REACHED("No support for bluetooth on this platform!");
return false;
#endif
}
bool
ContentChild::RecvRegisterChrome(const InfallibleTArray<ChromePackage>& packages,
const InfallibleTArray<ResourceMapping>& resources,

View File

@ -135,6 +135,9 @@ public:
virtual PStorageChild* AllocPStorage(const StorageConstructData& aData);
virtual bool DeallocPStorage(PStorageChild* aActor);
virtual PBluetoothChild* AllocPBluetooth();
virtual bool DeallocPBluetooth(PBluetoothChild* aActor);
virtual bool RecvRegisterChrome(const InfallibleTArray<ChromePackage>& packages,
const InfallibleTArray<ResourceMapping>& resources,
const InfallibleTArray<OverrideMapping>& overrides,

View File

@ -26,6 +26,7 @@
#include "mozilla/dom/ExternalHelperAppParent.h"
#include "mozilla/dom/PMemoryReportRequestParent.h"
#include "mozilla/dom/StorageParent.h"
#include "mozilla/dom/bluetooth/PBluetoothParent.h"
#include "mozilla/dom/devicestorage/DeviceStorageRequestParent.h"
#include "mozilla/dom/sms/SmsParent.h"
#include "mozilla/hal_sandbox/PHalParent.h"
@ -105,10 +106,16 @@
#include "nsIVolumeService.h"
#endif
#ifdef MOZ_B2G_BT
#include "BluetoothParent.h"
#include "BluetoothService.h"
#endif
static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
static const char* sClipboardTextFlavors[] = { kUnicodeMime };
using base::KillProcess;
using namespace mozilla::dom::bluetooth;
using namespace mozilla::dom::devicestorage;
using namespace mozilla::dom::sms;
using namespace mozilla::dom::indexedDB;
@ -1458,6 +1465,46 @@ ContentParent::DeallocPStorage(PStorageParent* aActor)
return true;
}
PBluetoothParent*
ContentParent::AllocPBluetooth()
{
#ifdef MOZ_B2G_BT
if (!AppProcessHasPermission(this, "bluetooth")) {
return nullptr;
}
return new mozilla::dom::bluetooth::BluetoothParent();
#else
MOZ_NOT_REACHED("No support for bluetooth on this platform!");
return nullptr;
#endif
}
bool
ContentParent::DeallocPBluetooth(PBluetoothParent* aActor)
{
#ifdef MOZ_B2G_BT
delete aActor;
return true;
#else
MOZ_NOT_REACHED("No support for bluetooth on this platform!");
return false;
#endif
}
bool
ContentParent::RecvPBluetoothConstructor(PBluetoothParent* aActor)
{
#ifdef MOZ_B2G_BT
nsRefPtr<BluetoothService> btService = BluetoothService::Get();
NS_ENSURE_TRUE(btService, false);
return static_cast<BluetoothParent*>(aActor)->InitWithService(btService);
#else
MOZ_NOT_REACHED("No support for bluetooth on this platform!");
return false;
#endif
}
void
ContentParent::ReportChildAlreadyBlocked()
{

View File

@ -233,6 +233,10 @@ private:
virtual PStorageParent* AllocPStorage(const StorageConstructData& aData);
virtual bool DeallocPStorage(PStorageParent* aActor);
virtual PBluetoothParent* AllocPBluetooth();
virtual bool DeallocPBluetooth(PBluetoothParent* aActor);
virtual bool RecvPBluetoothConstructor(PBluetoothParent* aActor);
virtual bool RecvReadPrefsArray(InfallibleTArray<PrefSetting>* aPrefs);
virtual bool RecvReadFontList(InfallibleTArray<FontListEntry>* retValue);

View File

@ -101,6 +101,8 @@ LOCAL_INCLUDES += \
-I$(topsrcdir)/dom/sms/src/ipc \
-I$(topsrcdir)/dom/devicestorage \
-I$(topsrcdir)/widget/xpwidgets \
-I$(topsrcdir)/dom/bluetooth \
-I$(topsrcdir)/dom/bluetooth/ipc \
$(NULL)
DEFINES += -DBIN_SUFFIX='"$(BIN_SUFFIX)"'

View File

@ -6,6 +6,7 @@
include protocol PAudio;
include protocol PBlob;
include protocol PBluetooth;
include protocol PBrowser;
include protocol PCompositor;
include protocol PCrashReporter;
@ -163,6 +164,7 @@ rpc protocol PContent
manages PAudio;
manages PBlob;
manages PBluetooth;
manages PBrowser;
manages PCrashReporter;
manages PDeviceStorageRequest;
@ -267,6 +269,8 @@ parent:
PStorage(StorageConstructData data);
PBluetooth();
// Services remoting
async StartVisitedQuery(URIParams uri);

View File

@ -119,7 +119,7 @@ LOCAL_INCLUDES += \
endif
ifdef MOZ_B2G_BT #{
SHARED_LIBRARY_LIBS += $(DEPTH)/dom/bluetooth/$(LIB_PREFIX)dombluetooth_s.$(LIB_SUFFIX)
SHARED_LIBRARY_LIBS += $(DEPTH)/dom/bluetooth/$(LIB_PREFIX)dombluetooth_s.$(LIB_SUFFIX)
endif #}
SHARED_LIBRARY_LIBS += $(DEPTH)/dom/camera/$(LIB_PREFIX)domcamera_s.$(LIB_SUFFIX)