Bug 730992 - Patch 2: The machinery in Bluetooth*Service, r=qdot, sr=mrbkap

---
 dom/bluetooth/BluetoothCommon.h              |    8 +
 dom/bluetooth/BluetoothService.h             |   17 +
 dom/bluetooth/linux/BluetoothDBusService.cpp |  561 ++++++++++++++++++++++++-
 dom/bluetooth/linux/BluetoothDBusService.h   |   23 +
 4 files changed, 586 insertions(+), 23 deletions(-)
This commit is contained in:
Eric Chou 2012-08-17 18:35:59 +08:00
parent 1353638291
commit 2dc14ca1d9
4 changed files with 586 additions and 23 deletions

View File

@ -18,6 +18,14 @@
#define USING_BLUETOOTH_NAMESPACE \
using namespace mozilla::dom::bluetooth;
#define LOCAL_AGENT_PATH "/B2G/bluetooth/agent"
#define REMOTE_AGENT_PATH "/B2G/bluetooth/remote_device_agent"
// Bluetooth address format: xx:xx:xx:xx:xx:xx (or xx_xx_xx_xx_xx_xx)
#define BLUETOOTH_ADDRESS_LENGTH 17
#define DOM_BLUETOOTH_URL_PREF "dom.mozBluetooth.whitelist"
class nsCString;
BEGIN_BLUETOOTH_NAMESPACE

View File

@ -209,6 +209,22 @@ public:
RemoveReservedServicesInternal(const nsAString& aAdapterPath,
const nsTArray<PRUint32>& aServiceHandles) = 0;
virtual nsresult
CreatePairedDeviceInternal(const nsAString& aAdapterPath,
const nsAString& aAddress,
int aTimeout,
BluetoothReplyRunnable* aRunnable) = 0;
virtual nsresult
RemoveDeviceInternal(const nsAString& aAdapterPath,
const nsAString& aObjectPath,
BluetoothReplyRunnable* aRunnable) = 0;
virtual bool SetPinCodeInternal(const nsAString& aDeviceAddress, const nsAString& aPinCode) = 0;
virtual bool SetPasskeyInternal(const nsAString& aDeviceAddress, PRUint32 aPasskey) = 0;
virtual bool SetPairingConfirmationInternal(const nsAString& aDeviceAddress, bool aConfirm) = 0;
virtual bool SetAuthorizationInternal(const nsAString& aDeviceAddress, bool aAllow) = 0;
/**
* Due to the fact that some operations require multiple calls, a
* CommandThread is created that can run blocking, platform-specific calls
@ -222,6 +238,7 @@ public:
*
*/
nsCOMPtr<nsIThread> mBluetoothCommandThread;
protected:
BluetoothService()
{

View File

@ -28,7 +28,7 @@
#include "nsAutoPtr.h"
#include "nsThreadUtils.h"
#include "nsDebug.h"
#include "nsClassHashtable.h"
#include "nsDataHashtable.h"
#include "mozilla/ipc/DBusThread.h"
#include "mozilla/ipc/DBusUtils.h"
#include "mozilla/ipc/RawDBusConnection.h"
@ -57,9 +57,11 @@ USING_BLUETOOTH_NAMESPACE
#define LOG(args...) if (BTDEBUG) printf(args);
#endif
#define B2G_AGENT_CAPABILITIES "DisplayYesNo"
#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 DBUS_AGENT_IFACE BLUEZ_DBUS_BASE_IFC ".Agent"
#define BLUEZ_DBUS_BASE_PATH "/org/bluez"
#define BLUEZ_DBUS_BASE_IFC "org.bluez"
#define BLUEZ_ERROR_IFC "org.bluez.Error"
@ -133,6 +135,8 @@ static const char* sBluetoothDBusSignals[] =
*
*/
static nsAutoPtr<RawDBusConnection> gThreadConnection;
static nsDataHashtable<nsStringHashKey, DBusMessage* > sPairingReqTable;
static nsDataHashtable<nsStringHashKey, DBusMessage* > sAuthorizeReqTable;
class DistributeBluetoothSignalTask : public nsRunnable {
BluetoothSignal mSignal;
@ -155,7 +159,7 @@ public:
}
};
bool
static bool
IsDBusMessageError(DBusMessage* aMsg, DBusError* aErr, nsAString& aErrorStr)
{
if(aErr && dbus_error_is_set(aErr)) {
@ -187,7 +191,7 @@ IsDBusMessageError(DBusMessage* aMsg, DBusError* aErr, nsAString& aErrorStr)
return false;
}
void
static void
DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable,
const BluetoothValue& aValue, const nsAString& aErrorStr)
{
@ -206,7 +210,7 @@ DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable,
}
}
void
static void
UnpackObjectPathMessage(DBusMessage* aMsg, DBusError* aErr,
BluetoothValue& aValue, nsAString& aErrorStr)
{
@ -231,6 +235,300 @@ UnpackObjectPathMessage(DBusMessage* aMsg, DBusError* aErr,
typedef void (*UnpackFunc)(DBusMessage*, DBusError*, BluetoothValue&, nsAString&);
static 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;
}
static nsString
GetAddressFromObjectPath(const nsAString& aObjectPath)
{
// 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 address(aObjectPath);
int addressHead = address.RFind("/") + 5;
MOZ_ASSERT(addressHead + BLUETOOTH_ADDRESS_LENGTH == address.Length());
address.Cut(0, addressHead);
address.ReplaceChar('_', ':');
return address;
}
static void
KeepDBusPairingMessage(const nsString& aDeviceAddress, DBusMessage* aMsg)
{
sPairingReqTable.Put(aDeviceAddress, aMsg);
// Increase ref count here because we need this message later.
// It'll be unrefed when set*Internal() is called.
dbus_message_ref(aMsg);
}
static DBusHandlerResult
AgentEventFilter(DBusConnection *conn, DBusMessage *msg, void *data)
{
if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_METHOD_CALL) {
LOG("%s: agent handler not interested (not a method call).\n", __FUNCTION__);
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
DBusError err;
dbus_error_init(&err);
nsString signalPath = NS_ConvertUTF8toUTF16(dbus_message_get_path(msg));
nsString signalName = NS_ConvertUTF8toUTF16(dbus_message_get_member(msg));
nsString errorStr;
BluetoothValue v;
InfallibleTArray<BluetoothNamedValue> parameters;
// The following descriptions of each signal are retrieved from:
//
// http://maemo.org/api_refs/5.0/beta/bluez/agent.html
//
if (dbus_message_is_method_call(msg, DBUS_AGENT_IFACE, "Cancel")) {
// This method gets called to indicate that the agent request failed before a reply
// was returned.
// Return directly
DBusMessage *reply = dbus_message_new_method_return(msg);
if (!reply) {
errorStr.AssignLiteral("Memory can't be allocated for the message.");
} else {
dbus_connection_send(conn, reply, NULL);
dbus_message_unref(reply);
}
} else if (dbus_message_is_method_call(msg, DBUS_AGENT_IFACE, "Authorize")) {
// This method gets called when the service daemon needs to authorize a
// connection/service request.
char *objectPath;
const char *uuid;
if (!dbus_message_get_args(msg, NULL,
DBUS_TYPE_OBJECT_PATH, &objectPath,
DBUS_TYPE_STRING, &uuid,
DBUS_TYPE_INVALID)) {
LOG("%s: Invalid arguments for Authorize() method", __FUNCTION__);
errorStr.AssignLiteral("Invalid arguments for Authorize() method");
} else {
nsString deviceAddress = GetAddressFromObjectPath(NS_ConvertUTF8toUTF16(objectPath));
parameters.AppendElement(BluetoothNamedValue(NS_LITERAL_STRING("Device"), deviceAddress));
parameters.AppendElement(BluetoothNamedValue(NS_LITERAL_STRING("UUID"),
NS_ConvertUTF8toUTF16(uuid)));
// Because we may have authorization request and pairing request from the
// same remote device at the same time, we need two tables to keep these messages.
sAuthorizeReqTable.Put(deviceAddress, msg);
// Increase ref count here because we need this message later.
// It'll be unrefed when setAuthorizationInternal() is called.
dbus_message_ref(msg);
v = parameters;
}
} else if (dbus_message_is_method_call(msg, DBUS_AGENT_IFACE, "RequestConfirmation")) {
// This method gets called when the service daemon needs to confirm a passkey for
// an authentication.
char *objectPath;
uint32_t passkey;
if (!dbus_message_get_args(msg, NULL,
DBUS_TYPE_OBJECT_PATH, &objectPath,
DBUS_TYPE_UINT32, &passkey,
DBUS_TYPE_INVALID)) {
LOG("%s: Invalid arguments for RequestConfirmation() method", __FUNCTION__);
errorStr.AssignLiteral("Invalid arguments for RequestConfirmation() method");
} else {
nsString deviceAddress = GetAddressFromObjectPath(NS_ConvertUTF8toUTF16(objectPath));
parameters.AppendElement(BluetoothNamedValue(NS_LITERAL_STRING("Device"), deviceAddress));
parameters.AppendElement(BluetoothNamedValue(NS_LITERAL_STRING("Passkey"), passkey));
KeepDBusPairingMessage(deviceAddress, msg);
v = parameters;
}
} else if (dbus_message_is_method_call(msg, DBUS_AGENT_IFACE, "RequestPinCode")) {
// This method gets called when the service daemon needs to get the passkey for an
// authentication. The return value should be a string of 1-16 characters length.
// The string can be alphanumeric.
char *objectPath;
if (!dbus_message_get_args(msg, NULL,
DBUS_TYPE_OBJECT_PATH, &objectPath,
DBUS_TYPE_INVALID)) {
LOG("%s: Invalid arguments for RequestPinCode() method", __FUNCTION__);
errorStr.AssignLiteral("Invalid arguments for RequestPinCode() method");
} else {
nsString deviceAddress = GetAddressFromObjectPath(NS_ConvertUTF8toUTF16(objectPath));
parameters.AppendElement(BluetoothNamedValue(NS_LITERAL_STRING("Device"), deviceAddress));
KeepDBusPairingMessage(deviceAddress, msg);
v = parameters;
}
} else if (dbus_message_is_method_call(msg, DBUS_AGENT_IFACE, "RequestPasskey")) {
// This method gets called when the service daemon needs to get the passkey for an
// authentication. The return value should be a numeric value between 0-999999.
char *objectPath;
if (!dbus_message_get_args(msg, NULL,
DBUS_TYPE_OBJECT_PATH, &objectPath,
DBUS_TYPE_INVALID)) {
LOG("%s: Invalid arguments for RequestPasskey() method", __FUNCTION__);
errorStr.AssignLiteral("Invalid arguments for RequestPasskey() method");
} else {
nsString deviceAddress = GetAddressFromObjectPath(NS_ConvertUTF8toUTF16(objectPath));
parameters.AppendElement(BluetoothNamedValue(NS_LITERAL_STRING("Device"), deviceAddress));
KeepDBusPairingMessage(deviceAddress, msg);
v = parameters;
}
} else if (dbus_message_is_method_call(msg, DBUS_AGENT_IFACE, "Release")) {
// This method gets called when the service daemon unregisters the agent. An agent
// can use it to do cleanup tasks. There is no need to unregister the agent, because
// when this method gets called it has already been unregistered.
DBusMessage *reply = dbus_message_new_method_return(msg);
if (!reply) {
errorStr.AssignLiteral("Memory can't be allocated for the message.");
} else {
dbus_connection_send(conn, reply, NULL);
dbus_message_unref(reply);
// Do not send an notification to upper layer, too annoying.
return DBUS_HANDLER_RESULT_HANDLED;
}
} else {
LOG("agent handler %s: Unhandled event. Ignore.", __FUNCTION__);
}
if (!errorStr.IsEmpty()) {
NS_WARNING(NS_ConvertUTF16toUTF8(errorStr).get());
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
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;
}
static const DBusObjectPathVTable agentVtable = {
NULL, AgentEventFilter, NULL, NULL, NULL, NULL
};
// Local agent means agent for Adapter, not agent for Device. Some signals
// will be passed to local agent, some will be passed to device agent.
// For example, if a remote device would like to pair with us, then the
// signal will be passed to local agent. If we start pairing process with
// calling CreatePairedDevice, we'll get signal which should be passed to
// device agent.
static bool
RegisterLocalAgent(const char* adapterPath,
const char* agentPath,
const char* capabilities)
{
MOZ_ASSERT(!NS_IsMainThread());
if (!dbus_connection_register_object_path(gThreadConnection->GetConnection(),
agentPath,
&agentVtable,
NULL)) {
LOG("%s: Can't register object path %s for agent!",
__FUNCTION__, agentPath);
return false;
}
DBusMessage* msg =
dbus_message_new_method_call("org.bluez", adapterPath,
DBUS_ADAPTER_IFACE, "RegisterAgent");
if (!msg) {
LOG("%s: Can't allocate new method call for agent!", __FUNCTION__);
return false;
}
if (!dbus_message_append_args(msg,
DBUS_TYPE_OBJECT_PATH, &agentPath,
DBUS_TYPE_STRING, &capabilities,
DBUS_TYPE_INVALID)) {
LOG("%s: Couldn't append arguments to dbus message.", __FUNCTION__);
return false;
}
DBusError err;
dbus_error_init(&err);
DBusMessage* reply =
dbus_connection_send_with_reply_and_block(gThreadConnection->GetConnection(),
msg, -1, &err);
dbus_message_unref(msg);
if (!reply) {
if (dbus_error_is_set(&err)) {
if(!strcmp(err.name, "org.bluez.Error.AlreadyExists")) {
LOG_AND_FREE_DBUS_ERROR(&err);
#ifdef DEBUG
LOG("Agent already registered, still returning true");
#endif
} else {
LOG_AND_FREE_DBUS_ERROR(&err);
LOG("%s: Can't register agent!", __FUNCTION__);
return false;
}
}
} else {
dbus_message_unref(reply);
}
dbus_connection_flush(gThreadConnection->GetConnection());
return true;
}
static bool
RegisterAgent(const nsAString& aAdapterPath)
{
MOZ_ASSERT(!NS_IsMainThread());
if (!RegisterLocalAgent(NS_ConvertUTF16toUTF8(aAdapterPath).get(),
LOCAL_AGENT_PATH,
B2G_AGENT_CAPABILITIES)) {
return false;
}
// There is no "RegisterAgent" function defined in device interface.
// When we call "CreatePairedDevice", it will do device agent registration for us.
// (See maemo.org/api_refs/5.0/beta/bluez/adapter.html)
if (!dbus_connection_register_object_path(gThreadConnection->GetConnection(),
REMOTE_AGENT_PATH,
&agentVtable,
NULL)) {
LOG("%s: Can't register object path %s for remote device agent!",
__FUNCTION__, REMOTE_AGENT_PATH);
return false;
}
return true;
}
void
RunDBusCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable,
UnpackFunc aFunc)
@ -675,9 +973,20 @@ BluetoothDBusService::StartInternal()
return NS_ERROR_FAILURE;
}
sPairingReqTable.Init();
sAuthorizeReqTable.Init();
return NS_OK;
}
PLDHashOperator
UnrefDBusMessages(const nsAString& key, DBusMessage* value, void* arg)
{
dbus_message_unref(value);
return PL_DHASH_NEXT;
}
nsresult
BluetoothDBusService::StopInternal()
{
@ -705,6 +1014,14 @@ BluetoothDBusService::StopInternal()
mConnection = nullptr;
gThreadConnection = nullptr;
mBluetoothSignalObserverTable.Clear();
// unref stored DBusMessages before clear the hashtable
sPairingReqTable.EnumerateRead(UnrefDBusMessages, nullptr);
sPairingReqTable.Clear();
sAuthorizeReqTable.EnumerateRead(UnrefDBusMessages, nullptr);
sAuthorizeReqTable.Clear();
StopDBus();
return NS_OK;
}
@ -767,6 +1084,9 @@ public:
// We have to manually attach the path to the rest of the elements
v.get_ArrayOfBluetoothNamedValue().AppendElement(BluetoothNamedValue(NS_LITERAL_STRING("Path"),
path));
RegisterAgent(path);
DispatchBluetoothReply(mRunnable, v, replyError);
return NS_OK;
@ -783,6 +1103,7 @@ BluetoothDBusService::GetDefaultAdapterPathInternal(BluetoothReplyRunnable* aRun
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;
@ -1035,20 +1356,6 @@ BluetoothDBusService::SetProperty(BluetoothObjectType aType,
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,
@ -1066,12 +1373,12 @@ BluetoothDBusService::GetDeviceServiceChannelInternal(const nsAString& aObjectPa
// This is a blocking call, should not be run on main thread.
MOZ_ASSERT(!NS_IsMainThread());
const char* deviceObjectPath = NS_ConvertUTF16toUTF8(aObjectPath).get();
const char* pattern = NS_ConvertUTF16toUTF8(aPattern).get();
nsCString tempPattern = NS_ConvertUTF16toUTF8(aPattern);
const char* pattern = tempPattern.get();
DBusMessage *reply =
dbus_func_args(gThreadConnection->GetConnection(),
deviceObjectPath,
NS_ConvertUTF16toUTF8(aObjectPath).get(),
DBUS_DEVICE_IFACE, "GetServiceAttributeValue",
DBUS_TYPE_STRING, &pattern,
DBUS_TYPE_UINT16, &aAttributeId,
@ -1111,7 +1418,6 @@ BluetoothDBusService::AddReservedServicesInternal(const nsAString& aAdapterPath,
MOZ_ASSERT(!NS_IsMainThread());
nsTArray<PRUint32> ret;
const char* adapterPath = NS_ConvertUTF16toUTF8(aAdapterPath).get();
int length = aServices.Length();
if (length == 0) return ret;
@ -1119,7 +1425,7 @@ BluetoothDBusService::AddReservedServicesInternal(const nsAString& aAdapterPath,
const uint32_t* services = aServices.Elements();
DBusMessage* reply =
dbus_func_args(gThreadConnection->GetConnection(),
adapterPath,
NS_ConvertUTF16toUTF8(aAdapterPath).get(),
DBUS_ADAPTER_IFACE, "AddReservedServiceRecords",
DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
&services, length, DBUS_TYPE_INVALID);
@ -1156,3 +1462,212 @@ BluetoothDBusService::RemoveReservedServicesInternal(const nsAString& aAdapterPa
dbus_message_unref(reply);
return true;
}
nsresult
BluetoothDBusService::CreatePairedDeviceInternal(const nsAString& aAdapterPath,
const nsAString& aDeviceAddress,
int aTimeout,
BluetoothReplyRunnable* aRunnable)
{
const char *capabilities = B2G_AGENT_CAPABILITIES;
const char *deviceAgentPath = REMOTE_AGENT_PATH;
nsCString tempDeviceAddress = NS_ConvertUTF16toUTF8(aDeviceAddress);
const char *deviceAddress = tempDeviceAddress.get();
nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
// Then send CreatePairedDevice, it will register a temp device agent then
// unregister it after pairing process is over
bool ret = dbus_func_args_async(mConnection,
aTimeout,
GetObjectPathCallback,
(void*)runnable,
NS_ConvertUTF16toUTF8(aAdapterPath).get(),
DBUS_ADAPTER_IFACE,
"CreatePairedDevice",
DBUS_TYPE_STRING, &deviceAddress,
DBUS_TYPE_OBJECT_PATH, &deviceAgentPath,
DBUS_TYPE_STRING, &capabilities,
DBUS_TYPE_INVALID);
if (!ret) {
NS_WARNING("Could not start async function!");
return NS_ERROR_FAILURE;
}
runnable.forget();
return NS_OK;
}
nsresult
BluetoothDBusService::RemoveDeviceInternal(const nsAString& aAdapterPath,
const nsAString& aDeviceAddress,
BluetoothReplyRunnable* aRunnable)
{
nsCString tempDeviceObjectPath =
NS_ConvertUTF16toUTF8(GetObjectPathFromAddress(aAdapterPath, aDeviceAddress));
const char* deviceObjectPath = tempDeviceObjectPath.get();
nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
// We don't really care about how long it would take on removing a device,
// just to make sure that the value of timeout is reasonable. So, we use
// -1 for the timeout, which means a reasonable default timeout will be used.
bool ret = dbus_func_args_async(mConnection,
-1,
GetVoidCallback,
(void*)runnable,
NS_ConvertUTF16toUTF8(aAdapterPath).get(),
DBUS_ADAPTER_IFACE,
"RemoveDevice",
DBUS_TYPE_OBJECT_PATH, &deviceObjectPath,
DBUS_TYPE_INVALID);
if (!ret) {
NS_WARNING("Could not start async function!");
return NS_ERROR_FAILURE;
}
runnable.forget();
return NS_OK;
}
bool
BluetoothDBusService::SetPinCodeInternal(const nsAString& aDeviceAddress, const nsAString& aPinCode)
{
DBusMessage *msg;
if (!sPairingReqTable.Get(aDeviceAddress, &msg)) {
LOG("%s: Couldn't get original request message.", __FUNCTION__);
return false;
}
DBusMessage *reply = dbus_message_new_method_return(msg);
if (!reply) {
LOG("%s: Memory can't be allocated for the message.", __FUNCTION__);
dbus_message_unref(msg);
return false;
}
bool result;
nsCString tempPinCode = NS_ConvertUTF16toUTF8(aPinCode);
const char* pinCode = tempPinCode.get();
if (!dbus_message_append_args(reply,
DBUS_TYPE_STRING, &pinCode,
DBUS_TYPE_INVALID)) {
LOG("%s: Couldn't append arguments to dbus message.", __FUNCTION__);
result = false;
} else {
result = dbus_connection_send(mConnection, reply, NULL);
}
dbus_message_unref(msg);
dbus_message_unref(reply);
sPairingReqTable.Remove(aDeviceAddress);
return result;
}
bool
BluetoothDBusService::SetPasskeyInternal(const nsAString& aDeviceAddress, PRUint32 aPasskey)
{
DBusMessage *msg;
if (!sPairingReqTable.Get(aDeviceAddress, &msg)) {
LOG("%s: Couldn't get original request message.", __FUNCTION__);
return false;
}
DBusMessage *reply = dbus_message_new_method_return(msg);
if (!reply) {
LOG("%s: Memory can't be allocated for the message.", __FUNCTION__);
dbus_message_unref(msg);
return false;
}
uint32_t passkey = aPasskey;
bool result;
if (!dbus_message_append_args(reply,
DBUS_TYPE_UINT32, &passkey,
DBUS_TYPE_INVALID)) {
LOG("%s: Couldn't append arguments to dbus message.", __FUNCTION__);
result = false;
} else {
result = dbus_connection_send(mConnection, reply, NULL);
}
dbus_message_unref(msg);
dbus_message_unref(reply);
sPairingReqTable.Remove(aDeviceAddress);
return result;
}
bool
BluetoothDBusService::SetPairingConfirmationInternal(const nsAString& aDeviceAddress, bool aConfirm)
{
DBusMessage *msg;
if (!sPairingReqTable.Get(aDeviceAddress, &msg)) {
LOG("%s: Couldn't get original request message.", __FUNCTION__);
return false;
}
DBusMessage *reply;
if (aConfirm) {
reply = dbus_message_new_method_return(msg);
} else {
reply = dbus_message_new_error(msg, "org.bluez.Error.Rejected", "User rejected confirmation");
}
if (!reply) {
LOG("%s: Memory can't be allocated for the message.", __FUNCTION__);
dbus_message_unref(msg);
return false;
}
bool result = dbus_connection_send(mConnection, reply, NULL);
dbus_message_unref(msg);
dbus_message_unref(reply);
sPairingReqTable.Remove(aDeviceAddress);
return result;
}
bool
BluetoothDBusService::SetAuthorizationInternal(const nsAString& aDeviceAddress, bool aAllow)
{
DBusMessage *msg;
if (!sAuthorizeReqTable.Get(aDeviceAddress, &msg)) {
LOG("%s: Couldn't get original request message.", __FUNCTION__);
return false;
}
DBusMessage *reply;
if (aAllow) {
reply = dbus_message_new_method_return(msg);
} else {
reply = dbus_message_new_error(msg, "org.bluez.Error.Rejected", "Authorization rejected");
}
if (!reply) {
LOG("%s: Memory can't be allocated for the message.", __FUNCTION__);
dbus_message_unref(msg);
return false;
}
bool result = dbus_connection_send(mConnection, reply, NULL);
dbus_message_unref(msg);
dbus_message_unref(reply);
sAuthorizeReqTable.Remove(aDeviceAddress);
return result;
}

View File

@ -59,6 +59,29 @@ public:
RemoveReservedServicesInternal(const nsAString& aAdapterPath,
const nsTArray<PRUint32>& aServiceHandles);
virtual nsresult
CreatePairedDeviceInternal(const nsAString& aAdapterPath,
const nsAString& aDeviceAddress,
int aTimeout,
BluetoothReplyRunnable* aRunnable);
virtual nsresult
RemoveDeviceInternal(const nsAString& aAdapterPath,
const nsAString& aDeviceObjectPath,
BluetoothReplyRunnable* aRunnable);
virtual bool
SetPinCodeInternal(const nsAString& aDeviceAddress, const nsAString& aPinCode);
virtual bool
SetPasskeyInternal(const nsAString& aDeviceAddress, PRUint32 aPasskey);
virtual bool
SetPairingConfirmationInternal(const nsAString& aDeviceAddress, bool aConfirm);
virtual bool
SetAuthorizationInternal(const nsAString& aDeviceAddress, bool aAllow);
private:
nsresult SendGetPropertyMessage(const nsAString& aPath,
const char* aInterface,