mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 07:42:04 +00:00
Bug 740744: Asynchronous dbus events for bluetooth, Start/StopDiscovery and device event firing; r=bent sr=mrbkap
This commit is contained in:
parent
7ce5477f9b
commit
f8c0d08e82
@ -517,6 +517,8 @@ using mozilla::dom::indexedDB::IDBWrapperCache;
|
||||
#ifdef MOZ_B2G_BT
|
||||
#include "BluetoothManager.h"
|
||||
#include "BluetoothAdapter.h"
|
||||
#include "BluetoothDevice.h"
|
||||
#include "BluetoothDeviceEvent.h"
|
||||
#endif
|
||||
|
||||
#include "nsIDOMNavigatorSystemMessages.h"
|
||||
@ -1671,7 +1673,11 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
||||
NS_DEFINE_CLASSINFO_DATA(BluetoothManager, nsEventTargetSH,
|
||||
EVENTTARGET_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(BluetoothAdapter, nsEventTargetSH,
|
||||
EVENTTARGET_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(BluetoothDevice, nsEventTargetSH,
|
||||
EVENTTARGET_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(BluetoothDeviceEvent, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
#endif
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(DOMError, nsDOMGenericSH,
|
||||
@ -4484,6 +4490,15 @@ nsDOMClassInfo::Init()
|
||||
DOM_CLASSINFO_MAP_BEGIN(BluetoothAdapter, nsIDOMBluetoothAdapter)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBluetoothAdapter)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(BluetoothDevice, nsIDOMBluetoothDevice)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBluetoothDevice)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(BluetoothDeviceEvent, nsIDOMBluetoothDeviceEvent)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBluetoothDeviceEvent)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEvent)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
#endif
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(DOMError, nsIDOMDOMError)
|
||||
|
@ -528,6 +528,8 @@ DOMCI_CLASS(CallEvent)
|
||||
#ifdef MOZ_B2G_BT
|
||||
DOMCI_CLASS(BluetoothManager)
|
||||
DOMCI_CLASS(BluetoothAdapter)
|
||||
DOMCI_CLASS(BluetoothDevice)
|
||||
DOMCI_CLASS(BluetoothDeviceEvent)
|
||||
#endif
|
||||
|
||||
DOMCI_CLASS(DOMError)
|
||||
|
@ -4,16 +4,25 @@
|
||||
* 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 "BluetoothAdapter.h"
|
||||
#include "BluetoothUtils.h"
|
||||
#include "BluetoothDevice.h"
|
||||
#include "BluetoothDeviceEvent.h"
|
||||
#include "BluetoothService.h"
|
||||
#include "BluetoothTypes.h"
|
||||
#include "BluetoothReplyRunnable.h"
|
||||
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsDOMEvent.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsXPCOMCIDInternal.h"
|
||||
#include "nsIDOMDOMRequest.h"
|
||||
|
||||
#include "mozilla/LazyIdleThread.h"
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
|
||||
DOMCI_DATA(BluetoothAdapter, BluetoothAdapter)
|
||||
@ -22,10 +31,16 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothAdapter)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothAdapter,
|
||||
nsDOMEventTargetHelper)
|
||||
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(devicefound)
|
||||
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(devicedisappeared)
|
||||
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(propertychanged)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothAdapter,
|
||||
nsDOMEventTargetHelper)
|
||||
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(devicefound)
|
||||
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(devicedisappeared)
|
||||
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(propertychanged)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothAdapter)
|
||||
@ -36,29 +51,227 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
|
||||
NS_IMPL_ADDREF_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper)
|
||||
|
||||
BluetoothAdapter::BluetoothAdapter(const nsCString& name) :
|
||||
mName(name)
|
||||
class GetPropertiesTask : public BluetoothReplyRunnable
|
||||
{
|
||||
}
|
||||
public:
|
||||
GetPropertiesTask(BluetoothAdapter* aAdapter, nsIDOMDOMRequest* aReq) :
|
||||
BluetoothReplyRunnable(aReq),
|
||||
mAdapterPtr(aAdapter)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
ParseSuccessfulReply(jsval* aValue)
|
||||
{
|
||||
const InfallibleTArray<BluetoothNamedValue>& values =
|
||||
mReply->get_BluetoothReplySuccess().value().get_ArrayOfBluetoothNamedValue();
|
||||
for (uint32_t i = 0; i < values.Length(); ++i) {
|
||||
mAdapterPtr->SetPropertyByValue(values[i]);
|
||||
}
|
||||
*aValue = JSVAL_VOID;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ReleaseMembers()
|
||||
{
|
||||
BluetoothReplyRunnable::ReleaseMembers();
|
||||
mAdapterPtr = nsnull;
|
||||
}
|
||||
private:
|
||||
nsRefPtr<BluetoothAdapter> mAdapterPtr;
|
||||
};
|
||||
|
||||
BluetoothAdapter::~BluetoothAdapter()
|
||||
{
|
||||
if (NS_FAILED(UnregisterBluetoothEventHandler(mName, this))) {
|
||||
NS_WARNING("Failed to unregister object with observer!");
|
||||
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!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothAdapter::SetPropertyByValue(const BluetoothNamedValue& aValue)
|
||||
{
|
||||
const nsString& name = aValue.name();
|
||||
const BluetoothValue& value = aValue.value();
|
||||
if (name.EqualsLiteral("Name")) {
|
||||
mName = value.get_nsString();
|
||||
} else if (name.EqualsLiteral("Address")) {
|
||||
mAddress = value.get_nsString();
|
||||
} else if (name.EqualsLiteral("Enabled")) {
|
||||
mEnabled = value.get_bool();
|
||||
} else if (name.EqualsLiteral("Discoverable")) {
|
||||
mDiscoverable = value.get_bool();
|
||||
} else if (name.EqualsLiteral("Pairable")) {
|
||||
mPairable = value.get_bool();
|
||||
} else if (name.EqualsLiteral("Powered")) {
|
||||
mPowered = value.get_bool();
|
||||
} else if (name.EqualsLiteral("PairableTimeout")) {
|
||||
mPairableTimeout = value.get_uint32_t();
|
||||
} else if (name.EqualsLiteral("DiscoverableTimeout")) {
|
||||
mDiscoverableTimeout = value.get_uint32_t();
|
||||
} else if (name.EqualsLiteral("Class")) {
|
||||
mClass = value.get_uint32_t();
|
||||
} else if (name.EqualsLiteral("UUIDs")) {
|
||||
mUuids = value.get_ArrayOfnsString();
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
nsCString warningMsg;
|
||||
warningMsg.AssignLiteral("Not handling adapter property: ");
|
||||
warningMsg.Append(NS_ConvertUTF16toUTF8(name));
|
||||
NS_WARNING(warningMsg.get());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<BluetoothAdapter>
|
||||
BluetoothAdapter::Create(const nsCString& name) {
|
||||
nsRefPtr<BluetoothAdapter> adapter = new BluetoothAdapter(name);
|
||||
if (NS_FAILED(RegisterBluetoothEventHandler(name, adapter))) {
|
||||
BluetoothAdapter::Create(nsPIDOMWindow* aOwner, const nsAString& aPath)
|
||||
{
|
||||
// Make sure we at least have a path
|
||||
NS_ASSERTION(!aPath.IsEmpty(), "Adapter created with empty path!");
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
MOZ_ASSERT(bs);
|
||||
|
||||
nsRefPtr<BluetoothAdapter> adapter = new BluetoothAdapter(aPath);
|
||||
adapter->BindToOwner(aOwner);
|
||||
if (NS_FAILED(bs->RegisterBluetoothSignalHandler(aPath, adapter))) {
|
||||
NS_WARNING("Failed to register object with observer!");
|
||||
return NULL;
|
||||
return nsnull;
|
||||
}
|
||||
return adapter.forget();
|
||||
}
|
||||
|
||||
void BluetoothAdapter::Notify(const BluetoothEvent& aData) {
|
||||
printf("Got an adapter message!\n");
|
||||
void
|
||||
BluetoothAdapter::Notify(const BluetoothSignal& aData)
|
||||
{
|
||||
if (aData.name().EqualsLiteral("DeviceFound")) {
|
||||
nsRefPtr<BluetoothDevice> d = BluetoothDevice::Create(GetOwner(), aData);
|
||||
nsRefPtr<BluetoothDeviceEvent> e = BluetoothDeviceEvent::Create(d);
|
||||
e->Dispatch(ToIDOMEventTarget(), NS_LITERAL_STRING("devicefound"));
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
nsCString warningMsg;
|
||||
warningMsg.AssignLiteral("Not handling manager signal: ");
|
||||
warningMsg.Append(NS_ConvertUTF16toUTF8(aData.name()));
|
||||
NS_WARNING(warningMsg.get());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothAdapter::StartStopDiscovery(bool aStart, nsIDOMDOMRequest** aRequest)
|
||||
{
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
MOZ_ASSERT(bs);
|
||||
|
||||
nsCOMPtr<nsIDOMRequestService> rs = do_GetService("@mozilla.org/dom/dom-request-service;1");
|
||||
|
||||
if (!rs) {
|
||||
NS_WARNING("No DOMRequest Service!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMDOMRequest> req;
|
||||
nsresult rv = rs->CreateRequest(GetOwner(), getter_AddRefs(req));
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Can't create DOMRequest!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsRefPtr<BluetoothVoidReplyRunnable> results = new BluetoothVoidReplyRunnable(req);
|
||||
|
||||
if (aStart) {
|
||||
rv = bs->StartDiscoveryInternal(mPath, results);
|
||||
} else {
|
||||
rv = bs->StopDiscoveryInternal(mPath, results);
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Starting discovery failed!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
req.forget(aRequest);
|
||||
|
||||
// mDiscovering is not set here, we'll get a Property update from our external
|
||||
// protocol to tell us that it's been set.
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BluetoothAdapter::StartDiscovery(nsIDOMDOMRequest** aRequest)
|
||||
{
|
||||
return StartStopDiscovery(true, aRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BluetoothAdapter::StopDiscovery(nsIDOMDOMRequest** aRequest)
|
||||
{
|
||||
return StartStopDiscovery(false, aRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BluetoothAdapter::GetEnabled(bool* aEnabled)
|
||||
{
|
||||
*aEnabled = mEnabled;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BluetoothAdapter::GetAddress(nsAString& aAddress)
|
||||
{
|
||||
aAddress = mAddress;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BluetoothAdapter::GetAdapterClass(PRUint32* aClass)
|
||||
{
|
||||
*aClass = mClass;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BluetoothAdapter::GetDiscovering(bool* aDiscovering)
|
||||
{
|
||||
*aDiscovering = mDiscovering;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BluetoothAdapter::GetName(nsAString& aName)
|
||||
{
|
||||
aName = mName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BluetoothAdapter::GetDiscoverable(bool* aDiscoverable)
|
||||
{
|
||||
*aDiscoverable = mDiscoverable;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BluetoothAdapter::GetDiscoverableTimeout(PRUint32* aDiscoverableTimeout)
|
||||
{
|
||||
*aDiscoverableTimeout = mDiscoverableTimeout;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BluetoothAdapter::GetDevices(JSContext* aCx, jsval* aDevices)
|
||||
{
|
||||
NS_WARNING("GetDevices not yet implemented.");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_EVENT_HANDLER(BluetoothAdapter, propertychanged)
|
||||
NS_IMPL_EVENT_HANDLER(BluetoothAdapter, devicefound)
|
||||
NS_IMPL_EVENT_HANDLER(BluetoothAdapter, devicedisappeared)
|
||||
|
@ -8,18 +8,21 @@
|
||||
#define mozilla_dom_bluetooth_bluetoothadapter_h__
|
||||
|
||||
#include "BluetoothCommon.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDOMEventTargetHelper.h"
|
||||
#include "nsIDOMBluetoothAdapter.h"
|
||||
#include "nsIDOMDOMRequest.h"
|
||||
#include "mozilla/Observer.h"
|
||||
|
||||
class nsIEventTarget;
|
||||
class nsIDOMDOMRequest;
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothSignal;
|
||||
class BluetoothNamedValue;
|
||||
|
||||
class BluetoothAdapter : public nsDOMEventTargetHelper
|
||||
, public nsIDOMBluetoothAdapter
|
||||
, public BluetoothEventObserver
|
||||
, public BluetoothSignalObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
@ -29,17 +32,55 @@ public:
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(BluetoothAdapter,
|
||||
nsDOMEventTargetHelper)
|
||||
|
||||
static already_AddRefed<BluetoothAdapter>
|
||||
Create(const nsCString& name);
|
||||
Create(nsPIDOMWindow* aOwner, const nsAString& name);
|
||||
|
||||
void Notify(const BluetoothEvent& aParam);
|
||||
protected:
|
||||
nsCString mName;
|
||||
void Notify(const BluetoothSignal& aParam);
|
||||
|
||||
nsIDOMEventTarget*
|
||||
ToIDOMEventTarget() const
|
||||
{
|
||||
return static_cast<nsDOMEventTargetHelper*>(
|
||||
const_cast<BluetoothAdapter*>(this));
|
||||
}
|
||||
|
||||
nsISupports*
|
||||
ToISupports() const
|
||||
{
|
||||
return ToIDOMEventTarget();
|
||||
}
|
||||
|
||||
nsresult GetProperties();
|
||||
void SetPropertyByValue(const BluetoothNamedValue& aValue);
|
||||
private:
|
||||
BluetoothAdapter() {}
|
||||
BluetoothAdapter(const nsCString& name);
|
||||
|
||||
BluetoothAdapter(const nsAString& aPath) : mPath(aPath)
|
||||
{
|
||||
}
|
||||
|
||||
~BluetoothAdapter();
|
||||
|
||||
nsresult SetProperty(const BluetoothNamedValue& aValue,
|
||||
nsIDOMDOMRequest** aRequest);
|
||||
nsresult StartStopDiscovery(bool aStart, nsIDOMDOMRequest** aRequest);
|
||||
|
||||
nsString mAddress;
|
||||
nsString mName;
|
||||
nsString mPath;
|
||||
bool mEnabled;
|
||||
bool mDiscoverable;
|
||||
bool mDiscovering;
|
||||
bool mPairable;
|
||||
bool mPowered;
|
||||
PRUint32 mPairableTimeout;
|
||||
PRUint32 mDiscoverableTimeout;
|
||||
PRUint32 mClass;
|
||||
nsTArray<nsString> mDeviceAddresses;
|
||||
nsTArray<nsString> mUuids;
|
||||
|
||||
NS_DECL_EVENT_HANDLER(propertychanged)
|
||||
NS_DECL_EVENT_HANDLER(devicefound)
|
||||
NS_DECL_EVENT_HANDLER(devicedisappeared)
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
@ -22,43 +22,8 @@ class nsCString;
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
/**
|
||||
* BluetoothEvents usually hand back one of 3 types:
|
||||
*
|
||||
* - 32-bit Int
|
||||
* - String
|
||||
* - Bool
|
||||
*
|
||||
* BluetoothVariant encases the types into a single structure.
|
||||
*/
|
||||
struct BluetoothVariant
|
||||
{
|
||||
uint32_t mUint32;
|
||||
nsCString mString;
|
||||
};
|
||||
|
||||
/**
|
||||
* BluetoothNamedVariant is a variant with a name value, for passing around
|
||||
* things like properties with variant values.
|
||||
*/
|
||||
struct BluetoothNamedVariant
|
||||
{
|
||||
nsCString mName;
|
||||
BluetoothVariant mValue;
|
||||
};
|
||||
|
||||
/**
|
||||
* BluetoothEvent holds a variant value and the name of an event, such as
|
||||
* PropertyChanged or DeviceFound.
|
||||
*/
|
||||
struct BluetoothEvent
|
||||
{
|
||||
nsCString mEventName;
|
||||
nsTArray<BluetoothNamedVariant> mValues;
|
||||
};
|
||||
|
||||
typedef mozilla::Observer<BluetoothEvent> BluetoothEventObserver;
|
||||
typedef mozilla::ObserverList<BluetoothEvent> BluetoothEventObserverList;
|
||||
class BluetoothSignal;
|
||||
typedef mozilla::Observer<BluetoothSignal> BluetoothSignalObserver;
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
|
117
dom/bluetooth/BluetoothDevice.cpp
Normal file
117
dom/bluetooth/BluetoothDevice.cpp
Normal file
@ -0,0 +1,117 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* 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 "BluetoothDevice.h"
|
||||
#include "BluetoothTypes.h"
|
||||
|
||||
#include "nsDOMClassInfo.h"
|
||||
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
|
||||
DOMCI_DATA(BluetoothDevice, BluetoothDevice)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothDevice)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothDevice,
|
||||
nsDOMEventTargetHelper)
|
||||
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(propertychanged)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothDevice,
|
||||
nsDOMEventTargetHelper)
|
||||
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(propertychanged)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothDevice)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMBluetoothDevice)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(BluetoothDevice)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(BluetoothDevice, nsDOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(BluetoothDevice, nsDOMEventTargetHelper)
|
||||
|
||||
BluetoothDevice::BluetoothDevice(const BluetoothSignal& aSignal)
|
||||
{
|
||||
const InfallibleTArray<BluetoothNamedValue>& values =
|
||||
aSignal.value().get_ArrayOfBluetoothNamedValue();
|
||||
for (uint32_t i = 0; i < values.Length(); ++i) {
|
||||
SetPropertyByValue(values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDevice::SetPropertyByValue(const BluetoothNamedValue& aValue)
|
||||
{
|
||||
const nsString& name = aValue.name();
|
||||
const BluetoothValue& value = aValue.value();
|
||||
if (name.EqualsLiteral("Name")) {
|
||||
mName = value.get_nsString();
|
||||
} else if (name.EqualsLiteral("Address")) {
|
||||
mAddress = value.get_nsString();
|
||||
} else if (name.EqualsLiteral("Class")) {
|
||||
mClass = value.get_uint32_t();
|
||||
} else if (name.EqualsLiteral("Connected")) {
|
||||
mConnected = value.get_bool();
|
||||
} else if (name.EqualsLiteral("Paired")) {
|
||||
mPaired = value.get_bool();
|
||||
} else if (name.EqualsLiteral("UUIDs")) {
|
||||
mUuids = value.get_ArrayOfnsString();
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
nsCString warningMsg;
|
||||
warningMsg.AssignLiteral("Not handling device property: ");
|
||||
warningMsg.Append(NS_ConvertUTF16toUTF8(name));
|
||||
NS_WARNING(warningMsg.get());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<BluetoothDevice>
|
||||
BluetoothDevice::Create(nsPIDOMWindow* aOwner, const BluetoothSignal& aSignal)
|
||||
{
|
||||
nsRefPtr<BluetoothDevice> device = new BluetoothDevice(aSignal);
|
||||
device->BindToOwner(device);
|
||||
return device.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BluetoothDevice::GetAddress(nsAString& aAddress)
|
||||
{
|
||||
aAddress = mAddress;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BluetoothDevice::GetName(nsAString& aName)
|
||||
{
|
||||
aName = mName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BluetoothDevice::GetDeviceClass(PRUint32* aClass)
|
||||
{
|
||||
*aClass = mClass;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BluetoothDevice::GetPaired(bool* aPaired)
|
||||
{
|
||||
*aPaired = mPaired;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BluetoothDevice::GetConnected(bool* aConnected)
|
||||
{
|
||||
*aConnected = mConnected;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_EVENT_HANDLER(BluetoothDevice, propertychanged)
|
65
dom/bluetooth/BluetoothDevice.h
Normal file
65
dom/bluetooth/BluetoothDevice.h
Normal file
@ -0,0 +1,65 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* 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_bluetoothdevice_h__
|
||||
#define mozilla_dom_bluetooth_bluetoothdevice_h__
|
||||
|
||||
#include "BluetoothCommon.h"
|
||||
#include "nsDOMEventTargetHelper.h"
|
||||
#include "nsIDOMBluetoothDevice.h"
|
||||
#include "nsString.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothNamedValue;
|
||||
class BluetoothSignal;
|
||||
|
||||
class BluetoothDevice : public nsDOMEventTargetHelper
|
||||
, public nsIDOMBluetoothDevice
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIDOMBLUETOOTHDEVICE
|
||||
|
||||
NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper::)
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(BluetoothDevice,
|
||||
nsDOMEventTargetHelper)
|
||||
|
||||
static already_AddRefed<BluetoothDevice>
|
||||
Create(nsPIDOMWindow* aOwner, const BluetoothSignal& aSignal);
|
||||
|
||||
nsIDOMEventTarget*
|
||||
ToIDOMEventTarget() const
|
||||
{
|
||||
return static_cast<nsDOMEventTargetHelper*>(
|
||||
const_cast<BluetoothDevice*>(this));
|
||||
}
|
||||
|
||||
nsISupports*
|
||||
ToISupports() const
|
||||
{
|
||||
return ToIDOMEventTarget();
|
||||
}
|
||||
|
||||
private:
|
||||
BluetoothDevice(const BluetoothSignal& aSignal);
|
||||
~BluetoothDevice() {}
|
||||
void SetPropertyByValue(const BluetoothNamedValue& aValue);
|
||||
|
||||
nsString mAddress;
|
||||
nsString mName;
|
||||
PRUint32 mClass;
|
||||
bool mConnected;
|
||||
bool mPaired;
|
||||
nsTArray<nsString> mUuids;
|
||||
|
||||
NS_DECL_EVENT_HANDLER(propertychanged)
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif
|
57
dom/bluetooth/BluetoothDeviceEvent.cpp
Normal file
57
dom/bluetooth/BluetoothDeviceEvent.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* 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 "BluetoothDeviceEvent.h"
|
||||
#include "BluetoothTypes.h"
|
||||
#include "BluetoothDevice.h"
|
||||
|
||||
#include "nsDOMClassInfo.h"
|
||||
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
|
||||
// static
|
||||
already_AddRefed<BluetoothDeviceEvent>
|
||||
BluetoothDeviceEvent::Create(BluetoothDevice* aDevice)
|
||||
{
|
||||
NS_ASSERTION(aDevice, "Null pointer!");
|
||||
|
||||
nsRefPtr<BluetoothDeviceEvent> event = new BluetoothDeviceEvent();
|
||||
|
||||
event->mDevice = aDevice;
|
||||
|
||||
return event.forget();
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothDeviceEvent)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothDeviceEvent,
|
||||
nsDOMEvent)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDevice)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothDeviceEvent,
|
||||
nsDOMEvent)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDevice)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothDeviceEvent)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMBluetoothDeviceEvent)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(BluetoothDeviceEvent)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(BluetoothDeviceEvent, nsDOMEvent)
|
||||
NS_IMPL_RELEASE_INHERITED(BluetoothDeviceEvent, nsDOMEvent)
|
||||
|
||||
DOMCI_DATA(BluetoothDeviceEvent, BluetoothDeviceEvent)
|
||||
|
||||
NS_IMETHODIMP
|
||||
BluetoothDeviceEvent::GetDevice(nsIDOMBluetoothDevice** aDevice)
|
||||
{
|
||||
nsCOMPtr<nsIDOMBluetoothDevice> device = mDevice.get();
|
||||
device.forget(aDevice);
|
||||
return NS_OK;
|
||||
}
|
68
dom/bluetooth/BluetoothDeviceEvent.h
Normal file
68
dom/bluetooth/BluetoothDeviceEvent.h
Normal file
@ -0,0 +1,68 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* 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_deviceevent_h__
|
||||
#define mozilla_dom_bluetooth_deviceevent_h__
|
||||
|
||||
#include "BluetoothCommon.h"
|
||||
|
||||
#include "nsIDOMBluetoothDeviceEvent.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
|
||||
#include "nsDOMEvent.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothDevice;
|
||||
|
||||
class BluetoothDeviceEvent : public nsDOMEvent
|
||||
, public nsIDOMBluetoothDeviceEvent
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_FORWARD_TO_NSDOMEVENT
|
||||
NS_DECL_NSIDOMBLUETOOTHDEVICEEVENT
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(BluetoothDeviceEvent, nsDOMEvent)
|
||||
|
||||
static already_AddRefed<BluetoothDeviceEvent>
|
||||
Create(BluetoothDevice* aDevice);
|
||||
|
||||
nsresult
|
||||
Dispatch(nsIDOMEventTarget* aTarget, const nsAString& aEventType)
|
||||
{
|
||||
NS_ASSERTION(aTarget, "Null pointer!");
|
||||
NS_ASSERTION(!aEventType.IsEmpty(), "Empty event type!");
|
||||
|
||||
nsresult rv = InitEvent(aEventType, false, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = SetTrusted(true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsIDOMEvent* thisEvent =
|
||||
static_cast<nsDOMEvent*>(const_cast<BluetoothDeviceEvent*>(this));
|
||||
|
||||
bool dummy;
|
||||
rv = aTarget->DispatchEvent(thisEvent, &dummy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
BluetoothDeviceEvent()
|
||||
: nsDOMEvent(nsnull, nsnull)
|
||||
{ }
|
||||
|
||||
~BluetoothDeviceEvent()
|
||||
{ }
|
||||
|
||||
nsCOMPtr<nsIDOMBluetoothDevice> mDevice;
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif
|
@ -1,85 +0,0 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* 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 "BluetoothFirmware.h"
|
||||
|
||||
#include "nsDebug.h"
|
||||
#include "nsError.h"
|
||||
#include <dlfcn.h>
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace bluetooth {
|
||||
|
||||
static struct BluedroidFunctions {
|
||||
bool initialized;
|
||||
bool tried_initialization;
|
||||
|
||||
BluedroidFunctions() :
|
||||
initialized(false),
|
||||
tried_initialization(false)
|
||||
{
|
||||
}
|
||||
|
||||
int (* bt_enable)();
|
||||
int (* bt_disable)();
|
||||
int (* bt_is_enabled)();
|
||||
} sBluedroidFunctions;
|
||||
|
||||
bool EnsureBluetoothInit() {
|
||||
if (sBluedroidFunctions.tried_initialization)
|
||||
{
|
||||
return sBluedroidFunctions.initialized;
|
||||
}
|
||||
|
||||
sBluedroidFunctions.initialized = false;
|
||||
sBluedroidFunctions.tried_initialization = true;
|
||||
|
||||
void* handle = dlopen("libbluedroid.so", RTLD_LAZY);
|
||||
|
||||
if(!handle) {
|
||||
NS_ERROR("Failed to open libbluedroid.so, bluetooth cannot run");
|
||||
return false;
|
||||
}
|
||||
|
||||
sBluedroidFunctions.bt_enable = (int (*)())dlsym(handle, "bt_enable");
|
||||
if(sBluedroidFunctions.bt_enable == NULL) {
|
||||
NS_ERROR("Failed to attach bt_enable function");
|
||||
return false;
|
||||
}
|
||||
sBluedroidFunctions.bt_disable = (int (*)())dlsym(handle, "bt_disable");
|
||||
if(sBluedroidFunctions.bt_disable == NULL) {
|
||||
NS_ERROR("Failed to attach bt_disable function");
|
||||
return false;
|
||||
}
|
||||
sBluedroidFunctions.bt_is_enabled = (int (*)())dlsym(handle, "bt_is_enabled");
|
||||
if(sBluedroidFunctions.bt_is_enabled == NULL) {
|
||||
NS_ERROR("Failed to attach bt_is_enabled function");
|
||||
return false;
|
||||
}
|
||||
sBluedroidFunctions.initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
int IsBluetoothEnabled()
|
||||
{
|
||||
return sBluedroidFunctions.bt_is_enabled();
|
||||
}
|
||||
|
||||
int EnableBluetooth()
|
||||
{
|
||||
return sBluedroidFunctions.bt_enable();
|
||||
}
|
||||
|
||||
int DisableBluetooth()
|
||||
{
|
||||
return sBluedroidFunctions.bt_disable();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -4,29 +4,23 @@
|
||||
* 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 "BluetoothManager.h"
|
||||
#include "BluetoothCommon.h"
|
||||
#include "BluetoothFirmware.h"
|
||||
#include "BluetoothAdapter.h"
|
||||
#include "BluetoothUtils.h"
|
||||
#include "BluetoothService.h"
|
||||
#include "BluetoothTypes.h"
|
||||
#include "BluetoothReplyRunnable.h"
|
||||
|
||||
#include "nsIURI.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsIDOMDOMRequest.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsDOMEvent.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsXPCOMCIDInternal.h"
|
||||
#include "mozilla/LazyIdleThread.h"
|
||||
#include "mozilla/Util.h"
|
||||
#include "nsCharSeparatedTokenizer.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
#define DOM_BLUETOOTH_URL_PREF "dom.mozBluetooth.whitelist"
|
||||
|
||||
@ -35,36 +29,16 @@ using mozilla::Preferences;
|
||||
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
|
||||
static void
|
||||
FireEnabled(bool aResult, nsIDOMDOMRequest* aDomRequest)
|
||||
{
|
||||
nsCOMPtr<nsIDOMRequestService> rs =
|
||||
do_GetService("@mozilla.org/dom/dom-request-service;1");
|
||||
|
||||
if (!rs) {
|
||||
NS_WARNING("No DOMRequest Service!");
|
||||
return;
|
||||
}
|
||||
|
||||
DebugOnly<nsresult> rv =
|
||||
aResult ?
|
||||
rs->FireSuccess(aDomRequest, JSVAL_VOID) :
|
||||
rs->FireError(aDomRequest,
|
||||
NS_LITERAL_STRING("Bluetooth firmware loading failed"));
|
||||
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Bluetooth firmware loading failed");
|
||||
}
|
||||
|
||||
DOMCI_DATA(BluetoothManager, BluetoothManager)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothManager)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothManager,
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothManager,
|
||||
nsDOMEventTargetHelper)
|
||||
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(enabled)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothManager,
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothManager,
|
||||
nsDOMEventTargetHelper)
|
||||
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(enabled)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
@ -77,148 +51,149 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
|
||||
NS_IMPL_ADDREF_INHERITED(BluetoothManager, nsDOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(BluetoothManager, nsDOMEventTargetHelper)
|
||||
|
||||
class ToggleBtResultTask : public nsRunnable
|
||||
class GetAdapterTask : public BluetoothReplyRunnable
|
||||
{
|
||||
public:
|
||||
ToggleBtResultTask(nsRefPtr<BluetoothManager>& aManager,
|
||||
nsCOMPtr<nsIDOMDOMRequest>& aReq,
|
||||
bool aEnabled,
|
||||
bool aResult)
|
||||
: mEnabled(aEnabled),
|
||||
mResult(aResult)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
public:
|
||||
GetAdapterTask(BluetoothManager* aManager,
|
||||
nsIDOMDOMRequest* aReq) :
|
||||
BluetoothReplyRunnable(aReq),
|
||||
mManagerPtr(aManager)
|
||||
{
|
||||
}
|
||||
|
||||
mDOMRequest.swap(aReq);
|
||||
mManagerPtr.swap(aManager);
|
||||
bool
|
||||
ParseSuccessfulReply(jsval* aValue)
|
||||
{
|
||||
nsCOMPtr<nsIDOMBluetoothAdapter> adapter;
|
||||
*aValue = JSVAL_VOID;
|
||||
|
||||
const nsString& path =
|
||||
mReply->get_BluetoothReplySuccess().value().get_nsString();
|
||||
adapter = BluetoothAdapter::Create(mManagerPtr->GetOwner(),
|
||||
path);
|
||||
|
||||
nsresult rv;
|
||||
nsIScriptContext* sc = mManagerPtr->GetContextForEventHandlers(&rv);
|
||||
if (!sc) {
|
||||
NS_WARNING("Cannot create script context!");
|
||||
SetError(NS_LITERAL_STRING("BluetoothScriptContextError"));
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Update bt power status to BluetoothAdapter only if loading bluetooth
|
||||
// firmware succeeds.
|
||||
if (mResult) {
|
||||
mManagerPtr->SetEnabledInternal(mEnabled);
|
||||
}
|
||||
|
||||
FireEnabled(mResult, mDOMRequest);
|
||||
|
||||
//mAdapterPtr must be null before returning to prevent the background
|
||||
//thread from racing to release it during the destruction of this runnable.
|
||||
mManagerPtr = NULL;
|
||||
mDOMRequest = NULL;
|
||||
|
||||
return NS_OK;
|
||||
rv = nsContentUtils::WrapNative(sc->GetNativeContext(),
|
||||
sc->GetNativeGlobal(),
|
||||
adapter,
|
||||
aValue);
|
||||
bool result = NS_SUCCEEDED(rv) ? true : false;
|
||||
if (!result) {
|
||||
NS_WARNING("Cannot create native object!");
|
||||
SetError(NS_LITERAL_STRING("BluetoothNativeObjectError"));
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<BluetoothManager> mManagerPtr;
|
||||
nsCOMPtr<nsIDOMDOMRequest> mDOMRequest;
|
||||
bool mEnabled;
|
||||
bool mResult;
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
ReleaseMembers()
|
||||
{
|
||||
BluetoothReplyRunnable::ReleaseMembers();
|
||||
mManagerPtr = nsnull;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<BluetoothManager> mManagerPtr;
|
||||
};
|
||||
|
||||
class ToggleBtTask : public nsRunnable
|
||||
class ToggleBtResultTask : public BluetoothReplyRunnable
|
||||
{
|
||||
public:
|
||||
ToggleBtTask(bool aEnabled, nsIDOMDOMRequest* aReq,
|
||||
BluetoothManager* aManager)
|
||||
: mEnabled(aEnabled),
|
||||
mManagerPtr(aManager),
|
||||
mDOMRequest(aReq)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
public:
|
||||
ToggleBtResultTask(BluetoothManager* aManager,
|
||||
nsIDOMDOMRequest* aReq,
|
||||
bool aEnabled)
|
||||
: BluetoothReplyRunnable(aReq),
|
||||
mManagerPtr(aManager),
|
||||
mEnabled(aEnabled)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
~ToggleBtResultTask()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
ParseSuccessfulReply(jsval* aValue)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
*aValue = JSVAL_VOID;
|
||||
mManagerPtr->SetEnabledInternal(mEnabled);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool result;
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
// Platform specific check for gonk until object is divided in
|
||||
// different implementations per platform. Linux doesn't require
|
||||
// bluetooth firmware loading, but code should work otherwise.
|
||||
if(!EnsureBluetoothInit()) {
|
||||
NS_ERROR("Failed to load bluedroid library.\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// return 1 if it's enabled, 0 if it's disabled, and -1 on error
|
||||
int isEnabled = IsBluetoothEnabled();
|
||||
|
||||
if ((isEnabled == 1 && mEnabled) || (isEnabled == 0 && !mEnabled)) {
|
||||
result = true;
|
||||
} else if (isEnabled < 0) {
|
||||
result = false;
|
||||
} else if (mEnabled) {
|
||||
result = (EnableBluetooth() == 0) ? true : false;
|
||||
} else {
|
||||
result = (DisableBluetooth() == 0) ? true : false;
|
||||
}
|
||||
#else
|
||||
result = true;
|
||||
NS_WARNING("No bluetooth firmware loading support in this build configuration, faking a success event instead");
|
||||
#endif
|
||||
|
||||
// Create a result thread and pass it to Main Thread,
|
||||
nsCOMPtr<nsIRunnable> resultRunnable = new ToggleBtResultTask(mManagerPtr, mDOMRequest, mEnabled, result);
|
||||
|
||||
if (NS_FAILED(NS_DispatchToMainThread(resultRunnable))) {
|
||||
NS_WARNING("Failed to dispatch to main thread!");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
bool mEnabled;
|
||||
nsRefPtr<BluetoothManager> mManagerPtr;
|
||||
nsCOMPtr<nsIDOMDOMRequest> mDOMRequest;
|
||||
void
|
||||
ReleaseMembers()
|
||||
{
|
||||
BluetoothReplyRunnable::ReleaseMembers();
|
||||
// mManagerPtr must be null before returning to prevent the background
|
||||
// thread from racing to release it during the destruction of this runnable.
|
||||
mManagerPtr = nsnull;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<BluetoothManager> mManagerPtr;
|
||||
bool mEnabled;
|
||||
};
|
||||
|
||||
BluetoothManager::BluetoothManager(nsPIDOMWindow *aWindow) :
|
||||
mEnabled(false),
|
||||
mName(nsDependentCString("/"))
|
||||
mEnabled(false)
|
||||
{
|
||||
BindToOwner(aWindow);
|
||||
mName.AssignLiteral("/");
|
||||
}
|
||||
|
||||
BluetoothManager::~BluetoothManager()
|
||||
{
|
||||
if(NS_FAILED(UnregisterBluetoothEventHandler(mName, this))) {
|
||||
NS_WARNING("Failed to unregister object with observer!");
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
// We can be null on shutdown, where this might happen
|
||||
if (bs) {
|
||||
if (NS_FAILED(bs->UnregisterBluetoothSignalHandler(mName, this))) {
|
||||
NS_WARNING("Failed to unregister object with observer!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BluetoothManager::SetEnabled(bool aEnabled, nsIDOMDOMRequest** aDomRequest)
|
||||
{
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
MOZ_ASSERT(bs);
|
||||
|
||||
nsCOMPtr<nsIDOMRequestService> rs = do_GetService("@mozilla.org/dom/dom-request-service;1");
|
||||
|
||||
if (!rs) {
|
||||
NS_ERROR("No DOMRequest Service!");
|
||||
NS_WARNING("No DOMRequest Service!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMDOMRequest> request;
|
||||
nsresult rv = rs->CreateRequest(GetOwner(), getter_AddRefs(request));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!mToggleBtThread) {
|
||||
mToggleBtThread = new LazyIdleThread(15000, NS_LITERAL_CSTRING("Bluetooth"));
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Can't create DOM request!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> r = new ToggleBtTask(aEnabled, request, this);
|
||||
|
||||
rv = mToggleBtThread->Dispatch(r, NS_DISPATCH_NORMAL);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsRefPtr<BluetoothReplyRunnable> results = new ToggleBtResultTask(this, request, aEnabled);
|
||||
if (aEnabled) {
|
||||
if (NS_FAILED(bs->Start(results))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (NS_FAILED(bs->Stop(results))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
request.forget(aDomRequest);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -226,32 +201,51 @@ NS_IMETHODIMP
|
||||
BluetoothManager::GetEnabled(bool* aEnabled)
|
||||
{
|
||||
*aEnabled = mEnabled;
|
||||
return NS_OK;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BluetoothManager::GetDefaultAdapter(nsIDOMBluetoothAdapter** aAdapter)
|
||||
BluetoothManager::GetDefaultAdapter(nsIDOMDOMRequest** aAdapter)
|
||||
{
|
||||
nsCString path;
|
||||
nsresult rv = GetDefaultAdapterPathInternal(path);
|
||||
if(NS_FAILED(rv)) {
|
||||
NS_WARNING("Cannot fetch adapter path!");
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
MOZ_ASSERT(bs);
|
||||
|
||||
nsCOMPtr<nsIDOMRequestService> rs = do_GetService("@mozilla.org/dom/dom-request-service;1");
|
||||
|
||||
if (!rs) {
|
||||
NS_WARNING("No DOMRequest Service!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsRefPtr<BluetoothAdapter> adapter = BluetoothAdapter::Create(path);
|
||||
adapter.forget(aAdapter);
|
||||
|
||||
nsCOMPtr<nsIDOMDOMRequest> request;
|
||||
nsresult rv = rs->CreateRequest(GetOwner(), getter_AddRefs(request));
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Can't create DOMRequest!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsRefPtr<BluetoothReplyRunnable> results = new GetAdapterTask(this, request);
|
||||
|
||||
if (NS_FAILED(bs->GetDefaultAdapterPathInternal(results))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
request.forget(aAdapter);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<BluetoothManager>
|
||||
BluetoothManager::Create(nsPIDOMWindow* aWindow) {
|
||||
|
||||
nsRefPtr<BluetoothManager> manager = new BluetoothManager(aWindow);
|
||||
nsDependentCString name("/");
|
||||
if(NS_FAILED(RegisterBluetoothEventHandler(name, manager))) {
|
||||
NS_WARNING("Failed to register object with observer!");
|
||||
return NULL;
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
MOZ_ASSERT(bs);
|
||||
|
||||
if (NS_FAILED(bs->RegisterBluetoothSignalHandler(NS_LITERAL_STRING("/"), manager))) {
|
||||
NS_ERROR("Failed to register object with observer!");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return manager.forget();
|
||||
}
|
||||
|
||||
@ -264,18 +258,28 @@ NS_NewBluetoothManager(nsPIDOMWindow* aWindow,
|
||||
bool allowed;
|
||||
nsresult rv = nsContentUtils::IsOnPrefWhitelist(aWindow, DOM_BLUETOOTH_URL_PREF, &allowed);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
||||
if (!allowed) {
|
||||
*aBluetoothManager = NULL;
|
||||
*aBluetoothManager = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<BluetoothManager> bluetoothManager = BluetoothManager::Create(aWindow);
|
||||
|
||||
if (!bluetoothManager) {
|
||||
NS_ERROR("Cannot create bluetooth manager!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
bluetoothManager.forget(aBluetoothManager);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void BluetoothManager::Notify(const BluetoothEvent& aData) {
|
||||
printf("Received an manager message!\n");
|
||||
void
|
||||
BluetoothManager::Notify(const BluetoothSignal& aData)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
nsCString warningMsg;
|
||||
warningMsg.AssignLiteral("Not handling manager signal: ");
|
||||
warningMsg.Append(NS_ConvertUTF16toUTF8(aData.name()));
|
||||
NS_WARNING(warningMsg.get());
|
||||
#endif
|
||||
}
|
||||
|
@ -10,14 +10,13 @@
|
||||
#include "BluetoothCommon.h"
|
||||
#include "nsDOMEventTargetHelper.h"
|
||||
#include "nsIDOMBluetoothManager.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "mozilla/Observer.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothManager : public nsDOMEventTargetHelper
|
||||
, public nsIDOMBluetoothManager
|
||||
, public BluetoothEventObserver
|
||||
, public BluetoothSignalObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
@ -33,17 +32,15 @@ public:
|
||||
|
||||
static already_AddRefed<BluetoothManager>
|
||||
Create(nsPIDOMWindow* aWindow);
|
||||
void Notify(const BluetoothEvent& aData);
|
||||
void Notify(const BluetoothSignal& aData);
|
||||
private:
|
||||
BluetoothManager() {}
|
||||
BluetoothManager(nsPIDOMWindow* aWindow);
|
||||
~BluetoothManager();
|
||||
bool mEnabled;
|
||||
nsCString mName;
|
||||
nsString mName;
|
||||
|
||||
NS_DECL_EVENT_HANDLER(enabled)
|
||||
|
||||
nsCOMPtr<nsIEventTarget> mToggleBtThread;
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
@ -4,20 +4,13 @@
|
||||
* 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_bluetoothfirmware_h__
|
||||
#define mozilla_dom_bluetooth_bluetoothfirmware_h__
|
||||
#include "BluetoothService.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace bluetooth {
|
||||
|
||||
bool EnsureBluetoothInit();
|
||||
int IsBluetoothEnabled();
|
||||
int EnableBluetooth();
|
||||
int DisableBluetooth();
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
|
||||
BluetoothService*
|
||||
BluetoothService::Create()
|
||||
{
|
||||
NS_WARNING("Bluetooth not implemented for this platform!");
|
||||
return nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
76
dom/bluetooth/BluetoothReplyRunnable.cpp
Normal file
76
dom/bluetooth/BluetoothReplyRunnable.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* 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 "BluetoothTypes.h"
|
||||
#include "BluetoothReplyRunnable.h"
|
||||
#include "nsIDOMDOMRequest.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
|
||||
nsresult
|
||||
BluetoothReplyRunnable::FireReply(const jsval& aVal)
|
||||
{
|
||||
nsCOMPtr<nsIDOMRequestService> rs =
|
||||
do_GetService("@mozilla.org/dom/dom-request-service;1");
|
||||
|
||||
if (!rs) {
|
||||
NS_WARNING("No DOMRequest Service!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
return mReply->type() == BluetoothReply::TBluetoothReplySuccess ?
|
||||
rs->FireSuccess(mDOMRequest, aVal) :
|
||||
rs->FireError(mDOMRequest, mReply->get_BluetoothReplyError().error());
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothReplyRunnable::FireErrorString()
|
||||
{
|
||||
nsCOMPtr<nsIDOMRequestService> rs =
|
||||
do_GetService("@mozilla.org/dom/dom-request-service;1");
|
||||
|
||||
if (!rs) {
|
||||
NS_WARNING("No DOMRequest Service!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return rs->FireError(mDOMRequest, mErrorString);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BluetoothReplyRunnable::Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsresult rv;
|
||||
|
||||
MOZ_ASSERT(mDOMRequest);
|
||||
|
||||
if (mReply->type() != BluetoothReply::TBluetoothReplySuccess) {
|
||||
rv = FireReply(JSVAL_VOID);
|
||||
} else {
|
||||
jsval v;
|
||||
if (!ParseSuccessfulReply(&v)) {
|
||||
rv = FireErrorString();
|
||||
} else {
|
||||
rv = FireReply(v);
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Could not fire DOMRequest!");
|
||||
}
|
||||
|
||||
ReleaseMembers();
|
||||
if (mDOMRequest) {
|
||||
NS_WARNING("mDOMRequest still alive! Deriving class should call BluetoothReplyRunnable::ReleaseMembers()!");
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
87
dom/bluetooth/BluetoothReplyRunnable.h
Normal file
87
dom/bluetooth/BluetoothReplyRunnable.h
Normal file
@ -0,0 +1,87 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* 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_bluetoothreplyrunnable_h__
|
||||
#define mozilla_dom_bluetooth_bluetoothreplyrunnable_h__
|
||||
|
||||
#include "BluetoothCommon.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
class nsIDOMDOMRequest;
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothReply;
|
||||
|
||||
class BluetoothReplyRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
BluetoothReplyRunnable(nsIDOMDOMRequest* aReq) :
|
||||
mDOMRequest(aReq)
|
||||
{
|
||||
}
|
||||
|
||||
void SetReply(BluetoothReply* aReply)
|
||||
{
|
||||
mReply = aReply;
|
||||
}
|
||||
|
||||
void SetError(const nsAString& aError)
|
||||
{
|
||||
mErrorString = aError;
|
||||
}
|
||||
|
||||
virtual void ReleaseMembers()
|
||||
{
|
||||
mDOMRequest = nsnull;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~BluetoothReplyRunnable()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool ParseSuccessfulReply(jsval* aValue) = 0;
|
||||
|
||||
// This is an autoptr so we don't have to bring the ipdl include into the
|
||||
// header. We assume we'll only be running this once and it should die on
|
||||
// scope out of Run() anyways.
|
||||
nsAutoPtr<BluetoothReply> mReply;
|
||||
|
||||
private:
|
||||
nsresult FireReply(const jsval& aVal);
|
||||
nsresult FireErrorString();
|
||||
|
||||
nsCOMPtr<nsIDOMDOMRequest> mDOMRequest;
|
||||
nsString mErrorString;
|
||||
};
|
||||
|
||||
class BluetoothVoidReplyRunnable : public BluetoothReplyRunnable
|
||||
{
|
||||
public:
|
||||
BluetoothVoidReplyRunnable(nsIDOMDOMRequest* aReq) :
|
||||
BluetoothReplyRunnable(aReq)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void ReleaseMembers()
|
||||
{
|
||||
BluetoothReplyRunnable::ReleaseMembers();
|
||||
}
|
||||
protected:
|
||||
virtual bool ParseSuccessfulReply(jsval* aValue)
|
||||
{
|
||||
*aValue = JSVAL_VOID;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif
|
242
dom/bluetooth/BluetoothService.cpp
Normal file
242
dom/bluetooth/BluetoothService.cpp
Normal file
@ -0,0 +1,242 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* 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 "BluetoothService.h"
|
||||
#include "BluetoothTypes.h"
|
||||
#include "BluetoothReplyRunnable.h"
|
||||
|
||||
#include "nsIDOMDOMRequest.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsXPCOMCIDInternal.h"
|
||||
#include "nsObserverService.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/LazyIdleThread.h"
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
|
||||
nsRefPtr<BluetoothService> gBluetoothService;
|
||||
nsCOMPtr<nsIThread> gToggleBtThread;
|
||||
int gPendingInitCount = 0;
|
||||
bool gInShutdown = false;
|
||||
|
||||
NS_IMPL_ISUPPORTS1(BluetoothService, nsIObserver)
|
||||
|
||||
class ToggleBtAck : public nsRunnable
|
||||
{
|
||||
public:
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
gPendingInitCount--;
|
||||
|
||||
if (gPendingInitCount) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (gInShutdown) {
|
||||
gBluetoothService = nsnull;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIThread> t;
|
||||
gToggleBtThread.swap(t);
|
||||
t->Shutdown();
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
class ToggleBtTask : public nsRunnable
|
||||
{
|
||||
public:
|
||||
ToggleBtTask(bool aEnabled,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
: mEnabled(aEnabled),
|
||||
mRunnable(aRunnable)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
nsString replyError;
|
||||
if (mEnabled) {
|
||||
if (NS_FAILED(gBluetoothService->StartInternal())) {
|
||||
replyError.AssignLiteral("Bluetooth service not available - We should never reach this point!");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (NS_FAILED(gBluetoothService->StopInternal())) {
|
||||
replyError.AssignLiteral("Bluetooth service not available - We should never reach this point!");
|
||||
}
|
||||
}
|
||||
|
||||
// Always has to be called since this is where we take care of our reference
|
||||
// count for runnables. If there's an error, replyError won't be empty, so
|
||||
// consider our status flipped.
|
||||
nsCOMPtr<nsIRunnable> ackTask = new ToggleBtAck();
|
||||
if (NS_FAILED(NS_DispatchToMainThread(ackTask))) {
|
||||
NS_WARNING("Failed to dispatch to main thread!");
|
||||
}
|
||||
|
||||
if (!mRunnable) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Reply will be deleted by the runnable after running on main thread
|
||||
BluetoothReply* reply;
|
||||
if (!replyError.IsEmpty()) {
|
||||
reply = new BluetoothReply(BluetoothReplyError(replyError));
|
||||
}
|
||||
else {
|
||||
reply = new BluetoothReply(BluetoothReplySuccess());
|
||||
}
|
||||
mRunnable->SetReply(reply);
|
||||
|
||||
if (NS_FAILED(NS_DispatchToMainThread(mRunnable))) {
|
||||
NS_WARNING("Failed to dispatch to main thread!");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
bool mEnabled;
|
||||
nsRefPtr<BluetoothReplyRunnable> mRunnable;
|
||||
};
|
||||
|
||||
nsresult
|
||||
BluetoothService::RegisterBluetoothSignalHandler(const nsAString& aNodeName,
|
||||
BluetoothSignalObserver* aHandler)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
BluetoothSignalObserverList* ol;
|
||||
if (!mBluetoothSignalObserverTable.Get(aNodeName, &ol)) {
|
||||
ol = new BluetoothSignalObserverList();
|
||||
mBluetoothSignalObserverTable.Put(aNodeName, ol);
|
||||
}
|
||||
ol->AddObserver(aHandler);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothService::UnregisterBluetoothSignalHandler(const nsAString& aNodeName,
|
||||
BluetoothSignalObserver* aHandler)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
BluetoothSignalObserverList* ol;
|
||||
if (!mBluetoothSignalObserverTable.Get(aNodeName, &ol)) {
|
||||
NS_WARNING("Node does not exist to remove BluetoothSignalListener from!");
|
||||
return NS_OK;
|
||||
}
|
||||
ol->RemoveObserver(aHandler);
|
||||
if (ol->Length() == 0) {
|
||||
mBluetoothSignalObserverTable.Remove(aNodeName);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothService::DistributeSignal(const BluetoothSignal& signal)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// Notify observers that a message has been sent
|
||||
BluetoothSignalObserverList* ol;
|
||||
if (!mBluetoothSignalObserverTable.Get(signal.path(), &ol)) {
|
||||
return NS_OK;
|
||||
}
|
||||
ol->Broadcast(signal);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothService::StartStopBluetooth(BluetoothReplyRunnable* aResultRunnable,
|
||||
bool aStart)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// If we're shutting down, bail early.
|
||||
if (gInShutdown && aStart) {
|
||||
NS_ERROR("Start called while in shutdown!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (!gToggleBtThread) {
|
||||
nsresult rv = NS_NewNamedThread("BluetoothCtrl",
|
||||
getter_AddRefs(gToggleBtThread));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
nsCOMPtr<nsIRunnable> r = new ToggleBtTask(aStart, aResultRunnable);
|
||||
if (NS_FAILED(gToggleBtThread->Dispatch(r, NS_DISPATCH_NORMAL))) {
|
||||
NS_WARNING("Cannot dispatch firmware loading task!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
gPendingInitCount++;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothService::Start(BluetoothReplyRunnable* aResultRunnable)
|
||||
{
|
||||
return StartStopBluetooth(aResultRunnable, true);
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothService::Stop(BluetoothReplyRunnable* aResultRunnable)
|
||||
{
|
||||
return StartStopBluetooth(aResultRunnable, false);
|
||||
}
|
||||
|
||||
// static
|
||||
BluetoothService*
|
||||
BluetoothService::Get()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// If we already exist, exit early
|
||||
if (gBluetoothService) {
|
||||
return gBluetoothService;
|
||||
}
|
||||
|
||||
// If we're in shutdown, don't create a new instance
|
||||
if (gInShutdown) {
|
||||
NS_WARNING("BluetoothService returns null during shutdown");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
// Create new instance, register, return
|
||||
gBluetoothService = BluetoothService::Create();
|
||||
if (!gBluetoothService) {
|
||||
NS_WARNING("Cannot create bluetooth service!");
|
||||
return nsnull;
|
||||
}
|
||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||
MOZ_ASSERT(obs);
|
||||
|
||||
if (NS_FAILED(obs->AddObserver(gBluetoothService, "xpcom-shutdown", false))) {
|
||||
NS_ERROR("AddObserver failed!");
|
||||
}
|
||||
return gBluetoothService;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothService::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
const PRUnichar* aData)
|
||||
{
|
||||
NS_ASSERTION(!strcmp(aTopic, "xpcom-shutdown"),
|
||||
"BluetoothService got unexpected topic!");
|
||||
gInShutdown = true;
|
||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||
if (obs && NS_FAILED(obs->RemoveObserver(this, "xpcom-shutdown"))) {
|
||||
NS_WARNING("Can't unregister bluetooth service with xpcom shutdown!");
|
||||
}
|
||||
|
||||
return Stop(nsnull);
|
||||
}
|
171
dom/bluetooth/BluetoothService.h
Normal file
171
dom/bluetooth/BluetoothService.h
Normal file
@ -0,0 +1,171 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* 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_bluetootheventservice_h__
|
||||
#define mozilla_dom_bluetooth_bluetootheventservice_h__
|
||||
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "BluetoothCommon.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothSignal;
|
||||
class BluetoothReplyRunnable;
|
||||
class BluetoothNamedValue;
|
||||
|
||||
class BluetoothService : public nsIObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
/**
|
||||
* Add a message handler object from message distribution observer.
|
||||
* Must be called from the main thread.
|
||||
*
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* Remove a message handler object from message distribution observer.
|
||||
* Must be called from the main thread.
|
||||
*
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* Distribute a signal to the observer list
|
||||
*
|
||||
* @param aSignal Signal object to distribute
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @param aResultRunnable Runnable object to execute after bluetooth has
|
||||
* either come up or failed. Runnable should check existence of
|
||||
* BluetoothService via Get() function to see if service started correctly.
|
||||
*
|
||||
* @return NS_OK on initialization starting correctly, NS_ERROR_FAILURE
|
||||
* otherwise
|
||||
*/
|
||||
nsresult Start(BluetoothReplyRunnable* aResultRunnable);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param aResultRunnable Runnable object to execute after bluetooth has
|
||||
* either shut down or failed. Runnable should check lack of existence of
|
||||
* BluetoothService via Get() function to see if service stopped correctly.
|
||||
*
|
||||
* @return NS_OK on initialization starting correctly, NS_ERROR_FAILURE
|
||||
* otherwise
|
||||
*/
|
||||
nsresult Stop(BluetoothReplyRunnable* aResultRunnable);
|
||||
|
||||
/**
|
||||
* Returns the BluetoothService singleton. Only to be called from main thread.
|
||||
*
|
||||
* @param aService Pointer to return singleton into.
|
||||
*
|
||||
* @return NS_OK on proper assignment, NS_ERROR_FAILURE otherwise (if service
|
||||
* has not yet been started, for instance)
|
||||
*/
|
||||
static BluetoothService* Get();
|
||||
|
||||
/**
|
||||
* Returns the path of the default adapter, implemented via a platform
|
||||
* specific method.
|
||||
*
|
||||
* @return Default adapter path/name on success, NULL otherwise
|
||||
*/
|
||||
virtual nsresult GetDefaultAdapterPathInternal(BluetoothReplyRunnable* aRunnable) = 0;
|
||||
|
||||
/**
|
||||
* Stop device discovery (platform specific implementation)
|
||||
*
|
||||
* @param aAdapterPath Adapter to stop discovery on
|
||||
*
|
||||
* @return NS_OK if discovery stopped correctly, false otherwise
|
||||
*/
|
||||
virtual nsresult StopDiscoveryInternal(const nsAString& aAdapterPath,
|
||||
BluetoothReplyRunnable* aRunnable) = 0;
|
||||
|
||||
/**
|
||||
* Start device discovery (platform specific implementation)
|
||||
*
|
||||
* @param aAdapterPath Adapter to start discovery on
|
||||
*
|
||||
* @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;
|
||||
|
||||
protected:
|
||||
BluetoothService()
|
||||
{
|
||||
mBluetoothSignalObserverTable.Init();
|
||||
}
|
||||
|
||||
virtual ~BluetoothService()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult StartStopBluetooth(BluetoothReplyRunnable* aResultRunnable,
|
||||
bool aStart);
|
||||
// This function is implemented in platform-specific BluetoothServiceFactory
|
||||
// files
|
||||
static BluetoothService* Create();
|
||||
|
||||
typedef mozilla::ObserverList<BluetoothSignal> BluetoothSignalObserverList;
|
||||
typedef nsClassHashtable<nsStringHashKey, BluetoothSignalObserverList >
|
||||
BluetoothSignalObserverTable;
|
||||
|
||||
BluetoothSignalObserverTable mBluetoothSignalObserverTable;
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif
|
@ -1,77 +0,0 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* 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_bluetoothutils_h__
|
||||
#define mozilla_dom_bluetooth_bluetoothutils_h__
|
||||
|
||||
#include "BluetoothCommon.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
/**
|
||||
* BluetoothUtil functions are used to dispatch messages to Bluetooth DOM
|
||||
* objects on the main thread, as well as provide platform indenpendent 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
|
||||
* here.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Add a message handler object from message distribution observer.
|
||||
* Must be called from the main thread.
|
||||
*
|
||||
* @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 RegisterBluetoothEventHandler(const nsCString& aNodeName,
|
||||
BluetoothEventObserver *aMsgHandler);
|
||||
|
||||
/**
|
||||
* Remove a message handler object from message distribution observer.
|
||||
* Must be called from the main thread.
|
||||
*
|
||||
* @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 UnregisterBluetoothEventHandler(const nsCString& aNodeName,
|
||||
BluetoothEventObserver *aMsgHandler);
|
||||
|
||||
/**
|
||||
* Returns the path of the default adapter, implemented via a platform
|
||||
* specific method.
|
||||
*
|
||||
* @return Default adapter path/name on success, NULL otherwise
|
||||
*/
|
||||
nsresult GetDefaultAdapterPathInternal(nsCString& aAdapterPath);
|
||||
|
||||
/**
|
||||
* Set up variables and start the platform specific connection. Must
|
||||
* be called from main thread.
|
||||
*
|
||||
* @return NS_OK if connection starts successfully, NS_ERROR_FAILURE
|
||||
* otherwise
|
||||
*/
|
||||
nsresult StartBluetoothConnection();
|
||||
|
||||
/**
|
||||
* Stop the platform specific connection. Must be called from main
|
||||
* thread.
|
||||
*
|
||||
* @return NS_OK if connection starts successfully, NS_ERROR_FAILURE
|
||||
* otherwise
|
||||
*/
|
||||
nsresult StopBluetoothConnection();
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif
|
@ -15,41 +15,58 @@ XPIDL_MODULE = dom_bluetooth
|
||||
LIBXUL_LIBRARY = 1
|
||||
FORCE_STATIC_LIB = 1
|
||||
|
||||
ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
|
||||
VPATH += $(srcdir)/linux
|
||||
LOCAL_INCLUDES += $(MOZ_DBUS_CFLAGS)
|
||||
endif
|
||||
|
||||
ifdef MOZ_ENABLE_DBUS
|
||||
VPATH += $(srcdir)/linux
|
||||
LOCAL_INCLUDES += $(MOZ_DBUS_CFLAGS)
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/dom/dom-config.mk
|
||||
|
||||
CPPSRCS = \
|
||||
CPPSRCS += \
|
||||
BluetoothService.cpp \
|
||||
BluetoothManager.cpp \
|
||||
BluetoothAdapter.cpp \
|
||||
BluetoothFirmware.cpp \
|
||||
BluetoothDevice.cpp \
|
||||
BluetoothDeviceEvent.cpp \
|
||||
BluetoothReplyRunnable.cpp \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_ENABLE_DBUS
|
||||
CPPSRCS += BluetoothDBusUtils.cpp
|
||||
endif
|
||||
|
||||
ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
|
||||
CPPSRCS += BluetoothDBusUtils.cpp
|
||||
endif
|
||||
|
||||
XPIDLSRCS = \
|
||||
nsIDOMNavigatorBluetooth.idl \
|
||||
nsIDOMBluetoothManager.idl \
|
||||
nsIDOMBluetoothAdapter.idl \
|
||||
nsIDOMBluetoothDevice.idl \
|
||||
nsIDOMBluetoothDeviceEvent.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
|
||||
VPATH += \
|
||||
$(srcdir)/linux \
|
||||
$(srcdir)/gonk \
|
||||
$(NULL)
|
||||
LOCAL_INCLUDES += $(MOZ_DBUS_CFLAGS)
|
||||
CPPSRCS += \
|
||||
BluetoothDBusService.cpp \
|
||||
BluetoothGonkService.cpp \
|
||||
BluetoothGonkServiceFactory.cpp \
|
||||
$(NULL)
|
||||
else
|
||||
ifdef MOZ_ENABLE_DBUS
|
||||
VPATH += $(srcdir)/linux
|
||||
LOCAL_INCLUDES += $(MOZ_DBUS_CFLAGS)
|
||||
CPPSRCS += \
|
||||
BluetoothDBusService.cpp \
|
||||
BluetoothDBusServiceFactory.cpp \
|
||||
$(NULL)
|
||||
CFLAGS += $(MOZ_DBUS_GLIB_CFLAGS)
|
||||
CXXFLAGS += $(MOZ_DBUS_GLIB_CFLAGS) -DHAVE_PTHREADS
|
||||
else
|
||||
CPPSRCS += BluetoothNullServiceFactory.cpp
|
||||
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
|
||||
LOCAL_INCLUDES += $(VPATH:%=-I%)
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
|
150
dom/bluetooth/gonk/BluetoothGonkService.cpp
Normal file
150
dom/bluetooth/gonk/BluetoothGonkService.cpp
Normal file
@ -0,0 +1,150 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* 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 "BluetoothGonkService.h"
|
||||
#include "BluetoothDBusService.h"
|
||||
|
||||
#include "nsDebug.h"
|
||||
#include "nsError.h"
|
||||
#include <dlfcn.h>
|
||||
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
|
||||
static struct BluedroidFunctions
|
||||
{
|
||||
bool initialized;
|
||||
bool tried_initialization;
|
||||
|
||||
BluedroidFunctions() :
|
||||
initialized(false),
|
||||
tried_initialization(false)
|
||||
{
|
||||
}
|
||||
|
||||
int (* bt_enable)();
|
||||
int (* bt_disable)();
|
||||
int (* bt_is_enabled)();
|
||||
} sBluedroidFunctions;
|
||||
|
||||
bool
|
||||
EnsureBluetoothInit()
|
||||
{
|
||||
if (sBluedroidFunctions.tried_initialization)
|
||||
{
|
||||
return sBluedroidFunctions.initialized;
|
||||
}
|
||||
|
||||
sBluedroidFunctions.initialized = false;
|
||||
sBluedroidFunctions.tried_initialization = true;
|
||||
|
||||
void* handle = dlopen("libbluedroid.so", RTLD_LAZY);
|
||||
|
||||
if (!handle) {
|
||||
NS_ERROR("Failed to open libbluedroid.so, bluetooth cannot run");
|
||||
return false;
|
||||
}
|
||||
|
||||
sBluedroidFunctions.bt_enable = (int (*)())dlsym(handle, "bt_enable");
|
||||
if (!sBluedroidFunctions.bt_enable) {
|
||||
NS_ERROR("Failed to attach bt_enable function");
|
||||
return false;
|
||||
}
|
||||
sBluedroidFunctions.bt_disable = (int (*)())dlsym(handle, "bt_disable");
|
||||
if (!sBluedroidFunctions.bt_disable) {
|
||||
NS_ERROR("Failed to attach bt_disable function");
|
||||
return false;
|
||||
}
|
||||
sBluedroidFunctions.bt_is_enabled = (int (*)())dlsym(handle, "bt_is_enabled");
|
||||
if (!sBluedroidFunctions.bt_is_enabled) {
|
||||
NS_ERROR("Failed to attach bt_is_enabled function");
|
||||
return false;
|
||||
}
|
||||
sBluedroidFunctions.initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
IsBluetoothEnabled()
|
||||
{
|
||||
return sBluedroidFunctions.bt_is_enabled();
|
||||
}
|
||||
|
||||
int
|
||||
EnableBluetooth()
|
||||
{
|
||||
return sBluedroidFunctions.bt_enable();
|
||||
}
|
||||
|
||||
int
|
||||
DisableBluetooth()
|
||||
{
|
||||
return sBluedroidFunctions.bt_disable();
|
||||
}
|
||||
|
||||
nsresult
|
||||
StartStopGonkBluetooth(bool aShouldEnable)
|
||||
{
|
||||
bool result;
|
||||
|
||||
// Platform specific check for gonk until object is divided in
|
||||
// different implementations per platform. Linux doesn't require
|
||||
// bluetooth firmware loading, but code should work otherwise.
|
||||
if (!EnsureBluetoothInit()) {
|
||||
NS_ERROR("Failed to load bluedroid library.\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// return 1 if it's enabled, 0 if it's disabled, and -1 on error
|
||||
int isEnabled = IsBluetoothEnabled();
|
||||
|
||||
if ((isEnabled == 1 && aShouldEnable) || (isEnabled == 0 && !aShouldEnable)) {
|
||||
result = true;
|
||||
} else if (isEnabled < 0) {
|
||||
result = false;
|
||||
} else if (aShouldEnable) {
|
||||
result = (EnableBluetooth() == 0) ? true : false;
|
||||
} else {
|
||||
result = (DisableBluetooth() == 0) ? true : false;
|
||||
}
|
||||
if (!result) {
|
||||
NS_WARNING("Could not set gonk bluetooth firmware!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothGonkService::StartInternal()
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "This should not run on the main thread!");
|
||||
|
||||
nsresult ret;
|
||||
|
||||
ret = StartStopGonkBluetooth(true);
|
||||
|
||||
if (NS_FAILED(ret)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return BluetoothDBusService::StartInternal();
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothGonkService::StopInternal()
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "This should not run on the main thread!");
|
||||
nsresult ret;
|
||||
|
||||
ret = StartStopGonkBluetooth(false);
|
||||
|
||||
if (NS_FAILED(ret)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return BluetoothDBusService::StopInternal();
|
||||
}
|
||||
|
48
dom/bluetooth/gonk/BluetoothGonkService.h
Normal file
48
dom/bluetooth/gonk/BluetoothGonkService.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* 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_bluetoothgonkservice_h__
|
||||
#define mozilla_dom_bluetooth_bluetoothgonkservice_h__
|
||||
|
||||
#include "BluetoothCommon.h"
|
||||
#include "BluetoothDBusService.h"
|
||||
|
||||
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
|
||||
* 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
|
||||
* here.
|
||||
*/
|
||||
|
||||
class BluetoothGonkService : public BluetoothDBusService
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Set up variables and start the platform specific connection. Must
|
||||
* be called from main thread.
|
||||
*
|
||||
* @return NS_OK if connection starts successfully, NS_ERROR_FAILURE
|
||||
* otherwise
|
||||
*/
|
||||
virtual nsresult StartInternal();
|
||||
|
||||
/**
|
||||
* Stop the platform specific connection. Must be called from main
|
||||
* thread.
|
||||
*
|
||||
* @return NS_OK if connection starts successfully, NS_ERROR_FAILURE
|
||||
* otherwise
|
||||
*/
|
||||
virtual nsresult StopInternal();
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif
|
15
dom/bluetooth/gonk/BluetoothGonkServiceFactory.cpp
Normal file
15
dom/bluetooth/gonk/BluetoothGonkServiceFactory.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* 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 "BluetoothGonkService.h"
|
||||
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
|
||||
BluetoothService*
|
||||
BluetoothService::Create()
|
||||
{
|
||||
return new BluetoothGonkService();
|
||||
}
|
62
dom/bluetooth/ipc/BluetoothTypes.ipdlh
Normal file
62
dom/bluetooth/ipc/BluetoothTypes.ipdlh
Normal file
@ -0,0 +1,62 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* 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/. */
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace bluetooth {
|
||||
|
||||
/**
|
||||
* Value structure for returns from bluetooth. Currently modeled after dbus
|
||||
* returns, which can be a 32-bit int, an UTF16 string, a bool, or an array of
|
||||
* UTF16 strings. Can also hold key-value pairs for dictionary-ish access.
|
||||
*
|
||||
*/
|
||||
union BluetoothValue
|
||||
{
|
||||
uint32_t;
|
||||
nsString;
|
||||
bool;
|
||||
nsString[];
|
||||
BluetoothNamedValue[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Key-value pair for dicts returned by the bluetooth backend. Used for things
|
||||
* like property updates, where the property will have a name and a type.
|
||||
*
|
||||
*/
|
||||
struct BluetoothNamedValue
|
||||
{
|
||||
nsString name;
|
||||
BluetoothValue value;
|
||||
};
|
||||
|
||||
struct BluetoothSignal
|
||||
{
|
||||
nsString name;
|
||||
nsString path;
|
||||
BluetoothValue value;
|
||||
};
|
||||
|
||||
struct BluetoothReplySuccess
|
||||
{
|
||||
BluetoothValue value;
|
||||
};
|
||||
|
||||
struct BluetoothReplyError
|
||||
{
|
||||
nsString error;
|
||||
};
|
||||
|
||||
union BluetoothReply
|
||||
{
|
||||
BluetoothReplySuccess;
|
||||
BluetoothReplyError;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
7
dom/bluetooth/ipc/ipdl.mk
Normal file
7
dom/bluetooth/ipc/ipdl.mk
Normal file
@ -0,0 +1,7 @@
|
||||
# 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/.
|
||||
|
||||
IPDLSRCS = \
|
||||
BluetoothTypes.ipdlh \
|
||||
$(NULL)
|
577
dom/bluetooth/linux/BluetoothDBusService.cpp
Normal file
577
dom/bluetooth/linux/BluetoothDBusService.cpp
Normal file
@ -0,0 +1,577 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/*
|
||||
** Copyright 2006, The Android Open Source Project
|
||||
**
|
||||
** 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 "base/basictypes.h"
|
||||
#include "BluetoothDBusService.h"
|
||||
#include "BluetoothTypes.h"
|
||||
#include "BluetoothReplyRunnable.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
#include "nsIDOMDOMRequest.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "mozilla/ipc/DBusThread.h"
|
||||
#include "mozilla/ipc/DBusUtils.h"
|
||||
#include "mozilla/ipc/RawDBusConnection.h"
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
/**
|
||||
* Some rules for dealing with memory in DBus:
|
||||
* - A DBusError only needs to be deleted if it's been set, not just
|
||||
* initialized. This is why LOG_AND_FREE... is called only when an error is
|
||||
* set, and the macro cleans up the error itself.
|
||||
* - A DBusMessage needs to be unrefed when it is newed explicitly. DBusMessages
|
||||
* from signals do not need to be unrefed, as they will be cleaned by DBus
|
||||
* after DBUS_HANDLER_RESULT_HANDLED is returned from the filter.
|
||||
*/
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::ipc;
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
|
||||
#undef LOG
|
||||
#if defined(MOZ_WIDGET_GONK)
|
||||
#include <android/log.h>
|
||||
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GonkDBus", args);
|
||||
#else
|
||||
#define BTDEBUG true
|
||||
#define LOG(args...) if (BTDEBUG) printf(args);
|
||||
#endif
|
||||
|
||||
#define DBUS_ADAPTER_IFACE BLUEZ_DBUS_BASE_IFC ".Adapter"
|
||||
#define DBUS_DEVICE_IFACE BLUEZ_DBUS_BASE_IFC ".Device"
|
||||
#define BLUEZ_DBUS_BASE_PATH "/org/bluez"
|
||||
#define BLUEZ_DBUS_BASE_IFC "org.bluez"
|
||||
#define BLUEZ_ERROR_IFC "org.bluez.Error"
|
||||
|
||||
typedef struct {
|
||||
const char* name;
|
||||
int type;
|
||||
} Properties;
|
||||
|
||||
static Properties remote_device_properties[] = {
|
||||
{"Address", DBUS_TYPE_STRING},
|
||||
{"Name", DBUS_TYPE_STRING},
|
||||
{"Icon", DBUS_TYPE_STRING},
|
||||
{"Class", DBUS_TYPE_UINT32},
|
||||
{"UUIDs", DBUS_TYPE_ARRAY},
|
||||
{"Services", DBUS_TYPE_ARRAY},
|
||||
{"Paired", DBUS_TYPE_BOOLEAN},
|
||||
{"Connected", DBUS_TYPE_BOOLEAN},
|
||||
{"Trusted", DBUS_TYPE_BOOLEAN},
|
||||
{"Blocked", DBUS_TYPE_BOOLEAN},
|
||||
{"Alias", DBUS_TYPE_STRING},
|
||||
{"Nodes", DBUS_TYPE_ARRAY},
|
||||
{"Adapter", DBUS_TYPE_OBJECT_PATH},
|
||||
{"LegacyPairing", DBUS_TYPE_BOOLEAN},
|
||||
{"RSSI", DBUS_TYPE_INT16},
|
||||
{"TX", DBUS_TYPE_UINT32},
|
||||
{"Broadcaster", DBUS_TYPE_BOOLEAN}
|
||||
};
|
||||
|
||||
static Properties adapter_properties[] = {
|
||||
{"Address", DBUS_TYPE_STRING},
|
||||
{"Name", DBUS_TYPE_STRING},
|
||||
{"Class", DBUS_TYPE_UINT32},
|
||||
{"Powered", DBUS_TYPE_BOOLEAN},
|
||||
{"Discoverable", DBUS_TYPE_BOOLEAN},
|
||||
{"DiscoverableTimeout", DBUS_TYPE_UINT32},
|
||||
{"Pairable", DBUS_TYPE_BOOLEAN},
|
||||
{"PairableTimeout", DBUS_TYPE_UINT32},
|
||||
{"Discovering", DBUS_TYPE_BOOLEAN},
|
||||
{"Devices", DBUS_TYPE_ARRAY},
|
||||
{"UUIDs", DBUS_TYPE_ARRAY},
|
||||
};
|
||||
|
||||
static const char* BLUETOOTH_DBUS_SIGNALS[] =
|
||||
{
|
||||
"type='signal',interface='org.freedesktop.DBus'",
|
||||
"type='signal',interface='org.bluez.Adapter'",
|
||||
"type='signal',interface='org.bluez.Manager'",
|
||||
"type='signal',interface='org.bluez.Device'",
|
||||
"type='signal',interface='org.bluez.Input'",
|
||||
"type='signal',interface='org.bluez.Network'",
|
||||
"type='signal',interface='org.bluez.NetworkServer'",
|
||||
"type='signal',interface='org.bluez.HealthDevice'",
|
||||
"type='signal',interface='org.bluez.AudioSink'"
|
||||
};
|
||||
|
||||
class DistributeBluetoothSignalTask : public nsRunnable {
|
||||
BluetoothSignal mSignal;
|
||||
public:
|
||||
DistributeBluetoothSignalTask(const BluetoothSignal& aSignal) :
|
||||
mSignal(aSignal)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
MOZ_ASSERT(bs);
|
||||
return bs->DistributeSignal(mSignal);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
bool
|
||||
IsDBusMessageError(DBusMessage* aMsg, nsAString& aError)
|
||||
{
|
||||
DBusError err;
|
||||
dbus_error_init(&err);
|
||||
if (dbus_message_get_type(aMsg) == DBUS_MESSAGE_TYPE_ERROR) {
|
||||
const char* error_msg;
|
||||
if (!dbus_message_get_args(aMsg, &err, DBUS_TYPE_STRING,
|
||||
&error_msg, DBUS_TYPE_INVALID) ||
|
||||
!error_msg) {
|
||||
if (dbus_error_is_set(&err)) {
|
||||
aError = NS_ConvertUTF8toUTF16(err.message);
|
||||
LOG_AND_FREE_DBUS_ERROR(&err);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
aError = NS_ConvertUTF8toUTF16(error_msg);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable,
|
||||
const BluetoothValue& aValue, const nsAString& aError)
|
||||
{
|
||||
// Reply will be deleted by the runnable after running on main thread
|
||||
BluetoothReply* reply;
|
||||
if (!aError.IsEmpty()) {
|
||||
nsString err(aError);
|
||||
reply = new BluetoothReply(BluetoothReplyError(err));
|
||||
}
|
||||
else {
|
||||
reply = new BluetoothReply(BluetoothReplySuccess(aValue));
|
||||
}
|
||||
|
||||
aRunnable->SetReply(reply);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(aRunnable))) {
|
||||
NS_WARNING("Failed to dispatch to main thread!");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GetObjectPathCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
DBusError err;
|
||||
dbus_error_init(&err);
|
||||
nsRefPtr<BluetoothReplyRunnable> replyRunnable =
|
||||
dont_AddRef(static_cast< BluetoothReplyRunnable* >(aBluetoothReplyRunnable));
|
||||
|
||||
NS_ASSERTION(replyRunnable, "Callback reply runnable is null!");
|
||||
|
||||
nsString replyError;
|
||||
nsString replyPath;
|
||||
|
||||
nsTArray<BluetoothNamedValue> replyValues;
|
||||
BluetoothValue v;
|
||||
if (!IsDBusMessageError(aMsg, replyError)) {
|
||||
NS_ASSERTION(dbus_message_get_type(aMsg) == DBUS_MESSAGE_TYPE_METHOD_RETURN,
|
||||
"Got dbus callback that's not a METHOD_RETURN!");
|
||||
const char* object_path;
|
||||
if (!dbus_message_get_args(aMsg, &err, DBUS_TYPE_OBJECT_PATH,
|
||||
&object_path, DBUS_TYPE_INVALID) ||
|
||||
!object_path) {
|
||||
if (dbus_error_is_set(&err)) {
|
||||
replyError = NS_ConvertUTF8toUTF16(err.message);
|
||||
LOG_AND_FREE_DBUS_ERROR(&err);
|
||||
}
|
||||
} else {
|
||||
v = NS_ConvertUTF8toUTF16(object_path);
|
||||
}
|
||||
}
|
||||
DispatchBluetoothReply(replyRunnable, v, replyError);
|
||||
}
|
||||
|
||||
void
|
||||
GetVoidCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
DBusError err;
|
||||
dbus_error_init(&err);
|
||||
nsRefPtr<BluetoothReplyRunnable> replyRunnable =
|
||||
dont_AddRef(static_cast< BluetoothReplyRunnable* >(aBluetoothReplyRunnable));
|
||||
|
||||
NS_ASSERTION(replyRunnable, "Callback reply runnable is null!");
|
||||
|
||||
nsString replyError;
|
||||
BluetoothValue v;
|
||||
if (!IsDBusMessageError(aMsg, replyError) &&
|
||||
dbus_message_get_type(aMsg) == DBUS_MESSAGE_TYPE_METHOD_RETURN &&
|
||||
!dbus_message_get_args(aMsg, &err, DBUS_TYPE_INVALID)) {
|
||||
if (dbus_error_is_set(&err)) {
|
||||
replyError = NS_ConvertUTF8toUTF16(err.message);
|
||||
LOG_AND_FREE_DBUS_ERROR(&err);
|
||||
}
|
||||
}
|
||||
DispatchBluetoothReply(replyRunnable, v, replyError);
|
||||
}
|
||||
|
||||
bool
|
||||
GetProperty(DBusMessageIter aIter, Properties* aPropertyTypes,
|
||||
int aPropertiesTypeLen, int* aPropIndex,
|
||||
InfallibleTArray<BluetoothNamedValue>& aProperties)
|
||||
{
|
||||
DBusMessageIter prop_val, array_val_iter;
|
||||
char* property = NULL;
|
||||
uint32_t array_type;
|
||||
int i, type;
|
||||
|
||||
if (dbus_message_iter_get_arg_type(&aIter) != DBUS_TYPE_STRING) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dbus_message_iter_get_basic(&aIter, &property);
|
||||
|
||||
if (!dbus_message_iter_next(&aIter) ||
|
||||
dbus_message_iter_get_arg_type(&aIter) != DBUS_TYPE_VARIANT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < aPropertiesTypeLen; i++) {
|
||||
if (!strncmp(property, aPropertyTypes[i].name, strlen(property))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == aPropertiesTypeLen) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsString propertyName;
|
||||
propertyName.AssignASCII(aPropertyTypes[i].name);
|
||||
*aPropIndex = i;
|
||||
|
||||
dbus_message_iter_recurse(&aIter, &prop_val);
|
||||
type = aPropertyTypes[*aPropIndex].type;
|
||||
|
||||
NS_ASSERTION(dbus_message_iter_get_arg_type(&prop_val) == type,
|
||||
"Iterator not type we expect!");
|
||||
|
||||
BluetoothValue propertyValue;
|
||||
switch (type) {
|
||||
case DBUS_TYPE_STRING:
|
||||
case DBUS_TYPE_OBJECT_PATH:
|
||||
const char* c;
|
||||
dbus_message_iter_get_basic(&prop_val, &c);
|
||||
propertyValue = NS_ConvertUTF8toUTF16(c);
|
||||
break;
|
||||
case DBUS_TYPE_UINT32:
|
||||
case DBUS_TYPE_INT16:
|
||||
uint32_t i;
|
||||
dbus_message_iter_get_basic(&prop_val, &i);
|
||||
propertyValue = i;
|
||||
break;
|
||||
case DBUS_TYPE_BOOLEAN:
|
||||
bool b;
|
||||
dbus_message_iter_get_basic(&prop_val, &b);
|
||||
propertyValue = b;
|
||||
break;
|
||||
case DBUS_TYPE_ARRAY:
|
||||
dbus_message_iter_recurse(&prop_val, &array_val_iter);
|
||||
array_type = dbus_message_iter_get_arg_type(&array_val_iter);
|
||||
if (array_type == DBUS_TYPE_OBJECT_PATH ||
|
||||
array_type == DBUS_TYPE_STRING){
|
||||
InfallibleTArray<nsString> arr;
|
||||
do {
|
||||
const char* tmp;
|
||||
dbus_message_iter_get_basic(&array_val_iter, &tmp);
|
||||
nsString s;
|
||||
s = NS_ConvertUTF8toUTF16(tmp);
|
||||
arr.AppendElement(s);
|
||||
} while (dbus_message_iter_next(&array_val_iter));
|
||||
propertyValue = arr;
|
||||
} else {
|
||||
NS_WARNING("Received array type that's not a string array!");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
NS_NOTREACHED("Cannot find dbus message type!");
|
||||
}
|
||||
aProperties.AppendElement(BluetoothNamedValue(propertyName, propertyValue));
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ParseProperties(DBusMessageIter* aIter,
|
||||
Properties* aPropertyTypes,
|
||||
const int aPropertiesTypeLen,
|
||||
InfallibleTArray<BluetoothNamedValue>& aProperties)
|
||||
{
|
||||
DBusMessageIter dict_entry, dict;
|
||||
int prop_index = -1;
|
||||
|
||||
NS_ASSERTION(dbus_message_iter_get_arg_type(aIter) == DBUS_TYPE_ARRAY,
|
||||
"Trying to parse a property from something that's not an array!");
|
||||
|
||||
dbus_message_iter_recurse(aIter, &dict);
|
||||
|
||||
do {
|
||||
NS_ASSERTION(dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY,
|
||||
"Trying to parse a property from something that's not an dict!");
|
||||
dbus_message_iter_recurse(&dict, &dict_entry);
|
||||
|
||||
if (!GetProperty(dict_entry, aPropertyTypes, aPropertiesTypeLen, &prop_index,
|
||||
aProperties)) {
|
||||
NS_WARNING("Can't create property!");
|
||||
return;
|
||||
}
|
||||
} while (dbus_message_iter_next(&dict));
|
||||
}
|
||||
|
||||
void
|
||||
ParsePropertyChange(DBusMessage* aMsg, Properties* aPropertyTypes,
|
||||
const int aPropertiesTypeLen,
|
||||
InfallibleTArray<BluetoothNamedValue>& aProperties)
|
||||
{
|
||||
DBusMessageIter iter;
|
||||
DBusError err;
|
||||
int prop_index = -1;
|
||||
|
||||
dbus_error_init(&err);
|
||||
if (!dbus_message_iter_init(aMsg, &iter)) {
|
||||
LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, aMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!GetProperty(iter, aPropertyTypes, aPropertiesTypeLen,
|
||||
&prop_index, aProperties)) {
|
||||
NS_WARNING("Can't get property!");
|
||||
}
|
||||
}
|
||||
|
||||
// Called by dbus during WaitForAndDispatchEventNative()
|
||||
// This function is called on the IOThread
|
||||
static
|
||||
DBusHandlerResult
|
||||
EventFilter(DBusConnection* aConn, DBusMessage* aMsg, void* aData)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Shouldn't be called from Main Thread!");
|
||||
|
||||
if (dbus_message_get_type(aMsg) != DBUS_MESSAGE_TYPE_SIGNAL) {
|
||||
LOG("%s: not interested (not a signal).\n", __FUNCTION__);
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
|
||||
if (dbus_message_get_path(aMsg) == NULL) {
|
||||
LOG("DBusMessage %s has no bluetooth destination, ignoring\n",
|
||||
dbus_message_get_member(aMsg));
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
|
||||
DBusError err;
|
||||
nsString signalPath;
|
||||
nsString signalName;
|
||||
dbus_error_init(&err);
|
||||
signalPath = NS_ConvertUTF8toUTF16(dbus_message_get_path(aMsg));
|
||||
LOG("%s: Received signal %s:%s from %s\n", __FUNCTION__,
|
||||
dbus_message_get_interface(aMsg), dbus_message_get_member(aMsg),
|
||||
dbus_message_get_path(aMsg));
|
||||
|
||||
signalName = NS_ConvertUTF8toUTF16(dbus_message_get_member(aMsg));
|
||||
BluetoothValue v;
|
||||
|
||||
if (dbus_message_is_signal(aMsg, DBUS_ADAPTER_IFACE, "DeviceFound")) {
|
||||
|
||||
DBusMessageIter iter;
|
||||
|
||||
NS_ASSERTION(dbus_message_iter_init(aMsg, &iter),
|
||||
"Can't create message iterator!");
|
||||
|
||||
InfallibleTArray<BluetoothNamedValue> value;
|
||||
const char* addr;
|
||||
dbus_message_iter_get_basic(&iter, &addr);
|
||||
value.AppendElement(BluetoothNamedValue(NS_LITERAL_STRING("Address"),
|
||||
NS_ConvertUTF8toUTF16(addr)));
|
||||
|
||||
if (dbus_message_iter_next(&iter)) {
|
||||
ParseProperties(&iter,
|
||||
remote_device_properties,
|
||||
ArrayLength(remote_device_properties),
|
||||
value);
|
||||
NS_ASSERTION(value.Length() != 0, "Properties returned empty!");
|
||||
v = value;
|
||||
} else {
|
||||
NS_WARNING("DBus iterator not as long as expected!");
|
||||
}
|
||||
} else if (dbus_message_is_signal(aMsg, DBUS_ADAPTER_IFACE, "DeviceDisappeared")) {
|
||||
const char* str;
|
||||
if (!dbus_message_get_args(aMsg, &err,
|
||||
DBUS_TYPE_STRING, &str,
|
||||
DBUS_TYPE_INVALID)) {
|
||||
LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, aMsg);
|
||||
}
|
||||
v = NS_ConvertUTF8toUTF16(str);
|
||||
} else if (dbus_message_is_signal(aMsg, DBUS_ADAPTER_IFACE, "DeviceCreated")) {
|
||||
const char* str;
|
||||
if (!dbus_message_get_args(aMsg, &err,
|
||||
DBUS_TYPE_OBJECT_PATH, &str,
|
||||
DBUS_TYPE_INVALID)) {
|
||||
LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, aMsg);
|
||||
}
|
||||
v = NS_ConvertUTF8toUTF16(str);
|
||||
} else if (dbus_message_is_signal(aMsg, DBUS_ADAPTER_IFACE, "PropertyChanged")) {
|
||||
InfallibleTArray<BluetoothNamedValue> value;
|
||||
ParsePropertyChange(aMsg,
|
||||
(Properties*)&adapter_properties,
|
||||
ArrayLength(adapter_properties),
|
||||
value);
|
||||
NS_ASSERTION(value.Length() != 0, "Properties returned empty!");
|
||||
v = value;
|
||||
}
|
||||
|
||||
BluetoothSignal signal(signalName, signalPath, v);
|
||||
|
||||
nsRefPtr<DistributeBluetoothSignalTask>
|
||||
t = new DistributeBluetoothSignalTask(signal);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(t))) {
|
||||
NS_WARNING("Failed to dispatch to main thread!");
|
||||
}
|
||||
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothDBusService::StartInternal()
|
||||
{
|
||||
// This could block. It should never be run on the main thread.
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
if (!StartDBus()) {
|
||||
NS_WARNING("Cannot start DBus thread!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (mConnection) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (NS_FAILED(EstablishDBusConnection())) {
|
||||
NS_WARNING("Cannot start DBus connection!");
|
||||
StopDBus();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Add a filter for all incoming messages_base
|
||||
if (!dbus_connection_add_filter(mConnection, EventFilter,
|
||||
NULL, NULL)) {
|
||||
NS_WARNING("Cannot create DBus Event Filter for DBus Thread!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothDBusService::StopInternal()
|
||||
{
|
||||
// This could block. It should never be run on the main thread.
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
if (!mConnection) {
|
||||
StopDBus();
|
||||
return NS_OK;
|
||||
}
|
||||
dbus_connection_remove_filter(mConnection, EventFilter, NULL);
|
||||
mConnection = nsnull;
|
||||
mBluetoothSignalObserverTable.Clear();
|
||||
StopDBus();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothDBusService::GetDefaultAdapterPathInternal(BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
if (!mConnection) {
|
||||
NS_ERROR("Bluetooth service not started yet!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!");
|
||||
|
||||
nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
|
||||
|
||||
if (!dbus_func_args_async(mConnection,
|
||||
1000,
|
||||
GetObjectPathCallback,
|
||||
(void*)aRunnable,
|
||||
"/",
|
||||
"org.bluez.Manager",
|
||||
"DefaultAdapter",
|
||||
DBUS_TYPE_INVALID)) {
|
||||
NS_WARNING("Could not start async function!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
runnable.forget();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
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!");
|
||||
|
||||
nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
|
||||
|
||||
const char* s = NS_ConvertUTF16toUTF8(aAdapterPath).get();
|
||||
if (!dbus_func_args_async(mConnection,
|
||||
1000,
|
||||
GetVoidCallback,
|
||||
(void*)aRunnable,
|
||||
s,
|
||||
DBUS_ADAPTER_IFACE,
|
||||
aMessageName,
|
||||
DBUS_TYPE_INVALID)) {
|
||||
NS_WARNING("Could not start async function!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
runnable.forget();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothDBusService::StopDiscoveryInternal(const nsAString& aAdapterPath,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
return SendDiscoveryMessage(aAdapterPath, "StopDiscovery", aRunnable);
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothDBusService::StartDiscoveryInternal(const nsAString& aAdapterPath,
|
||||
BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
return SendDiscoveryMessage(aAdapterPath, "StartDiscovery", aRunnable);
|
||||
}
|
84
dom/bluetooth/linux/BluetoothDBusService.h
Normal file
84
dom/bluetooth/linux/BluetoothDBusService.h
Normal file
@ -0,0 +1,84 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* 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_bluetoothdbuseventservice_h__
|
||||
#define mozilla_dom_bluetooth_bluetoothdbuseventservice_h__
|
||||
|
||||
#include "BluetoothCommon.h"
|
||||
#include "mozilla/ipc/RawDBusConnection.h"
|
||||
#include "BluetoothService.h"
|
||||
|
||||
class DBusMessage;
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
/**
|
||||
* BluetoothService functions are used to dispatch messages to Bluetooth DOM
|
||||
* 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
|
||||
* here.
|
||||
*/
|
||||
|
||||
class BluetoothDBusService : public BluetoothService
|
||||
, private mozilla::ipc::RawDBusConnection
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Set up variables and start the platform specific connection. Must
|
||||
* be called from outside main thread.
|
||||
*
|
||||
* @return NS_OK if connection starts successfully, NS_ERROR_FAILURE
|
||||
* otherwise
|
||||
*/
|
||||
virtual nsresult StartInternal();
|
||||
|
||||
/**
|
||||
* Stop the platform specific connection. Must be called from outside main
|
||||
* thread.
|
||||
*
|
||||
* @return NS_OK if connection starts successfully, NS_ERROR_FAILURE
|
||||
* otherwise
|
||||
*/
|
||||
virtual nsresult StopInternal();
|
||||
|
||||
/**
|
||||
* Returns the path of the default adapter, implemented via a platform
|
||||
* specific method.
|
||||
*
|
||||
* @return Default adapter path/name on success, NULL otherwise
|
||||
*/
|
||||
virtual nsresult GetDefaultAdapterPathInternal(BluetoothReplyRunnable* aRunnable);
|
||||
|
||||
/**
|
||||
* Start device discovery (platform specific implementation)
|
||||
*
|
||||
* @param aAdapterPath Adapter to start discovery on
|
||||
*
|
||||
* @return NS_OK if discovery stopped correctly, NS_ERROR_FAILURE otherwise
|
||||
*/
|
||||
virtual nsresult StartDiscoveryInternal(const nsAString& aAdapterPath,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
/**
|
||||
* Stop device discovery (platform specific implementation)
|
||||
*
|
||||
* @param aAdapterPath Adapter to stop discovery on
|
||||
*
|
||||
* @return NS_OK if discovery stopped correctly, NS_ERROR_FAILURE otherwise
|
||||
*/
|
||||
virtual nsresult StopDiscoveryInternal(const nsAString& aAdapterPath,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
|
||||
private:
|
||||
nsresult SendDiscoveryMessage(const nsAString& aAdapterPath,
|
||||
const char* aMessageName,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif
|
15
dom/bluetooth/linux/BluetoothDBusServiceFactory.cpp
Normal file
15
dom/bluetooth/linux/BluetoothDBusServiceFactory.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* 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();
|
||||
}
|
@ -6,7 +6,31 @@
|
||||
|
||||
#include "nsIDOMEventTarget.idl"
|
||||
|
||||
[scriptable, builtinclass, uuid(fe6602d2-f32f-4b95-bf66-028452bbe6d2)]
|
||||
interface nsIDOMDOMRequest;
|
||||
interface nsIDOMBluetoothDevice;
|
||||
|
||||
[scriptable, builtinclass, uuid(48df7f05-2bbc-4ac8-aa88-9fecd4c24028)]
|
||||
interface nsIDOMBluetoothAdapter : nsIDOMEventTarget
|
||||
{
|
||||
readonly attribute DOMString address;
|
||||
[binaryname(AdapterClass)] readonly attribute unsigned long class;
|
||||
readonly attribute bool enabled;
|
||||
readonly attribute bool discovering;
|
||||
|
||||
[implicit_jscontext]
|
||||
readonly attribute jsval devices;
|
||||
|
||||
readonly attribute DOMString name;
|
||||
readonly attribute bool discoverable;
|
||||
// Unit: sec
|
||||
readonly attribute unsigned long discoverableTimeout;
|
||||
|
||||
nsIDOMDOMRequest startDiscovery();
|
||||
nsIDOMDOMRequest stopDiscovery();
|
||||
// Fired when discoverying and any device is discovered.
|
||||
attribute nsIDOMEventListener ondevicefound;
|
||||
// Fired when any device is out of discoverable range.
|
||||
attribute nsIDOMEventListener ondevicedisappeared;
|
||||
// Fired when a property of the adapter is changed
|
||||
attribute nsIDOMEventListener onpropertychanged;
|
||||
};
|
||||
|
19
dom/bluetooth/nsIDOMBluetoothDevice.idl
Normal file
19
dom/bluetooth/nsIDOMBluetoothDevice.idl
Normal file
@ -0,0 +1,19 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* 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 "nsIDOMEventTarget.idl"
|
||||
|
||||
[scriptable, builtinclass, uuid(2c446123-b5dd-4631-80f6-eda91befd8c9)]
|
||||
interface nsIDOMBluetoothDevice : nsIDOMEventTarget
|
||||
{
|
||||
readonly attribute DOMString address;
|
||||
readonly attribute DOMString name;
|
||||
|
||||
[binaryname(DeviceClass)] readonly attribute unsigned long class;
|
||||
readonly attribute bool connected;
|
||||
readonly attribute bool paired;
|
||||
attribute nsIDOMEventListener onpropertychanged;
|
||||
};
|
15
dom/bluetooth/nsIDOMBluetoothDeviceEvent.idl
Normal file
15
dom/bluetooth/nsIDOMBluetoothDeviceEvent.idl
Normal file
@ -0,0 +1,15 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* 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 "nsIDOMEvent.idl"
|
||||
|
||||
interface nsIDOMBluetoothDevice;
|
||||
|
||||
[scriptable, builtinclass, uuid(49294da3-b698-4a7f-aca2-3f9bc44c7625)]
|
||||
interface nsIDOMBluetoothDeviceEvent : nsIDOMEvent
|
||||
{
|
||||
readonly attribute nsIDOMBluetoothDevice device;
|
||||
};
|
@ -9,11 +9,11 @@
|
||||
interface nsIDOMDOMRequest;
|
||||
interface nsIDOMBluetoothAdapter;
|
||||
|
||||
[scriptable, builtinclass, uuid(9d4bcbad-8904-4985-b366-036d32959312)]
|
||||
[scriptable, builtinclass, uuid(1442c310-8233-4670-8aa9-752ad673bae0)]
|
||||
interface nsIDOMBluetoothManager : nsIDOMEventTarget
|
||||
{
|
||||
readonly attribute bool enabled;
|
||||
readonly attribute nsIDOMBluetoothAdapter defaultAdapter;
|
||||
|
||||
nsIDOMDOMRequest getDefaultAdapter();
|
||||
nsIDOMDOMRequest setEnabled(in boolean enabled);
|
||||
};
|
||||
|
@ -19,36 +19,19 @@
|
||||
#include "AutoMounter.h"
|
||||
#endif
|
||||
#include "mozilla/ipc/Ril.h"
|
||||
#ifdef MOZ_B2G_BT
|
||||
#include "mozilla/ipc/DBusThread.h"
|
||||
#include "BluetoothFirmware.h"
|
||||
#include "BluetoothUtils.h"
|
||||
#endif
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsRadioInterfaceLayer.h"
|
||||
#include "WifiWorker.h"
|
||||
|
||||
#undef LOG
|
||||
#if defined(MOZ_WIDGET_GONK)
|
||||
#include <android/log.h>
|
||||
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GonkBluetooth", args);
|
||||
#else
|
||||
#define BTDEBUG true
|
||||
#define LOG(args...) if(BTDEBUG) printf(args);
|
||||
#endif
|
||||
|
||||
|
||||
USING_WORKERS_NAMESPACE
|
||||
|
||||
using namespace mozilla::dom::gonk;
|
||||
using namespace mozilla::ipc;
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
using namespace mozilla::system;
|
||||
#endif
|
||||
#ifdef MOZ_B2G_BT
|
||||
using namespace mozilla::dom::bluetooth;
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
@ -229,15 +212,6 @@ SystemWorkerManager::Init()
|
||||
return rv;
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G_BT
|
||||
rv = InitBluetooth(cx);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Failed to initialize Bluetooth!");
|
||||
return rv;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
InitAutoMounter();
|
||||
#endif
|
||||
@ -270,9 +244,7 @@ SystemWorkerManager::Shutdown()
|
||||
#endif
|
||||
|
||||
StopRil();
|
||||
#ifdef MOZ_B2G_BT
|
||||
StopDBus();
|
||||
#endif
|
||||
|
||||
mRILWorker = nsnull;
|
||||
nsCOMPtr<nsIWifi> wifi(do_QueryInterface(mWifiWorker));
|
||||
if (wifi) {
|
||||
@ -385,29 +357,6 @@ SystemWorkerManager::InitWifi(JSContext *cx)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SystemWorkerManager::InitBluetooth(JSContext *cx)
|
||||
{
|
||||
#ifdef MOZ_B2G_BT
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
// We need a platform specific check here to make sure of when we're
|
||||
// running on an emulator. Therefore, if we're compiled with gonk,
|
||||
// see if we can load functions out of bluedroid. If not, assume
|
||||
// it's an emulator and don't start the bluetooth thread.
|
||||
if(EnsureBluetoothInit()) {
|
||||
#endif
|
||||
StartDBus();
|
||||
StartBluetoothConnection();
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
}
|
||||
else {
|
||||
LOG("Bluedroid functions not available, assuming running on simulator. Not starting DBus thread.");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS2(SystemWorkerManager, nsIObserver, nsIInterfaceRequestor)
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -45,8 +45,7 @@ private:
|
||||
|
||||
nsresult InitRIL(JSContext *cx);
|
||||
nsresult InitWifi(JSContext *cx);
|
||||
nsresult InitBluetooth(JSContext *cx);
|
||||
|
||||
|
||||
nsCOMPtr<nsIWorkerHolder> mRILWorker;
|
||||
nsCOMPtr<nsIWorkerHolder> mWifiWorker;
|
||||
|
||||
|
@ -46,7 +46,6 @@
|
||||
#include "base/message_loop.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
#include "mozilla/Util.h"
|
||||
#include "mozilla/FileUtils.h"
|
||||
@ -62,7 +61,7 @@
|
||||
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GonkDBus", args);
|
||||
#else
|
||||
#define BTDEBUG true
|
||||
#define LOG(args...) if(BTDEBUG) printf(args);
|
||||
#define LOG(args...) if (BTDEBUG) printf(args);
|
||||
#endif
|
||||
|
||||
#define DEFAULT_INITIAL_POLLFD_COUNT 8
|
||||
@ -131,14 +130,12 @@ struct DBusThread : public RawDBusConnection
|
||||
~DBusThread();
|
||||
|
||||
bool StartEventLoop();
|
||||
void StopEventLoop();
|
||||
bool StopEventLoop();
|
||||
bool IsEventLoopRunning();
|
||||
static void* EventLoop(void* aPtr);
|
||||
void EventLoop();
|
||||
|
||||
// Thread members
|
||||
pthread_t mThread;
|
||||
Mutex mMutex;
|
||||
bool mIsRunning;
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
|
||||
// Information about the sockets we're polling. Socket counts
|
||||
// increase/decrease depending on how many add/remove watch signals
|
||||
@ -173,25 +170,25 @@ AddWatch(DBusWatch *aWatch, void *aData)
|
||||
// to by our eventloop and remove this watch.. reading the add first
|
||||
// and then inspecting the recently deceased watch would be bad.
|
||||
char control = DBUS_EVENT_LOOP_ADD;
|
||||
if(write(dbt->mControlFdW.get(), &control, sizeof(char)) < 0) {
|
||||
if (write(dbt->mControlFdW.get(), &control, sizeof(char)) < 0) {
|
||||
LOG("Cannot write DBus add watch control data to socket!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO change this to dbus_watch_get_unix_fd once we move to ics
|
||||
int fd = dbus_watch_get_fd(aWatch);
|
||||
if(write(dbt->mControlFdW.get(), &fd, sizeof(int)) < 0) {
|
||||
if (write(dbt->mControlFdW.get(), &fd, sizeof(int)) < 0) {
|
||||
LOG("Cannot write DBus add watch descriptor data to socket!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int flags = dbus_watch_get_flags(aWatch);
|
||||
if(write(dbt->mControlFdW.get(), &flags, sizeof(unsigned int)) < 0) {
|
||||
if (write(dbt->mControlFdW.get(), &flags, sizeof(unsigned int)) < 0) {
|
||||
LOG("Cannot write DBus add watch flag data to socket!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(write(dbt->mControlFdW.get(), &aWatch, sizeof(DBusWatch*)) < 0) {
|
||||
if (write(dbt->mControlFdW.get(), &aWatch, sizeof(DBusWatch*)) < 0) {
|
||||
LOG("Cannot write DBus add watch struct data to socket!\n");
|
||||
return false;
|
||||
}
|
||||
@ -205,20 +202,20 @@ RemoveWatch(DBusWatch *aWatch, void *aData)
|
||||
DBusThread *dbt = (DBusThread *)aData;
|
||||
|
||||
char control = DBUS_EVENT_LOOP_REMOVE;
|
||||
if(write(dbt->mControlFdW.get(), &control, sizeof(char)) < 0) {
|
||||
if (write(dbt->mControlFdW.get(), &control, sizeof(char)) < 0) {
|
||||
LOG("Cannot write DBus remove watch control data to socket!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO change this to dbus_watch_get_unix_fd once we move to ics
|
||||
int fd = dbus_watch_get_fd(aWatch);
|
||||
if(write(dbt->mControlFdW.get(), &fd, sizeof(int)) < 0) {
|
||||
if (write(dbt->mControlFdW.get(), &fd, sizeof(int)) < 0) {
|
||||
LOG("Cannot write DBus remove watch descriptor data to socket!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int flags = dbus_watch_get_flags(aWatch);
|
||||
if(write(dbt->mControlFdW.get(), &flags, sizeof(unsigned int)) < 0) {
|
||||
if (write(dbt->mControlFdW.get(), &flags, sizeof(unsigned int)) < 0) {
|
||||
LOG("Cannot write DBus remove watch flag data to socket!\n");
|
||||
return;
|
||||
}
|
||||
@ -240,15 +237,15 @@ HandleWatchAdd(DBusThread* aDbt)
|
||||
DBusWatch *watch;
|
||||
int newFD;
|
||||
unsigned int flags;
|
||||
if(read(aDbt->mControlFdR.get(), &newFD, sizeof(int)) < 0) {
|
||||
if (read(aDbt->mControlFdR.get(), &newFD, sizeof(int)) < 0) {
|
||||
LOG("Cannot read DBus watch add descriptor data from socket!\n");
|
||||
return;
|
||||
}
|
||||
if(read(aDbt->mControlFdR.get(), &flags, sizeof(unsigned int)) < 0) {
|
||||
if (read(aDbt->mControlFdR.get(), &flags, sizeof(unsigned int)) < 0) {
|
||||
LOG("Cannot read DBus watch add flag data from socket!\n");
|
||||
return;
|
||||
}
|
||||
if(read(aDbt->mControlFdR.get(), &watch, sizeof(DBusWatch *)) < 0) {
|
||||
if (read(aDbt->mControlFdR.get(), &watch, sizeof(DBusWatch *)) < 0) {
|
||||
LOG("Cannot read DBus watch add watch data from socket!\n");
|
||||
return;
|
||||
}
|
||||
@ -258,20 +255,21 @@ HandleWatchAdd(DBusThread* aDbt)
|
||||
p.fd = newFD;
|
||||
p.revents = 0;
|
||||
p.events = events;
|
||||
if(aDbt->mPollData.Contains(p, PollFdComparator())) return;
|
||||
if (aDbt->mPollData.Contains(p, PollFdComparator())) return;
|
||||
aDbt->mPollData.AppendElement(p);
|
||||
aDbt->mWatchData.AppendElement(watch);
|
||||
}
|
||||
|
||||
static void HandleWatchRemove(DBusThread* aDbt) {
|
||||
static void HandleWatchRemove(DBusThread* aDbt)
|
||||
{
|
||||
int removeFD;
|
||||
unsigned int flags;
|
||||
|
||||
if(read(aDbt->mControlFdR.get(), &removeFD, sizeof(int)) < 0) {
|
||||
if (read(aDbt->mControlFdR.get(), &removeFD, sizeof(int)) < 0) {
|
||||
LOG("Cannot read DBus watch remove descriptor data from socket!\n");
|
||||
return;
|
||||
}
|
||||
if(read(aDbt->mControlFdR.get(), &flags, sizeof(unsigned int)) < 0) {
|
||||
if (read(aDbt->mControlFdR.get(), &flags, sizeof(unsigned int)) < 0) {
|
||||
LOG("Cannot read DBus watch remove flag data from socket!\n");
|
||||
return;
|
||||
}
|
||||
@ -284,7 +282,7 @@ static void HandleWatchRemove(DBusThread* aDbt) {
|
||||
// haven't been added (for example, whenever gecko comes up after
|
||||
// adapters have already been enabled), so check to make sure we're
|
||||
// using the watch in the first place
|
||||
if(index < 0) {
|
||||
if (index < 0) {
|
||||
LOG("DBus requested watch removal of non-existant socket, ignoring...");
|
||||
return;
|
||||
}
|
||||
@ -297,8 +295,7 @@ static void HandleWatchRemove(DBusThread* aDbt) {
|
||||
|
||||
// DBus Thread Implementation
|
||||
|
||||
DBusThread::DBusThread() : mMutex("DBusGonk.mMutex")
|
||||
, mIsRunning(false)
|
||||
DBusThread::DBusThread()
|
||||
{
|
||||
}
|
||||
|
||||
@ -311,7 +308,7 @@ bool
|
||||
DBusThread::SetUpEventLoop()
|
||||
{
|
||||
// If we already have a connection, exit
|
||||
if(mConnection) {
|
||||
if (mConnection) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -321,7 +318,7 @@ DBusThread::SetUpEventLoop()
|
||||
|
||||
// If we can't establish a connection to dbus, nothing else will work
|
||||
nsresult rv = EstablishDBusConnection();
|
||||
if(NS_FAILED(rv)) {
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Cannot create DBus Connection for DBus Thread!");
|
||||
return false;
|
||||
}
|
||||
@ -330,7 +327,7 @@ DBusThread::SetUpEventLoop()
|
||||
// Since we are maintaining a single thread for all the DBus bluez
|
||||
// signals we want, register all of them in this thread at startup.
|
||||
// The event handler will sort the destinations out as needed.
|
||||
for(uint32_t i = 0; i < ArrayLength(DBUS_SIGNALS); ++i) {
|
||||
for (uint32_t i = 0; i < ArrayLength(DBUS_SIGNALS); ++i) {
|
||||
dbus_bus_add_match(mConnection,
|
||||
DBUS_SIGNALS[i],
|
||||
&err);
|
||||
@ -368,7 +365,7 @@ DBusThread::TearDownEventLoop()
|
||||
DBusError err;
|
||||
dbus_error_init(&err);
|
||||
|
||||
for(uint32_t i = 0; i < ArrayLength(DBUS_SIGNALS); ++i) {
|
||||
for (uint32_t i = 0; i < ArrayLength(DBUS_SIGNALS); ++i) {
|
||||
dbus_bus_remove_match(mConnection,
|
||||
DBUS_SIGNALS[i],
|
||||
&err);
|
||||
@ -380,61 +377,51 @@ DBusThread::TearDownEventLoop()
|
||||
return true;
|
||||
}
|
||||
|
||||
void*
|
||||
DBusThread::EventLoop(void *aPtr)
|
||||
void
|
||||
DBusThread::EventLoop()
|
||||
{
|
||||
DBusThread* dbt = static_cast<DBusThread*>(aPtr);
|
||||
MOZ_ASSERT(dbt);
|
||||
dbus_connection_set_watch_functions(mConnection, AddWatch,
|
||||
RemoveWatch, ToggleWatch, this, NULL);
|
||||
|
||||
dbus_connection_set_watch_functions(dbt->mConnection, AddWatch,
|
||||
RemoveWatch, ToggleWatch, aPtr, NULL);
|
||||
|
||||
dbt->mIsRunning = true;
|
||||
LOG("DBus Event Loop Starting\n");
|
||||
while (1) {
|
||||
poll(dbt->mPollData.Elements(), dbt->mPollData.Length(), -1);
|
||||
poll(mPollData.Elements(), mPollData.Length(), -1);
|
||||
|
||||
for (uint32_t i = 0; i < dbt->mPollData.Length(); i++) {
|
||||
if (!dbt->mPollData[i].revents) {
|
||||
for (uint32_t i = 0; i < mPollData.Length(); i++) {
|
||||
if (!mPollData[i].revents) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dbt->mPollData[i].fd == dbt->mControlFdR.get()) {
|
||||
if (mPollData[i].fd == mControlFdR.get()) {
|
||||
char data;
|
||||
while (recv(dbt->mControlFdR.get(), &data, sizeof(char), MSG_DONTWAIT)
|
||||
while (recv(mControlFdR.get(), &data, sizeof(char), MSG_DONTWAIT)
|
||||
!= -1) {
|
||||
switch (data) {
|
||||
case DBUS_EVENT_LOOP_EXIT:
|
||||
{
|
||||
LOG("DBus Event Loop Exiting\n");
|
||||
dbus_connection_set_watch_functions(dbt->mConnection,
|
||||
NULL, NULL, NULL, NULL, NULL);
|
||||
dbt->TearDownEventLoop();
|
||||
return NULL;
|
||||
}
|
||||
case DBUS_EVENT_LOOP_ADD:
|
||||
{
|
||||
HandleWatchAdd(dbt);
|
||||
break;
|
||||
}
|
||||
case DBUS_EVENT_LOOP_REMOVE:
|
||||
{
|
||||
HandleWatchRemove(dbt);
|
||||
break;
|
||||
}
|
||||
case DBUS_EVENT_LOOP_EXIT:
|
||||
LOG("DBus Event Loop Exiting\n");
|
||||
dbus_connection_set_watch_functions(mConnection,
|
||||
NULL, NULL, NULL, NULL, NULL);
|
||||
TearDownEventLoop();
|
||||
return;
|
||||
case DBUS_EVENT_LOOP_ADD:
|
||||
HandleWatchAdd(this);
|
||||
break;
|
||||
case DBUS_EVENT_LOOP_REMOVE:
|
||||
HandleWatchRemove(this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
short events = dbt->mPollData[i].revents;
|
||||
short events = mPollData[i].revents;
|
||||
unsigned int flags = UnixEventsToDBusFlags(events);
|
||||
dbus_watch_handle(dbt->mWatchData[i], flags);
|
||||
dbt->mPollData[i].revents = 0;
|
||||
dbus_watch_handle(mWatchData[i], flags);
|
||||
mPollData[i].revents = 0;
|
||||
// Break at this point since we don't know if the operation
|
||||
// was destructive
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (dbus_connection_dispatch(dbt->mConnection) ==
|
||||
while (dbus_connection_dispatch(mConnection) ==
|
||||
DBUS_DISPATCH_DATA_REMAINS)
|
||||
{}
|
||||
}
|
||||
@ -443,9 +430,6 @@ DBusThread::EventLoop(void *aPtr)
|
||||
bool
|
||||
DBusThread::StartEventLoop()
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
mIsRunning = false;
|
||||
|
||||
// socketpair opens two sockets for the process to communicate on.
|
||||
// This is how android's implementation of the dbus event loop
|
||||
// communicates with itself in relation to IPC signals. These
|
||||
@ -474,106 +458,70 @@ DBusThread::StartEventLoop()
|
||||
TearDownData();
|
||||
return false;
|
||||
}
|
||||
if (NS_FAILED(NS_NewNamedThread("DBus Poll",
|
||||
getter_AddRefs(mThread),
|
||||
NS_NewNonOwningRunnableMethod(this,
|
||||
&DBusThread::EventLoop)))) {
|
||||
NS_WARNING("Cannot create DBus Thread!");
|
||||
return false;
|
||||
}
|
||||
LOG("DBus Thread Starting\n");
|
||||
pthread_create(&(mThread), NULL, DBusThread::EventLoop, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
DBusThread::StopEventLoop()
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
if (mIsRunning) {
|
||||
char data = DBUS_EVENT_LOOP_EXIT;
|
||||
ssize_t wret = write(mControlFdW.get(), &data, sizeof(char));
|
||||
if(wret < 0) {
|
||||
LOG("Cannot write exit bit to DBus Thread!\n");
|
||||
}
|
||||
void *ret;
|
||||
LOG("DBus Thread Joining\n");
|
||||
pthread_join(mThread, &ret);
|
||||
LOG("DBus Thread Joined\n");
|
||||
TearDownData();
|
||||
if (!mThread) {
|
||||
return true;
|
||||
}
|
||||
mIsRunning = false;
|
||||
}
|
||||
|
||||
bool
|
||||
DBusThread::IsEventLoopRunning()
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
return mIsRunning;
|
||||
char data = DBUS_EVENT_LOOP_EXIT;
|
||||
ssize_t wret = write(mControlFdW.get(), &data, sizeof(char));
|
||||
if(wret < 0) {
|
||||
NS_ERROR("Cannot write exit flag to Dbus Thread!");
|
||||
return false;
|
||||
}
|
||||
LOG("DBus Thread Joining\n");
|
||||
nsCOMPtr<nsIThread> tmpThread;
|
||||
mThread.swap(tmpThread);
|
||||
if(NS_FAILED(tmpThread->Shutdown())) {
|
||||
NS_WARNING("DBus thread shutdown failed!");
|
||||
}
|
||||
LOG("DBus Thread Joined\n");
|
||||
TearDownData();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Startup/Shutdown utility functions
|
||||
|
||||
static void
|
||||
ConnectDBus(Monitor* aMonitor, bool* aSuccess)
|
||||
{
|
||||
if(sDBusThread) {
|
||||
NS_WARNING("Trying to start DBus Thread that is already currently running, skipping.");
|
||||
return;
|
||||
}
|
||||
|
||||
sDBusThread = new DBusThread();
|
||||
*aSuccess = true;
|
||||
if(!sDBusThread->StartEventLoop())
|
||||
{
|
||||
*aSuccess = false;
|
||||
}
|
||||
{
|
||||
MonitorAutoLock lock(*aMonitor);
|
||||
lock.Notify();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DisconnectDBus(Monitor* aMonitor, bool* aSuccess)
|
||||
{
|
||||
if(!sDBusThread) {
|
||||
NS_WARNING("Trying to shutdown DBus Thread that is not currently running, skipping.");
|
||||
return;
|
||||
}
|
||||
|
||||
*aSuccess = true;
|
||||
sDBusThread->StopEventLoop();
|
||||
sDBusThread = NULL;
|
||||
{
|
||||
MonitorAutoLock lock(*aMonitor);
|
||||
lock.Notify();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
StartDBus()
|
||||
{
|
||||
Monitor monitor("StartDBus.monitor");
|
||||
bool success;
|
||||
{
|
||||
MonitorAutoLock lock(monitor);
|
||||
|
||||
XRE_GetIOMessageLoop()->PostTask(
|
||||
FROM_HERE,
|
||||
NewRunnableFunction(ConnectDBus, &monitor, &success));
|
||||
lock.Wait();
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
if (sDBusThread) {
|
||||
NS_WARNING("Trying to start DBus Thread that is already currently running, skipping.");
|
||||
return true;
|
||||
}
|
||||
return success;
|
||||
nsAutoPtr<DBusThread> thread(new DBusThread());
|
||||
if (!thread->StartEventLoop()) {
|
||||
NS_WARNING("Cannot start DBus event loop!");
|
||||
return false;
|
||||
}
|
||||
sDBusThread = thread;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
StopDBus()
|
||||
{
|
||||
Monitor monitor("StopDBus.monitor");
|
||||
bool success;
|
||||
{
|
||||
MonitorAutoLock lock(monitor);
|
||||
|
||||
XRE_GetIOMessageLoop()->PostTask(
|
||||
FROM_HERE,
|
||||
NewRunnableFunction(DisconnectDBus, &monitor, &success));
|
||||
lock.Wait();
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
if (!sDBusThread) {
|
||||
return true;
|
||||
}
|
||||
return success;
|
||||
|
||||
nsAutoPtr<DBusThread> thread(sDBusThread);
|
||||
sDBusThread = nsnull;
|
||||
return thread->StopEventLoop();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ namespace ipc {
|
||||
void
|
||||
log_and_free_dbus_error(DBusError* err, const char* function, DBusMessage* msg)
|
||||
{
|
||||
if(msg) {
|
||||
if (msg) {
|
||||
LOG("%s: D-Bus error in %s: %s (%s)", function,
|
||||
dbus_message_get_member((msg)), (err)->name, (err)->message);
|
||||
} else {
|
||||
@ -49,9 +49,8 @@ log_and_free_dbus_error(DBusError* err, const char* function, DBusMessage* msg)
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
void (*user_cb)(DBusMessage *, void *, void *);
|
||||
DBusCallback user_cb;
|
||||
void *user;
|
||||
void *nat;
|
||||
} dbus_async_call_t;
|
||||
|
||||
void dbus_func_args_async_callback(DBusPendingCall *call, void *data) {
|
||||
@ -66,7 +65,7 @@ void dbus_func_args_async_callback(DBusPendingCall *call, void *data) {
|
||||
if (msg) {
|
||||
if (req->user_cb) {
|
||||
// The user may not deref the message object.
|
||||
req->user_cb(msg, req->user, req->nat);
|
||||
req->user_cb(msg, req->user);
|
||||
}
|
||||
dbus_message_unref(msg);
|
||||
}
|
||||
@ -77,23 +76,47 @@ void dbus_func_args_async_callback(DBusPendingCall *call, void *data) {
|
||||
free(req);
|
||||
}
|
||||
|
||||
dbus_bool_t dbus_func_send_async(DBusConnection *conn,
|
||||
DBusMessage *msg,
|
||||
int timeout_ms,
|
||||
void (*user_cb)(DBusMessage*,
|
||||
void*),
|
||||
void *user) {
|
||||
dbus_async_call_t *pending;
|
||||
dbus_bool_t reply = FALSE;
|
||||
|
||||
// Freed at end of dbus_func_args_async_callback (becomes "req")
|
||||
pending = (dbus_async_call_t *)malloc(sizeof(dbus_async_call_t));
|
||||
DBusPendingCall *call;
|
||||
|
||||
pending->user_cb = user_cb;
|
||||
pending->user = user;
|
||||
|
||||
reply = dbus_connection_send_with_reply(conn, msg,
|
||||
&call,
|
||||
timeout_ms);
|
||||
if (reply) {
|
||||
dbus_pending_call_set_notify(call,
|
||||
dbus_func_args_async_callback,
|
||||
pending,
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (msg) dbus_message_unref(msg);
|
||||
return reply;
|
||||
}
|
||||
|
||||
static dbus_bool_t dbus_func_args_async_valist(DBusConnection *conn,
|
||||
int timeout_ms,
|
||||
void (*user_cb)(DBusMessage *,
|
||||
void *,
|
||||
void (*user_cb)(DBusMessage*,
|
||||
void*),
|
||||
void *user,
|
||||
void *nat,
|
||||
const char *path,
|
||||
const char *ifc,
|
||||
const char *func,
|
||||
int first_arg_type,
|
||||
va_list args) {
|
||||
DBusMessage *msg = NULL;
|
||||
const char *name;
|
||||
dbus_async_call_t *pending;
|
||||
dbus_bool_t reply = FALSE;
|
||||
|
||||
DBusMessage *msg = NULL;
|
||||
/* Compose the command */
|
||||
msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC, path, ifc, func);
|
||||
|
||||
@ -108,37 +131,16 @@ static dbus_bool_t dbus_func_args_async_valist(DBusConnection *conn,
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Make the call. */
|
||||
pending = (dbus_async_call_t *)malloc(sizeof(dbus_async_call_t));
|
||||
if (pending) {
|
||||
DBusPendingCall *call;
|
||||
|
||||
pending->user_cb = user_cb;
|
||||
pending->user = user;
|
||||
pending->nat = nat;
|
||||
//pending->method = msg;
|
||||
|
||||
reply = dbus_connection_send_with_reply(conn, msg,
|
||||
&call,
|
||||
timeout_ms);
|
||||
if (reply == TRUE) {
|
||||
dbus_pending_call_set_notify(call,
|
||||
dbus_func_args_async_callback,
|
||||
pending,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return dbus_func_send_async(conn, msg, timeout_ms, user_cb, user);
|
||||
done:
|
||||
if (msg) dbus_message_unref(msg);
|
||||
return reply;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
dbus_bool_t dbus_func_args_async(DBusConnection *conn,
|
||||
int timeout_ms,
|
||||
void (*reply)(DBusMessage *, void *, void*),
|
||||
void (*reply)(DBusMessage *, void *),
|
||||
void *user,
|
||||
void *nat,
|
||||
const char *path,
|
||||
const char *ifc,
|
||||
const char *func,
|
||||
@ -150,7 +152,7 @@ dbus_bool_t dbus_func_args_async(DBusConnection *conn,
|
||||
|
||||
ret = dbus_func_args_async_valist(conn,
|
||||
timeout_ms,
|
||||
reply, user, nat,
|
||||
reply, user,
|
||||
path, ifc, func,
|
||||
first_arg_type, lst);
|
||||
va_end(lst);
|
||||
@ -173,7 +175,6 @@ DBusMessage * dbus_func_args_timeout_valist(DBusConnection *conn,
|
||||
va_list args) {
|
||||
|
||||
DBusMessage *msg = NULL, *reply = NULL;
|
||||
const char *name;
|
||||
bool return_error = (err != NULL);
|
||||
|
||||
if (!return_error) {
|
||||
|
@ -50,49 +50,58 @@ private:
|
||||
DBusMessage* mMsg;
|
||||
};
|
||||
|
||||
typedef void (*DBusCallback)(DBusMessage *, void *);
|
||||
|
||||
|
||||
void log_and_free_dbus_error(DBusError* err,
|
||||
const char* function,
|
||||
DBusMessage* msg = NULL);
|
||||
dbus_bool_t dbus_func_args_async(DBusConnection *conn,
|
||||
|
||||
dbus_bool_t dbus_func_send_async(DBusConnection* conn,
|
||||
DBusMessage* msg,
|
||||
int timeout_ms,
|
||||
void (*reply)(DBusMessage *, void *, void *),
|
||||
void *user,
|
||||
void *nat,
|
||||
const char *path,
|
||||
const char *ifc,
|
||||
const char *func,
|
||||
DBusCallback user_cb,
|
||||
void* user);
|
||||
|
||||
dbus_bool_t dbus_func_args_async(DBusConnection* conn,
|
||||
int timeout_ms,
|
||||
DBusCallback reply,
|
||||
void* user,
|
||||
const char* path,
|
||||
const char* ifc,
|
||||
const char* func,
|
||||
int first_arg_type,
|
||||
...);
|
||||
|
||||
DBusMessage * dbus_func_args(DBusConnection *conn,
|
||||
const char *path,
|
||||
const char *ifc,
|
||||
const char *func,
|
||||
DBusMessage* dbus_func_args(DBusConnection* conn,
|
||||
const char* path,
|
||||
const char* ifc,
|
||||
const char* func,
|
||||
int first_arg_type,
|
||||
...);
|
||||
|
||||
DBusMessage * dbus_func_args_error(DBusConnection *conn,
|
||||
DBusError *err,
|
||||
const char *path,
|
||||
const char *ifc,
|
||||
const char *func,
|
||||
DBusMessage* dbus_func_args_error(DBusConnection* conn,
|
||||
DBusError* err,
|
||||
const char* path,
|
||||
const char* ifc,
|
||||
const char* func,
|
||||
int first_arg_type,
|
||||
...);
|
||||
|
||||
DBusMessage * dbus_func_args_timeout(DBusConnection *conn,
|
||||
DBusMessage* dbus_func_args_timeout(DBusConnection* conn,
|
||||
int timeout_ms,
|
||||
const char *path,
|
||||
const char *ifc,
|
||||
const char *func,
|
||||
const char* path,
|
||||
const char* ifc,
|
||||
const char* func,
|
||||
int first_arg_type,
|
||||
...);
|
||||
|
||||
DBusMessage * dbus_func_args_timeout_valist(DBusConnection *conn,
|
||||
DBusMessage* dbus_func_args_timeout_valist(DBusConnection* conn,
|
||||
int timeout_ms,
|
||||
DBusError *err,
|
||||
const char *path,
|
||||
const char *ifc,
|
||||
const char *func,
|
||||
DBusError* err,
|
||||
const char* path,
|
||||
const char* ifc,
|
||||
const char* func,
|
||||
int first_arg_type,
|
||||
va_list args);
|
||||
|
||||
|
@ -29,5 +29,5 @@ nsresult RawDBusConnection::EstablishDBusConnection() {
|
||||
|
||||
void RawDBusConnection::ScopedDBusConnectionPtrTraits::release(DBusConnection* ptr)
|
||||
{
|
||||
if(ptr) dbus_connection_unref(ptr);
|
||||
if (ptr) dbus_connection_unref(ptr);
|
||||
}
|
||||
|
@ -25,8 +25,9 @@ IPDLDIRS = \
|
||||
uriloader/exthandler \
|
||||
dom/devicestorage \
|
||||
dom/indexedDB/ipc \
|
||||
dom/bluetooth/ipc \
|
||||
dom/plugins/ipc \
|
||||
dom/ipc \
|
||||
dom/ipc \
|
||||
dom/sms/src/ipc \
|
||||
dom/src/storage \
|
||||
gfx/layers/ipc \
|
||||
|
Loading…
Reference in New Issue
Block a user