Bug 761511: Patch 2 - Added BluetoothPropertyContainer base class and utility functions; r=mrbkap

This commit is contained in:
Kyle Machulis 2012-07-31 21:49:59 -07:00
Родитель 564a0e174b
Коммит cdf8a37fda
12 изменённых файлов: 548 добавлений и 112 удалений

Просмотреть файл

@ -25,6 +25,15 @@ BEGIN_BLUETOOTH_NAMESPACE
class BluetoothSignal;
typedef mozilla::Observer<BluetoothSignal> BluetoothSignalObserver;
// Enums for object types, currently used for shared function lookups
// (get/setproperty, etc...). Possibly discernable via dbus paths, but this
// method is future-proofed for platform independence.
enum BluetoothObjectType {
TYPE_MANAGER = 0,
TYPE_ADAPTER = 1,
TYPE_DEVICE = 2
};
END_BLUETOOTH_NAMESPACE
#endif // mozilla_dom_bluetooth_bluetoothcommon_h__

Просмотреть файл

@ -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 "BluetoothPropertyContainer.h"
#include "BluetoothService.h"
#include "BluetoothTypes.h"
#include "nsIDOMDOMRequest.h"
USING_BLUETOOTH_NAMESPACE
nsresult
BluetoothPropertyContainer::GetProperties()
{
BluetoothService* bs = BluetoothService::Get();
if (!bs) {
NS_WARNING("Bluetooth service not available!");
return NS_ERROR_FAILURE;
}
nsRefPtr<BluetoothReplyRunnable> task = new GetPropertiesTask(this, NULL);
return bs->GetProperties(mObjectType, mPath, task);
}
nsresult
BluetoothPropertyContainer::SetProperty(nsIDOMWindow* aOwner,
const BluetoothNamedValue& aProperty,
nsIDOMDOMRequest** aRequest)
{
BluetoothService* bs = BluetoothService::Get();
if (!bs) {
NS_WARNING("Bluetooth service not available!");
return NS_ERROR_FAILURE;
}
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(aOwner, getter_AddRefs(req));
if (NS_FAILED(rv)) {
NS_WARNING("Can't create DOMRequest!");
return NS_ERROR_FAILURE;
}
nsRefPtr<BluetoothReplyRunnable> task = new BluetoothVoidReplyRunnable(req);
rv = bs->SetProperty(mObjectType, mPath, aProperty, task);
NS_ENSURE_SUCCESS(rv, rv);
req.forget(aRequest);
return NS_OK;
}
bool
BluetoothPropertyContainer::GetPropertiesTask::ParseSuccessfulReply(jsval* aValue)
{
*aValue = JSVAL_VOID;
BluetoothValue& v = mReply->get_BluetoothReplySuccess().value();
if (v.type() != BluetoothValue::TArrayOfBluetoothNamedValue) {
NS_WARNING("Not a BluetoothNamedValue array!");
return false;
}
const InfallibleTArray<BluetoothNamedValue>& values =
mReply->get_BluetoothReplySuccess().value().get_ArrayOfBluetoothNamedValue();
for (uint32_t i = 0; i < values.Length(); ++i) {
mPropObjPtr->SetPropertyByValue(values[i]);
}
return true;
}

Просмотреть файл

@ -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/. */
#ifndef mozilla_dom_bluetooth_bluetoothpropertyobject_h__
#define mozilla_dom_bluetooth_bluetoothpropertyobject_h__
#include "BluetoothCommon.h"
#include "BluetoothReplyRunnable.h"
#include "mozilla/RefPtr.h"
class nsIDOMDOMRequest;
class nsIDOMWindow;
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothNamedValue;
class BluetoothPropertyContainer
{
public:
nsresult GetProperties();
nsresult SetProperty(nsIDOMWindow* aOwner,
const BluetoothNamedValue& aProperty,
nsIDOMDOMRequest** aRequest);
virtual void SetPropertyByValue(const BluetoothNamedValue& aValue) = 0;
nsString GetPath()
{
return mPath;
}
// Compatibility with nsRefPtr to make sure we don't hold a weakptr to
// ourselves
virtual nsrefcnt AddRef() = 0;
virtual nsrefcnt Release() = 0;
protected:
BluetoothPropertyContainer(BluetoothObjectType aType) :
mObjectType(aType)
{}
~BluetoothPropertyContainer()
{}
class GetPropertiesTask : public BluetoothReplyRunnable
{
public:
GetPropertiesTask(BluetoothPropertyContainer* aPropObj, nsIDOMDOMRequest* aReq) :
BluetoothReplyRunnable(aReq),
mPropObjPtr(aPropObj)
{
MOZ_ASSERT(aReq && aPropObj);
}
virtual bool ParseSuccessfulReply(jsval* aValue);
void
ReleaseMembers()
{
BluetoothReplyRunnable::ReleaseMembers();
mPropObjPtr = nullptr;
}
private:
BluetoothPropertyContainer* mPropObjPtr;
};
nsString mPath;
BluetoothObjectType mObjectType;
};
END_BLUETOOTH_NAMESPACE
#endif

Просмотреть файл

@ -7,8 +7,6 @@
#include "base/basictypes.h"
#include "BluetoothTypes.h"
#include "BluetoothReplyRunnable.h"
#include "nsIDOMDOMRequest.h"
#include "jsapi.h"
USING_BLUETOOTH_NAMESPACE

Просмотреть файл

@ -9,10 +9,9 @@
#include "BluetoothCommon.h"
#include "nsThreadUtils.h"
#include "nsIDOMDOMRequest.h"
#include "jsapi.h"
class nsIDOMDOMRequest;
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothReply;

Просмотреть файл

@ -143,6 +143,50 @@ public:
*/
virtual nsresult StopInternal() = 0;
/**
* Fetches the propertes for the specified object
*
* @param aType Type of the object (see BluetoothObjectType in BluetoothCommon.h)
* @param aPath Path of the object
* @param aRunnable Runnable to return to after receiving callback
*
* @return NS_OK on function run, NS_ERROR_FAILURE otherwise
*/
virtual nsresult
GetProperties(BluetoothObjectType aType,
const nsAString& aPath,
BluetoothReplyRunnable* aRunnable) = 0;
/**
* Set a property for the specified object
*
* @param aPath Path to the object
* @param aPropName Name of the property
* @param aValue Boolean value
* @param aRunnable Runnable to run on async reply
*
* @return NS_OK if property is set correctly, NS_ERROR_FAILURE otherwise
*/
virtual nsresult
SetProperty(BluetoothObjectType aType,
const nsAString& aPath,
const BluetoothNamedValue& aValue,
BluetoothReplyRunnable* aRunnable) = 0;
/**
* Get the path of a device
*
* @param aAdapterPath Path to the Adapter that's communicating with the device
* @param aDeviceAddress Device address (XX:XX:XX:XX:XX:XX format)
* @param aDevicePath Return value of path
*
* @return True if path set correctly, false otherwise
*/
virtual bool
GetDevicePath(const nsAString& aAdapterPath,
const nsAString& aDeviceAddress,
nsAString& aDevicePath) = 0;
protected:
BluetoothService()
{

Просмотреть файл

@ -35,6 +35,7 @@ CPPSRCS += \
BluetoothDeviceEvent.cpp \
BluetoothPropertyEvent.cpp \
BluetoothReplyRunnable.cpp \
BluetoothPropertyContainer.cpp \
$(NULL)
XPIDLSRCS = \

Просмотреть файл

@ -57,6 +57,7 @@ USING_BLUETOOTH_NAMESPACE
#define LOG(args...) if (BTDEBUG) printf(args);
#endif
#define DBUS_MANAGER_IFACE BLUEZ_DBUS_BASE_IFC ".Manager"
#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"
@ -68,7 +69,7 @@ typedef struct {
int type;
} Properties;
static Properties remote_device_properties[] = {
static Properties sDeviceProperties[] = {
{"Address", DBUS_TYPE_STRING},
{"Name", DBUS_TYPE_STRING},
{"Icon", DBUS_TYPE_STRING},
@ -88,7 +89,7 @@ static Properties remote_device_properties[] = {
{"Broadcaster", DBUS_TYPE_BOOLEAN}
};
static Properties adapter_properties[] = {
static Properties sAdapterProperties[] = {
{"Address", DBUS_TYPE_STRING},
{"Name", DBUS_TYPE_STRING},
{"Class", DBUS_TYPE_UINT32},
@ -102,7 +103,18 @@ static Properties adapter_properties[] = {
{"UUIDs", DBUS_TYPE_ARRAY},
};
static const char* BLUETOOTH_DBUS_SIGNALS[] =
static Properties sManagerProperties[] = {
{"Adapters", DBUS_TYPE_ARRAY},
};
static const char* sBluetoothDBusIfaces[] =
{
DBUS_MANAGER_IFACE,
DBUS_ADAPTER_IFACE,
DBUS_DEVICE_IFACE
};
static const char* sBluetoothDBusSignals[] =
{
"type='signal',interface='org.freedesktop.DBus'",
"type='signal',interface='org.bluez.Adapter'",
@ -133,7 +145,6 @@ public:
}
};
bool
IsDBusMessageError(DBusMessage* aMsg, nsAString& aError)
{
@ -176,24 +187,14 @@ DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable,
NS_WARNING("Failed to dispatch to main thread!");
}
}
void
GetObjectPathCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
UnpackObjectPathMessage(DBusMessage* aMsg, BluetoothValue& aValue,
nsAString& aErrorStr)
{
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)) {
if (!IsDBusMessageError(aMsg, aErrorStr)) {
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;
@ -201,22 +202,22 @@ GetObjectPathCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
&object_path, DBUS_TYPE_INVALID) ||
!object_path) {
if (dbus_error_is_set(&err)) {
replyError = NS_ConvertUTF8toUTF16(err.message);
aErrorStr = NS_ConvertUTF8toUTF16(err.message);
LOG_AND_FREE_DBUS_ERROR(&err);
}
} else {
v = NS_ConvertUTF8toUTF16(object_path);
aValue = NS_ConvertUTF8toUTF16(object_path);
}
}
DispatchBluetoothReply(replyRunnable, v, replyError);
}
typedef void (*UnpackFunc)(DBusMessage*, BluetoothValue&, nsAString&);
void
GetVoidCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
RunDBusCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable,
UnpackFunc aFunc)
{
MOZ_ASSERT(!NS_IsMainThread());
DBusError err;
dbus_error_init(&err);
nsRefPtr<BluetoothReplyRunnable> replyRunnable =
dont_AddRef(static_cast< BluetoothReplyRunnable* >(aBluetoothReplyRunnable));
@ -224,20 +225,41 @@ GetVoidCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
nsString replyError;
BluetoothValue v;
if (!IsDBusMessageError(aMsg, replyError) &&
aFunc(aMsg, v, replyError);
DispatchBluetoothReply(replyRunnable, v, replyError);
}
void
GetObjectPathCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
{
RunDBusCallback(aMsg, aBluetoothReplyRunnable, UnpackObjectPathMessage);
}
void
UnpackVoidMessage(DBusMessage* aMsg, BluetoothValue& aValue,
nsAString& aErrorStr)
{
DBusError err;
dbus_error_init(&err);
if (!IsDBusMessageError(aMsg, aErrorStr) &&
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);
aErrorStr = NS_ConvertUTF8toUTF16(err.message);
LOG_AND_FREE_DBUS_ERROR(&err);
}
}
DispatchBluetoothReply(replyRunnable, v, replyError);
}
void
GetVoidCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
{
RunDBusCallback(aMsg, aBluetoothReplyRunnable, UnpackVoidMessage);
}
bool
GetProperty(DBusMessageIter aIter, Properties* aPropertyTypes,
int aPropertiesTypeLen, int* aPropIndex,
int aPropertyTypeLen, int* aPropIndex,
InfallibleTArray<BluetoothNamedValue>& aProperties)
{
DBusMessageIter prop_val, array_val_iter;
@ -256,13 +278,13 @@ GetProperty(DBusMessageIter aIter, Properties* aPropertyTypes,
return false;
}
for (i = 0; i < aPropertiesTypeLen; i++) {
for (i = 0; i < aPropertyTypeLen; i++) {
if (!strncmp(property, aPropertyTypes[i].name, strlen(property))) {
break;
}
}
if (i == aPropertiesTypeLen) {
if (i == aPropertyTypeLen) {
return false;
}
@ -310,6 +332,9 @@ GetProperty(DBusMessageIter aIter, Properties* aPropertyTypes,
} while (dbus_message_iter_next(&array_val_iter));
propertyValue = arr;
} else {
// This happens when the array is 0-length. Apparently we get a
// DBUS_TYPE_INVALID type.
propertyValue = InfallibleTArray<nsString>();
NS_WARNING("Received array type that's not a string array!");
}
break;
@ -321,10 +346,11 @@ GetProperty(DBusMessageIter aIter, Properties* aPropertyTypes,
}
void
ParseProperties(DBusMessageIter* aIter,
ParseProperties(DBusMessageIter* aIter,
BluetoothValue& aValue,
nsAString& aErrorStr,
Properties* aPropertyTypes,
const int aPropertiesTypeLen,
InfallibleTArray<BluetoothNamedValue>& aProperties)
const int aPropertyTypeLen)
{
DBusMessageIter dict_entry, dict;
int prop_index = -1;
@ -333,28 +359,100 @@ ParseProperties(DBusMessageIter* aIter,
"Trying to parse a property from something that's not an array!");
dbus_message_iter_recurse(aIter, &dict);
InfallibleTArray<BluetoothNamedValue> props;
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)) {
if (!GetProperty(dict_entry, aPropertyTypes, aPropertyTypeLen, &prop_index,
props)) {
aErrorStr.AssignLiteral("Can't Create Property!");
NS_WARNING("Can't create property!");
return;
}
} while (dbus_message_iter_next(&dict));
aValue = props;
}
void UnpackPropertiesMessage(DBusMessage* aMsg, BluetoothValue& aValue,
nsAString& aErrorStr, Properties* aPropertyTypes,
const int aPropertyTypeLen)
{
if (!IsDBusMessageError(aMsg, aErrorStr) &&
dbus_message_get_type(aMsg) == DBUS_MESSAGE_TYPE_METHOD_RETURN) {
DBusMessageIter iter;
if (!dbus_message_iter_init(aMsg, &iter)) {
aErrorStr.AssignLiteral("Cannot create dbus message iter!");
} else {
ParseProperties(&iter, aValue, aErrorStr, aPropertyTypes,
aPropertyTypeLen);
}
}
}
void UnpackAdapterPropertiesMessage(DBusMessage* aMsg, BluetoothValue& aValue,
nsAString& aErrorStr)
{
UnpackPropertiesMessage(aMsg, aValue, aErrorStr,
sAdapterProperties,
ArrayLength(sAdapterProperties));
}
void UnpackDevicePropertiesMessage(DBusMessage* aMsg, BluetoothValue& aValue,
nsAString& aErrorStr)
{
UnpackPropertiesMessage(aMsg, aValue, aErrorStr,
sDeviceProperties,
ArrayLength(sDeviceProperties));
}
void UnpackManagerPropertiesMessage(DBusMessage* aMsg, BluetoothValue& aValue,
nsAString& aErrorStr)
{
UnpackPropertiesMessage(aMsg, aValue, aErrorStr,
sManagerProperties,
ArrayLength(sManagerProperties));
}
void
ParsePropertyChange(DBusMessage* aMsg, Properties* aPropertyTypes,
const int aPropertiesTypeLen,
InfallibleTArray<BluetoothNamedValue>& aProperties)
GetManagerPropertiesCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
{
RunDBusCallback(aMsg, aBluetoothReplyRunnable, UnpackManagerPropertiesMessage);
}
void
GetAdapterPropertiesCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
{
RunDBusCallback(aMsg, aBluetoothReplyRunnable, UnpackAdapterPropertiesMessage);
}
void
GetDevicePropertiesCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
{
RunDBusCallback(aMsg, aBluetoothReplyRunnable, UnpackDevicePropertiesMessage);
}
static DBusCallback sBluetoothDBusPropCallbacks[] =
{
GetManagerPropertiesCallback,
GetAdapterPropertiesCallback,
GetDevicePropertiesCallback
};
MOZ_STATIC_ASSERT(sizeof(sBluetoothDBusPropCallbacks) == sizeof(sBluetoothDBusIfaces),
"DBus Property callback array and DBus interface array must be same size");
void
ParsePropertyChange(DBusMessage* aMsg, BluetoothValue& aValue,
nsAString& aErrorStr, Properties* aPropertyTypes,
const int aPropertyTypeLen)
{
DBusMessageIter iter;
DBusError err;
int prop_index = -1;
InfallibleTArray<BluetoothNamedValue> props;
dbus_error_init(&err);
if (!dbus_message_iter_init(aMsg, &iter)) {
@ -362,10 +460,13 @@ ParsePropertyChange(DBusMessage* aMsg, Properties* aPropertyTypes,
return;
}
if (!GetProperty(iter, aPropertyTypes, aPropertiesTypeLen,
&prop_index, aProperties)) {
if (!GetProperty(iter, aPropertyTypes, aPropertyTypeLen,
&prop_index, props)) {
NS_WARNING("Can't get property!");
aErrorStr.AssignLiteral("Can't get property!");
return;
}
aValue = props;
}
// Called by dbus during WaitForAndDispatchEventNative()
@ -392,11 +493,8 @@ EventFilter(DBusConnection* aConn, DBusMessage* aMsg, void* aData)
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));
nsString errorStr;
BluetoothValue v;
if (dbus_message_is_signal(aMsg, DBUS_ADAPTER_IFACE, "DeviceFound")) {
@ -408,21 +506,28 @@ EventFilter(DBusConnection* aConn, DBusMessage* aMsg, void* aData)
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
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;
v,
errorStr,
sDeviceProperties,
ArrayLength(sDeviceProperties));
if (v.type() == BluetoothValue::TArrayOfBluetoothNamedValue)
{
// The DBus DeviceFound message actually passes back a key value object
// with the address as the key and the rest of the device properties as
// a dict value. After we parse out the properties, we need to go back
// and add the address to the ipdl dict we've created to make sure we
// have all of the information to correctly build the device.
v.get_ArrayOfBluetoothNamedValue()
.AppendElement(BluetoothNamedValue(NS_LITERAL_STRING("Address"),
NS_ConvertUTF8toUTF16(addr)));
}
} else {
NS_WARNING("DBus iterator not as long as expected!");
errorStr.AssignLiteral("DBus device found message structure not as expected!");
}
} else if (dbus_message_is_signal(aMsg, DBUS_ADAPTER_IFACE, "DeviceDisappeared")) {
const char* str;
@ -430,6 +535,7 @@ EventFilter(DBusConnection* aConn, DBusMessage* aMsg, void* aData)
DBUS_TYPE_STRING, &str,
DBUS_TYPE_INVALID)) {
LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, aMsg);
errorStr.AssignLiteral("Cannot parse device address!");
}
v = NS_ConvertUTF8toUTF16(str);
} else if (dbus_message_is_signal(aMsg, DBUS_ADAPTER_IFACE, "DeviceCreated")) {
@ -438,16 +544,39 @@ EventFilter(DBusConnection* aConn, DBusMessage* aMsg, void* aData)
DBUS_TYPE_OBJECT_PATH, &str,
DBUS_TYPE_INVALID)) {
LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, aMsg);
errorStr.AssignLiteral("Cannot parse device path!");
}
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;
v,
errorStr,
sAdapterProperties,
ArrayLength(sAdapterProperties));
} else if (dbus_message_is_signal(aMsg, DBUS_DEVICE_IFACE, "PropertyChanged")) {
ParsePropertyChange(aMsg,
v,
errorStr,
sDeviceProperties,
ArrayLength(sDeviceProperties));
} else if (dbus_message_is_signal(aMsg, DBUS_MANAGER_IFACE, "PropertyChanged")) {
ParsePropertyChange(aMsg,
v,
errorStr,
sManagerProperties,
ArrayLength(sManagerProperties));
} else {
#ifdef DEBUG
nsCAutoString signalStr;
signalStr += dbus_message_get_member(aMsg);
signalStr += " Signal not handled!";
NS_WARNING(signalStr.get());
#endif
}
if (!errorStr.IsEmpty()) {
NS_WARNING(NS_ConvertUTF16toUTF8(errorStr).get());
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
BluetoothSignal signal(signalName, signalPath, v);
@ -577,3 +706,131 @@ BluetoothDBusService::StartDiscoveryInternal(const nsAString& aAdapterPath,
{
return SendDiscoveryMessage(aAdapterPath, "StartDiscovery", aRunnable);
}
nsresult
BluetoothDBusService::GetProperties(BluetoothObjectType aType,
const nsAString& aPath,
BluetoothReplyRunnable* aRunnable)
{
NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!");
MOZ_ASSERT(aType < ArrayLength(sBluetoothDBusIfaces));
MOZ_ASSERT(aType < ArrayLength(sBluetoothDBusPropCallbacks));
const char* interface = sBluetoothDBusIfaces[aType];
DBusCallback callback = sBluetoothDBusPropCallbacks[aType];
nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
if (!dbus_func_args_async(mConnection,
1000,
callback,
(void*)aRunnable,
NS_ConvertUTF16toUTF8(aPath).get(),
interface,
"GetProperties",
DBUS_TYPE_INVALID)) {
NS_WARNING("Could not start async function!");
return NS_ERROR_FAILURE;
}
runnable.forget();
return NS_OK;
}
nsresult
BluetoothDBusService::SetProperty(BluetoothObjectType aType,
const nsAString& aPath,
const BluetoothNamedValue& aValue,
BluetoothReplyRunnable* aRunnable)
{
NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!");
MOZ_ASSERT(aType < ArrayLength(sBluetoothDBusIfaces));
const char* interface = sBluetoothDBusIfaces[aType];
/* Compose the command */
DBusMessage* msg = dbus_message_new_method_call("org.bluez",
NS_ConvertUTF16toUTF8(aPath).get(),
interface,
"SetProperty");
if (!msg) {
NS_WARNING("Could not allocate D-Bus message object!");
return NS_ERROR_FAILURE;
}
const char* propName = NS_ConvertUTF16toUTF8(aValue.name()).get();
if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &propName, DBUS_TYPE_INVALID)) {
NS_WARNING("Couldn't append arguments to dbus message!");
return NS_ERROR_FAILURE;
}
int type;
int tmp_int;
void* val;
nsCString str;
if (aValue.value().type() == BluetoothValue::Tuint32_t) {
tmp_int = aValue.value().get_uint32_t();
val = &tmp_int;
type = DBUS_TYPE_UINT32;
} else if (aValue.value().type() == BluetoothValue::TnsString) {
str = NS_ConvertUTF16toUTF8(aValue.value().get_nsString());
val = (void*)str.get();
type = DBUS_TYPE_STRING;
} else if (aValue.value().type() == BluetoothValue::Tbool) {
tmp_int = aValue.value().get_bool() ? 1 : 0;
val = &(tmp_int);
type = DBUS_TYPE_BOOLEAN;
} else {
NS_WARNING("Property type not handled!");
dbus_message_unref(msg);
return NS_ERROR_FAILURE;
}
DBusMessageIter value_iter, iter;
dbus_message_iter_init_append(msg, &iter);
char var_type[2] = {(char)type, '\0'};
if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, var_type, &value_iter) ||
!dbus_message_iter_append_basic(&value_iter, type, val) ||
!dbus_message_iter_close_container(&iter, &value_iter)) {
NS_WARNING("Could not append argument to method call!");
dbus_message_unref(msg);
return NS_ERROR_FAILURE;
}
nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
// msg is unref'd as part of dbus_func_send_async
if (!dbus_func_send_async(mConnection,
msg,
1000,
GetVoidCallback,
(void*)aRunnable)) {
NS_WARNING("Could not start async function!");
return NS_ERROR_FAILURE;
}
runnable.forget();
return NS_OK;
}
nsString
GetObjectPathFromAddress(const nsAString& aAdapterPath,
const nsAString& aDeviceAddress)
{
// The object path would be like /org/bluez/2906/hci0/dev_00_23_7F_CB_B4_F1,
// and the adapter path would be the first part of the object path, accoring
// to the example above, it's /org/bluez/2906/hci0.
nsString devicePath(aAdapterPath);
devicePath.AppendLiteral("/dev_");
devicePath.Append(aDeviceAddress);
devicePath.ReplaceChar(':', '_');
return devicePath;
}
bool
BluetoothDBusService::GetDevicePath(const nsAString& aAdapterPath,
const nsAString& aDeviceAddress,
nsAString& aDevicePath)
{
aDevicePath = GetObjectPathFromAddress(aAdapterPath, aDeviceAddress);
return true;
}

Просмотреть файл

@ -16,67 +16,46 @@ 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.
* BluetoothDBusService is the implementation of BluetoothService for DBus on
* linux/android/B2G. Function comments are in BluetoothService.h
*/
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);
virtual nsresult
GetProperties(BluetoothObjectType aType,
const nsAString& aPath,
BluetoothReplyRunnable* aRunnable);
virtual nsresult
SetProperty(BluetoothObjectType aType,
const nsAString& aPath,
const BluetoothNamedValue& aValue,
BluetoothReplyRunnable* aRunnable);
virtual bool
GetDevicePath(const nsAString& aAdapterPath,
const nsAString& aDeviceAddress,
nsAString& aDevicePath);
private:
nsresult SendGetPropertyMessage(const nsAString& aPath,
const char* aInterface,
void (*aCB)(DBusMessage *, void *),
BluetoothReplyRunnable* aRunnable);
nsresult SendDiscoveryMessage(const nsAString& aAdapterPath,
const char* aMessageName,
BluetoothReplyRunnable* aRunnable);
nsresult SendSetPropertyMessage(const nsString& aPath, const char* aInterface,
const BluetoothNamedValue& aValue,
BluetoothReplyRunnable* aRunnable);
};
END_BLUETOOTH_NAMESPACE

Просмотреть файл

@ -170,7 +170,7 @@ EventFilter(DBusConnection *aConn, DBusMessage *aMsg,
nsresult
StartBluetoothConnection()
{
if(sDBusConnection) {
if (sDBusConnection) {
NS_WARNING("DBusConnection already established, skipping");
return NS_OK;
}
@ -193,7 +193,7 @@ StartBluetoothConnection()
nsresult
StopBluetoothConnection()
{
if(!sDBusConnection) {
if (!sDBusConnection) {
NS_WARNING("DBusConnection does not exist, nothing to stop, skipping.");
return NS_OK;
}

Просмотреть файл

@ -82,7 +82,6 @@ enum {
static const char* 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'",

Просмотреть файл

@ -12,8 +12,6 @@ struct DBusMessage;
namespace mozilla {
namespace ipc {
class nsCString;
/**
* Starts the DBus thread, which handles returning signals to objects
* that call asynchronous functions. This should be called from the