CLOSED TREE Bug 1180554 - Dispatch events to PBAP event handlers when the PBAP requests comes. r=btian, r=mrbkap

This commit is contained in:
Jamin Liu 2015-08-24 10:29:56 +08:00
parent 92b3e3e9e6
commit 3028f7aa6e
20 changed files with 1003 additions and 18 deletions

View File

@ -852,6 +852,9 @@ GK_ATOM(onpopuphiding, "onpopuphiding")
GK_ATOM(onpopupshowing, "onpopupshowing")
GK_ATOM(onpopupshown, "onpopupshown")
GK_ATOM(onpreviewstatechange, "onpreviewstatechange")
GK_ATOM(onpullphonebookreq, "onpullphonebookreq")
GK_ATOM(onpullvcardentryreq, "onpullvcardentryreq")
GK_ATOM(onpullvcardlistingreq, "onpullvcardlistingreq")
GK_ATOM(onpush, "onpush")
GK_ATOM(onpushsubscriptionchange, "onpushsubscriptionchange")
GK_ATOM(onpschange, "onpschange")

View File

@ -199,6 +199,10 @@ DOMInterfaces = {
'mozilla::dom::bluetooth::BluetoothPairingListener',
},
'BluetoothPbapRequestHandle': {
'nativeType': 'mozilla::dom::bluetooth::BluetoothPbapRequestHandle',
},
'BoxObject': {
'resultNotAddRefed': ['element'],
},

View File

@ -213,6 +213,13 @@ extern bool gBluetoothDebugFlag;
*/
#define REQUEST_MEDIA_PLAYSTATUS_ID "requestmediaplaystatus"
/**
* When receiving a PBAP request from a remote device, we'll dispatch an event.
*/
#define PULL_PHONEBOOK_REQ_ID "pullphonebookreq"
#define PULL_VCARD_ENTRY_REQ_ID "pullvcardentryreq"
#define PULL_VCARD_LISTING_REQ_ID "pullvcardlistingreq"
/**
* When the value of a characteristic of a remote BLE device changes, we'll
* dispatch an event

View File

@ -0,0 +1,79 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "BluetoothCommon.h"
#include "BluetoothPbapRequestHandle.h"
#include "BluetoothReplyRunnable.h"
#include "BluetoothService.h"
#include "mozilla/dom/BluetoothPbapRequestHandleBinding.h"
using namespace mozilla;
using namespace dom;
USING_BLUETOOTH_NAMESPACE
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(BluetoothPbapRequestHandle, mOwner)
NS_IMPL_CYCLE_COLLECTING_ADDREF(BluetoothPbapRequestHandle)
NS_IMPL_CYCLE_COLLECTING_RELEASE(BluetoothPbapRequestHandle)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BluetoothPbapRequestHandle)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
BluetoothPbapRequestHandle::BluetoothPbapRequestHandle(nsPIDOMWindow* aOwner)
: mOwner(aOwner)
{
MOZ_ASSERT(aOwner);
}
BluetoothPbapRequestHandle::~BluetoothPbapRequestHandle()
{
}
already_AddRefed<BluetoothPbapRequestHandle>
BluetoothPbapRequestHandle::Create(nsPIDOMWindow* aOwner)
{
MOZ_ASSERT(aOwner);
nsRefPtr<BluetoothPbapRequestHandle> handle =
new BluetoothPbapRequestHandle(aOwner);
return handle.forget();
}
already_AddRefed<DOMRequest>
BluetoothPbapRequestHandle::ReplyTovCardPulling(Blob& aBlob,
ErrorResult& aRv)
{
// TODO: Implement this function (Bug 1180555)
return nullptr;
}
already_AddRefed<DOMRequest>
BluetoothPbapRequestHandle::ReplyToPhonebookPulling(Blob& aBlob,
uint16_t phonebookSize,
ErrorResult& aRv)
{
// TODO: Implement this function (Bug 1180555)
return nullptr;
}
already_AddRefed<DOMRequest>
BluetoothPbapRequestHandle::ReplyTovCardListing(Blob& aBlob,
uint16_t phonebookSize,
ErrorResult& aRv)
{
// TODO: Implement this function (Bug 1180555)
return nullptr;
}
JSObject*
BluetoothPbapRequestHandle::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)
{
return BluetoothPbapRequestHandleBinding::Wrap(aCx, this, aGivenProto);
}

View File

@ -0,0 +1,62 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_bluetooth_bluetoothpbaprequesthandle_h
#define mozilla_dom_bluetooth_bluetoothpbaprequesthandle_h
#include "nsCOMPtr.h"
#include "mozilla/dom/DOMRequest.h"
#include "mozilla/dom/BlobSet.h"
namespace mozilla {
class ErrorResult;
namespace dom {
class Blob;
class DOMRequest;
}
}
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothPbapRequestHandle final : public nsISupports
, public nsWrapperCache
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(BluetoothPbapRequestHandle)
static already_AddRefed<BluetoothPbapRequestHandle>
Create(nsPIDOMWindow* aOwner);
nsPIDOMWindow* GetParentObject() const
{
return mOwner;
}
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
already_AddRefed<DOMRequest> ReplyTovCardPulling(Blob& aBlob,
ErrorResult& aRv);
already_AddRefed<DOMRequest> ReplyToPhonebookPulling(Blob& aBlob,
uint16_t phonebookSize,
ErrorResult& aRv);
already_AddRefed<DOMRequest> ReplyTovCardListing(Blob& aBlob,
uint16_t phonebookSize,
ErrorResult& aRv);
private:
BluetoothPbapRequestHandle(nsPIDOMWindow* aOwner);
~BluetoothPbapRequestHandle();
nsCOMPtr<nsPIDOMWindow> mOwner;
};
END_BLUETOOTH_NAMESPACE
#endif // mozilla_dom_bluetooth_bluetoothpbaprequesthandle_h

View File

@ -235,29 +235,59 @@ BluetoothPbapManager::ReceiveSocketData(BluetoothSocket* aSocket,
AfterPbapDisconnected();
break;
case ObexRequestCode::SetPath: {
// Section 3.3.6 "SetPath", IrOBEX 1.2
// [opcode:1][length:2][flags:1][contants:1][Headers:var]
if (receivedLength < 5 ||
!ParseHeaders(&data[5], receivedLength - 5, &pktHeaders)) {
ReplyError(ObexResponseCode::BadRequest);
return;
}
// Section 3.3.6 "SetPath", IrOBEX 1.2
// [opcode:1][length:2][flags:1][contants:1][Headers:var]
if (receivedLength < 5 ||
!ParseHeaders(&data[5], receivedLength - 5, &pktHeaders)) {
ReplyError(ObexResponseCode::BadRequest);
return;
}
uint8_t response = SetPhoneBookPath(data[3], pktHeaders);
if (response != ObexResponseCode::Success) {
ReplyError(response);
return;
}
uint8_t response = SetPhoneBookPath(data[3], pktHeaders);
if (response != ObexResponseCode::Success) {
ReplyError(response);
return;
}
ReplyToSetPath();
ReplyToSetPath();
break;
}
case ObexRequestCode::Get:
case ObexRequestCode::GetFinal: {
// [opcode:1][length:2][Headers:var]
if (receivedLength < 3 ||
!ParseHeaders(&data[3], receivedLength - 3, &pktHeaders)) {
ReplyError(ObexResponseCode::BadRequest);
return;
}
nsString type;
pktHeaders.GetContentType(type);
uint8_t response;
if (type.EqualsLiteral("x-bt/vcard-listing")) {
response = PullvCardListing(pktHeaders);
} else if (type.EqualsLiteral("x-bt/vcard")) {
response = PullvCardEntry(pktHeaders);
} else if (type.EqualsLiteral("x-bt/phonebook")) {
response = PullPhonebook(pktHeaders);
} else {
response = ObexResponseCode::BadRequest;
BT_LOGR("Unknown PBAP request type: %s",
NS_ConvertUTF16toUTF8(type).get());
}
// The OBEX success response will be sent after Gaia replies the PBAP
// request.
if (response != ObexResponseCode::Success) {
ReplyError(response);
return;
}
break;
}
case ObexRequestCode::Put:
case ObexRequestCode::PutFinal:
case ObexRequestCode::Get:
case ObexRequestCode::GetFinal:
ReplyError(ObexResponseCode::BadRequest);
BT_LOGR("Unsupported ObexRequestCode %x", opCode);
break;
default:
ReplyError(ObexResponseCode::NotImplemented);
@ -347,6 +377,241 @@ BluetoothPbapManager::SetPhoneBookPath(uint8_t flags,
return ObexResponseCode::Success;
}
uint8_t
BluetoothPbapManager::PullPhonebook(const ObexHeaderSet& aHeader)
{
MOZ_ASSERT(NS_IsMainThread());
BluetoothService* bs = BluetoothService::Get();
if (!bs) {
return ObexResponseCode::PreconditionFailed;
}
InfallibleTArray<BluetoothNamedValue> data;
nsString name;
aHeader.GetName(name);
BT_APPEND_NAMED_VALUE(data, "name", name);
AppendBtNamedValueByTagId(aHeader, data, AppParameterTag::Format);
AppendBtNamedValueByTagId(aHeader, data, AppParameterTag::PropertySelector);
AppendBtNamedValueByTagId(aHeader, data, AppParameterTag::MaxListCount);
AppendBtNamedValueByTagId(aHeader, data, AppParameterTag::ListStartOffset);
AppendBtNamedValueByTagId(aHeader, data, AppParameterTag::vCardSelector);
#ifdef MOZ_B2G_BT_API_V1
bs->DistributeSignal(
BluetoothSignal(NS_LITERAL_STRING(PULL_PHONEBOOK_REQ_ID),
NS_LITERAL_STRING(KEY_ADAPTER),
data));
#else
bs->DistributeSignal(NS_LITERAL_STRING(PULL_PHONEBOOK_REQ_ID),
NS_LITERAL_STRING(KEY_ADAPTER),
data);
#endif
return ObexResponseCode::Success;
}
uint8_t
BluetoothPbapManager::PullvCardListing(const ObexHeaderSet& aHeader)
{
MOZ_ASSERT(NS_IsMainThread());
BluetoothService* bs = BluetoothService::Get();
if (!bs) {
return ObexResponseCode::PreconditionFailed;
}
InfallibleTArray<BluetoothNamedValue> data;
nsString name;
aHeader.GetName(name);
BT_APPEND_NAMED_VALUE(data, "name", name);
AppendBtNamedValueByTagId(aHeader, data, AppParameterTag::Order);
AppendBtNamedValueByTagId(aHeader, data, AppParameterTag::SearchValue);
AppendBtNamedValueByTagId(aHeader, data, AppParameterTag::SearchProperty);
AppendBtNamedValueByTagId(aHeader, data, AppParameterTag::MaxListCount);
AppendBtNamedValueByTagId(aHeader, data, AppParameterTag::ListStartOffset);
AppendBtNamedValueByTagId(aHeader, data, AppParameterTag::vCardSelector);
#ifdef MOZ_B2G_BT_API_V1
bs->DistributeSignal(
BluetoothSignal(NS_LITERAL_STRING(PULL_VCARD_LISTING_REQ_ID),
NS_LITERAL_STRING(KEY_ADAPTER),
data));
#else
bs->DistributeSignal(NS_LITERAL_STRING(PULL_VCARD_LISTING_REQ_ID),
NS_LITERAL_STRING(KEY_ADAPTER),
data);
#endif
return ObexResponseCode::Success;
}
uint8_t
BluetoothPbapManager::PullvCardEntry(const ObexHeaderSet& aHeader)
{
MOZ_ASSERT(NS_IsMainThread());
BluetoothService* bs = BluetoothService::Get();
if (!bs) {
return ObexResponseCode::PreconditionFailed;
}
InfallibleTArray<BluetoothNamedValue> data;
nsString name;
aHeader.GetName(name);
BT_APPEND_NAMED_VALUE(data, "name", name);
AppendBtNamedValueByTagId(aHeader, data, AppParameterTag::Format);
AppendBtNamedValueByTagId(aHeader, data, AppParameterTag::PropertySelector);
#ifdef MOZ_B2G_BT_API_V1
bs->DistributeSignal(
BluetoothSignal(NS_LITERAL_STRING(PULL_VCARD_ENTRY_REQ_ID),
NS_LITERAL_STRING(KEY_ADAPTER),
data));
#else
bs->DistributeSignal(NS_LITERAL_STRING(PULL_VCARD_ENTRY_REQ_ID),
NS_LITERAL_STRING(KEY_ADAPTER),
data);
#endif
return ObexResponseCode::Success;
}
void
BluetoothPbapManager::AppendBtNamedValueByTagId(
const ObexHeaderSet& aHeader,
InfallibleTArray<BluetoothNamedValue>& aValues,
const AppParameterTag aTagId)
{
uint8_t buf[64];
switch (aTagId) {
case AppParameterTag::Order: {
if (!aHeader.GetAppParameter(AppParameterTag::Order, buf, 64)) {
break;
}
static const nsString sOrderStr[] = {NS_LITERAL_STRING("alphanumeric"),
NS_LITERAL_STRING("indexed"),
NS_LITERAL_STRING("phonetical")};
uint8_t order = buf[0];
if (order < MOZ_ARRAY_LENGTH(sOrderStr)) {
BT_APPEND_NAMED_VALUE(aValues, "order", sOrderStr[order]);
} else {
BT_WARNING("%s: Unexpected value '%d' of 'Order'", __FUNCTION__, order);
}
break;
}
case AppParameterTag::SearchValue: {
if (!aHeader.GetAppParameter(AppParameterTag::SearchValue, buf, 64)) {
break;
}
// Section 5.3.4.3 "SearchValue {<text string>}", PBAP 1.2
// The UTF-8 character set shall be used for <text string>.
// Use nsCString to store UTF-8 string here to follow the suggestion of
// 'MDN:Internal_strings'.
nsCString text((char *) buf);
BT_APPEND_NAMED_VALUE(aValues, "searchText", text);
break;
}
case AppParameterTag::SearchProperty: {
if (!aHeader.GetAppParameter(AppParameterTag::SearchProperty, buf, 64)) {
break;
}
static const nsString sSearchKeyStr[] = {NS_LITERAL_STRING("name"),
NS_LITERAL_STRING("number"),
NS_LITERAL_STRING("sound")};
uint8_t searchKey = buf[0];
if (searchKey < MOZ_ARRAY_LENGTH(sSearchKeyStr)) {
BT_APPEND_NAMED_VALUE(aValues, "searchKey", sSearchKeyStr[searchKey]);
} else {
BT_WARNING("%s: Unexpected value '%d' of 'SearchProperty'",
__FUNCTION__, searchKey);
}
break;
}
case AppParameterTag::MaxListCount: {
if (!aHeader.GetAppParameter(AppParameterTag::MaxListCount, buf, 64)) {
break;
}
uint16_t maxListCount = *((uint16_t *)buf);
// convert big endian to little endian
maxListCount = (maxListCount >> 8) | (maxListCount << 8);
BT_APPEND_NAMED_VALUE(aValues, "maxListCount", (uint32_t) maxListCount);
break;
}
case AppParameterTag::ListStartOffset: {
if (!aHeader.GetAppParameter(AppParameterTag::ListStartOffset, buf, 64)) {
break;
}
uint16_t listStartOffset = *((uint16_t *)buf);
// convert big endian to little endian
listStartOffset = (listStartOffset >> 8) | (listStartOffset << 8);
BT_APPEND_NAMED_VALUE(aValues, "listStartOffset",
(uint32_t) listStartOffset);
break;
}
case AppParameterTag::PropertySelector: {
if (!aHeader.GetAppParameter(
AppParameterTag::PropertySelector, buf, 64)) {
break;
}
InfallibleTArray<uint32_t> props = PackPropertiesMask(buf, 64);
BT_APPEND_NAMED_VALUE(aValues, "propSelector", props);
break;
}
case AppParameterTag::Format: {
if (!aHeader.GetAppParameter(AppParameterTag::Format, buf, 64)) {
break;
}
bool usevCard3 = buf[0];
BT_APPEND_NAMED_VALUE(aValues, "format", usevCard3);
break;
}
case AppParameterTag::vCardSelector: {
if (!aHeader.GetAppParameter(AppParameterTag::vCardSelector, buf, 64)) {
break;
}
InfallibleTArray<uint32_t> props = PackPropertiesMask(buf, 64);
bool hasVCardSelectorOperator = aHeader.GetAppParameter(
AppParameterTag::vCardSelectorOperator, buf, 64);
if (hasVCardSelectorOperator && buf[0]) {
BT_APPEND_NAMED_VALUE(aValues, "vCardSelector_AND",
BluetoothValue(props));
} else {
BT_APPEND_NAMED_VALUE(aValues, "vCardSelector_OR",
BluetoothValue(props));
}
break;
}
default:
BT_LOGR("Unsupported AppParameterTag: %x", aTagId);
break;
}
}
bool
BluetoothPbapManager::IsLegalPath(const nsAString& aPath)
{
@ -460,6 +725,53 @@ BluetoothPbapManager::ReplyToSetPath()
SendObexData(req, ObexResponseCode::Success, index);
}
InfallibleTArray<uint32_t>
BluetoothPbapManager::PackPropertiesMask(uint8_t* aData, int aSize)
{
InfallibleTArray<uint32_t> propSelector;
// Table 5.1 "Property Mask", PBAP 1.2
// PropertyMask is a 64-bit mask that indicates the properties contained in
// the requested vCard objects. We only support bit 0~31 since the rest are
// reserved for future use or vendor specific properties.
// convert big endian to little endian
uint32_t x = (aData[7] << 0) | (aData[6] << 8) |
(aData[5] << 16) | (aData[4] << 24);
uint32_t count = 0;
while (!x) {
if (x & 1) {
propSelector.AppendElement(count);
}
++count;
x >>= 1;
}
return propSelector;
}
void
BluetoothPbapManager::ReplyToPullPhonebook(Blob* aBlob, uint16_t aPhonebookSize)
{
// TODO: Implement this function (Bug 1180556)
}
void
BluetoothPbapManager::ReplyToPullvCardListing(
Blob* aBlob,
uint16_t aPhonebookSize)
{
// TODO: Implement this function (Bug 1180556)
}
void
BluetoothPbapManager::ReplyToPullvCardEntry(Blob* aBlob)
{
// TODO: Implement this function (Bug 1180556)
}
void
BluetoothPbapManager::ReplyError(uint8_t aError)
{

View File

@ -10,8 +10,15 @@
#include "BluetoothCommon.h"
#include "BluetoothProfileManagerBase.h"
#include "BluetoothSocketObserver.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
#include "mozilla/ipc/SocketBase.h"
namespace mozilla {
namespace dom {
class Blob;
}
}
BEGIN_BLUETOOTH_NAMESPACE
/*
@ -27,6 +34,7 @@ enum AppParameterTag {
Format = 0x07,
PhonebookSize = 0x08,
NewMissedCalls = 0x09,
// ----- enumerators below are supported since PBAP 1.2 ----- //
PrimaryVersionCounter = 0x0A,
SecondaryVersionCounter = 0x0B,
vCardSelector = 0x0C,
@ -40,7 +48,7 @@ class BluetoothSocket;
class ObexHeaderSet;
class BluetoothPbapManager : public BluetoothSocketObserver
, public BluetoothProfileManagerBase
, public BluetoothProfileManagerBase
{
public:
BT_DECL_PROFILE_MGR_BASE
@ -54,6 +62,9 @@ public:
static BluetoothPbapManager* Get();
bool Listen();
void ReplyToPullPhonebook(Blob* aBlob, uint16_t aPhonebookSize);
void ReplyToPullvCardListing(Blob* aBlob, uint16_t aPhonebookSize);
void ReplyToPullvCardEntry(Blob* aBlob);
protected:
virtual ~BluetoothPbapManager();
@ -70,6 +81,15 @@ private:
void SendObexData(uint8_t* aData, uint8_t aOpcode, int aSize);
uint8_t SetPhoneBookPath(uint8_t flags, const ObexHeaderSet& aHeader);
uint8_t PullPhonebook(const ObexHeaderSet& aHeader);
uint8_t PullvCardListing(const ObexHeaderSet& aHeader);
uint8_t PullvCardEntry(const ObexHeaderSet& aHeader);
void AppendBtNamedValueByTagId(
const ObexHeaderSet& aHeader,
InfallibleTArray<BluetoothNamedValue>& aValues,
const AppParameterTag aTagId);
InfallibleTArray<uint32_t> PackPropertiesMask(uint8_t* aData, int aSize);
bool CompareHeaderTarget(const ObexHeaderSet& aHeader);
bool IsLegalPath(const nsAString& aPath);
void AfterPbapConnected();

View File

@ -16,7 +16,10 @@
#include "mozilla/dom/BluetoothAdapterBinding.h"
#include "mozilla/dom/BluetoothAttributeEvent.h"
#include "mozilla/dom/BluetoothPhonebookPullingEvent.h"
#include "mozilla/dom/BluetoothStatusChangedEvent.h"
#include "mozilla/dom/BluetoothVCardListingEvent.h"
#include "mozilla/dom/BluetoothVCardPullingEvent.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/Event.h"
#include "mozilla/dom/File.h"
@ -524,6 +527,12 @@ BluetoothAdapter::Notify(const BluetoothSignal& aData)
} else if (aData.name().EqualsLiteral(PAIRING_ABORTED_ID) ||
aData.name().EqualsLiteral(REQUEST_MEDIA_PLAYSTATUS_ID)) {
DispatchEmptyEvent(aData.name());
} else if (aData.name().EqualsLiteral(PULL_PHONEBOOK_REQ_ID)) {
HandlePullPhonebookReq(aData.value());
} else if (aData.name().EqualsLiteral(PULL_VCARD_ENTRY_REQ_ID)) {
HandlePullVCardEntryReq(aData.value());
} else if (aData.name().EqualsLiteral(PULL_VCARD_LISTING_REQ_ID)) {
HandlePullVCardListingReq(aData.value());
} else {
BT_WARNING("Not handling adapter signal: %s",
NS_ConvertUTF16toUTF8(aData.name()).get());
@ -1190,6 +1199,172 @@ BluetoothAdapter::HandleDeviceUnpaired(const BluetoothValue& aValue)
DispatchDeviceEvent(NS_LITERAL_STRING(DEVICE_UNPAIRED_ID), init);
}
void
BluetoothAdapter::HandlePullPhonebookReq(const BluetoothValue& aValue)
{
MOZ_ASSERT(aValue.type() == BluetoothValue::TArrayOfBluetoothNamedValue);
const InfallibleTArray<BluetoothNamedValue>& arr =
aValue.get_ArrayOfBluetoothNamedValue();
MOZ_ASSERT(arr.Length() >= 1 &&
arr[0].value().type() == BluetoothValue::TnsString);
BluetoothPhonebookPullingEventInit init;
for (uint32_t i = 0, propCount = arr.Length(); i < propCount; ++i) {
const nsString& name = arr[i].name();
const BluetoothValue& value = arr[i].value();
if (name.EqualsLiteral("name")) {
init.mName = value.get_nsString();
} else if (name.EqualsLiteral("format")) {
init.mFormat = value.get_bool() ? vCardVersion::VCard30
: vCardVersion::VCard21;
} else if (name.EqualsLiteral("propSelector")) {
init.mPropSelector = getVCardProperties(value);
} else if (name.EqualsLiteral("maxListCount")) {
init.mMaxListCount = value.get_uint32_t();
} else if (name.EqualsLiteral("listStartOffset")) {
init.mListStartOffset = value.get_uint32_t();
} else if (name.EqualsLiteral("vCardSelector_AND")) {
init.mVcardSelector = getVCardProperties(value);
init.mVcardSelectorOperator = vCardSelectorOp::AND;
} else if (name.EqualsLiteral("vCardSelector_OR")) {
init.mVcardSelector = getVCardProperties(value);
init.mVcardSelectorOperator = vCardSelectorOp::OR;
}
}
nsRefPtr<BluetoothPhonebookPullingEvent> event =
BluetoothPhonebookPullingEvent::Constructor(this,
NS_LITERAL_STRING(PULL_PHONEBOOK_REQ_ID), init);
DispatchTrustedEvent(event);
}
void
BluetoothAdapter::HandlePullVCardEntryReq(const BluetoothValue& aValue)
{
MOZ_ASSERT(aValue.type() == BluetoothValue::TArrayOfBluetoothNamedValue);
const InfallibleTArray<BluetoothNamedValue>& arr =
aValue.get_ArrayOfBluetoothNamedValue();
MOZ_ASSERT(arr.Length() >= 1 &&
arr[0].value().type() == BluetoothValue::TnsString);
BluetoothVCardPullingEventInit init;
Sequence<vCardProperties> propSelector;
for (uint32_t i = 0, propCount = arr.Length(); i < propCount; ++i) {
const nsString& name = arr[i].name();
const BluetoothValue& value = arr[i].value();
if (name.EqualsLiteral("name")) {
init.mName = value.get_nsString();
} else if (name.EqualsLiteral("format")) {
init.mFormat = value.get_bool() ? vCardVersion::VCard30
: vCardVersion::VCard21;
} else if (name.EqualsLiteral("propSelector")) {
init.mPropSelector = getVCardProperties(value);
}
}
nsRefPtr<BluetoothVCardPullingEvent> event =
BluetoothVCardPullingEvent::Constructor(this,
NS_LITERAL_STRING(PULL_VCARD_ENTRY_REQ_ID), init);
DispatchTrustedEvent(event);
}
void
BluetoothAdapter::HandlePullVCardListingReq(const BluetoothValue& aValue)
{
MOZ_ASSERT(aValue.type() == BluetoothValue::TArrayOfBluetoothNamedValue);
const InfallibleTArray<BluetoothNamedValue>& arr =
aValue.get_ArrayOfBluetoothNamedValue();
MOZ_ASSERT(arr.Length() >= 1 &&
arr[0].value().type() == BluetoothValue::TnsString);
BluetoothVCardListingEventInit init;
for (uint32_t i = 0, propCount = arr.Length(); i < propCount; ++i) {
const nsString& name = arr[i].name();
const BluetoothValue& value = arr[i].value();
if (name.EqualsLiteral("name")) {
init.mName = value.get_nsString();
} else if (name.EqualsLiteral("order")) {
init.mOrder = ConvertStringToVCardOrderType(value.get_nsString());
} else if (name.EqualsLiteral("searchText")) {
init.mSearchValue = value.get_nsString();
} else if (name.EqualsLiteral("searchKey")) {
init.mSearchKey = ConvertStringToVCardSearchKeyType(value.get_nsString());
} else if (name.EqualsLiteral("maxListCount")) {
init.mMaxListCount = value.get_uint32_t();
} else if (name.EqualsLiteral("listStartOffset")) {
init.mListStartOffset = value.get_uint32_t();
} else if (name.EqualsLiteral("vCardSelector_AND")) {
init.mVcardSelector = getVCardProperties(value);
init.mVcardSelectorOperator = vCardSelectorOp::AND;
} else if (name.EqualsLiteral("vCardSelector_OR")) {
init.mVcardSelector = getVCardProperties(value);
init.mVcardSelectorOperator = vCardSelectorOp::OR;
}
}
nsRefPtr<BluetoothVCardListingEvent> event =
BluetoothVCardListingEvent::Constructor(this,
NS_LITERAL_STRING(PULL_VCARD_LISTING_REQ_ID), init);
DispatchTrustedEvent(event);
}
Sequence<vCardProperties>
BluetoothAdapter::getVCardProperties(const BluetoothValue &aValue)
{
MOZ_ASSERT(aValue.type() == BluetoothValue::TArrayOfuint32_t);
Sequence<vCardProperties> propSelector;
const InfallibleTArray<uint32_t>& propSelectorArr =
aValue.get_ArrayOfuint32_t();
for (uint32_t i = 0; i < propSelectorArr.Length(); ++i) {
propSelector.AppendElement(
static_cast<vCardProperties>(propSelectorArr[i]), mozilla::fallible);
}
return propSelector;
}
vCardOrderType
BluetoothAdapter::ConvertStringToVCardOrderType(const nsAString& aString)
{
using namespace mozilla::dom::vCardOrderTypeValues;
for (size_t index = 0; index < ArrayLength(strings) - 1; index++) {
if (aString.LowerCaseEqualsASCII(strings[index].value,
strings[index].length)) {
return static_cast<vCardOrderType>(index);
}
}
BT_WARNING("Treat the unexpected string '%s' as vCardOrderType::Indexed",
NS_ConvertUTF16toUTF8(aString).get());
return vCardOrderType::Indexed; // The default value is 'Indexed'.
}
vCardSearchKeyType
BluetoothAdapter::ConvertStringToVCardSearchKeyType(const nsAString& aString)
{
using namespace mozilla::dom::vCardSearchKeyTypeValues;
for (size_t index = 0; index < ArrayLength(strings) - 1; index++) {
if (aString.LowerCaseEqualsASCII(strings[index].value,
strings[index].length)) {
return static_cast<vCardSearchKeyType>(index);
}
}
BT_WARNING("Treat the unexpected string '%s' as vCardSearchKeyType::Name",
NS_ConvertUTF16toUTF8(aString).get());
return vCardSearchKeyType::Name; // The default value is 'Name'.
}
void
BluetoothAdapter::DispatchAttributeEvent(const Sequence<nsString>& aTypes)
{

View File

@ -12,6 +12,7 @@
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/dom/BluetoothAdapterBinding.h"
#include "mozilla/dom/BluetoothDeviceEvent.h"
#include "mozilla/dom/BluetoothPbapParametersBinding.h"
#include "mozilla/dom/Promise.h"
#include "nsCOMPtr.h"
@ -89,6 +90,9 @@ public:
IMPL_EVENT_HANDLER(pairingaborted);
IMPL_EVENT_HANDLER(a2dpstatuschanged);
IMPL_EVENT_HANDLER(hfpstatuschanged);
IMPL_EVENT_HANDLER(pullphonebookreq);
IMPL_EVENT_HANDLER(pullvcardentryreq);
IMPL_EVENT_HANDLER(pullvcardlistingreq);
IMPL_EVENT_HANDLER(requestmediaplaystatus);
IMPL_EVENT_HANDLER(scostatuschanged);
@ -286,6 +290,73 @@ private:
*/
void HandleLeDeviceFound(const BluetoothValue& aValue);
/**
* Handle PULL_PHONEBOOK_REQ_ID bluetooth signal.
*
* @param aValue [in] Properties array of the PBAP request.
* The array should contain few properties:
* - nsString 'name'
* - bool 'format'
* - uint32_t[] 'propSelector'
* - uint32_t 'maxListCount'
* - uint32_t 'listStartOffset'
* - uint32_t[] 'vCardSelector_AND'
* - uint32_t[] 'vCardSelector_AND'
*/
void HandlePullPhonebookReq(const BluetoothValue& aValue);
/**
* Handle PULL_VCARD_ENTRY_REQ_ID bluetooth signal.
*
* @param aValue [in] Properties array of the PBAP request.
* The array should contain few properties:
* - nsString 'name'
* - bool 'format'
* - uint32_t[] 'propSelector'
*/
void HandlePullVCardEntryReq(const BluetoothValue& aValue);
/**
* Handle PULL_VCARD_LISTING_REQ_ID bluetooth signal.
*
* @param aValue [in] Properties array of the PBAP request.
* The array should contain few properties:
* - nsString 'name'
* - nsString 'order'
* - nsString 'searchText'
* - nsString 'searchKey'
* - uint32_t 'maxListCount'
* - uint32_t 'listStartOffset'
* - uint32_t[] 'vCardSelector_AND'
* - uint32_t[] 'vCardSelector_AND'
*/
void HandlePullVCardListingReq(const BluetoothValue& aValue);
/**
* Get a Sequence of vCard properies from a BluetoothValue. The name of
* BluetoothValue must be propSelector, vCardSelector_OR or vCardSelector_AND.
*
* @param aValue [in] a BluetoothValue with 'TArrayOfuint32_t' type
* The name of BluetoothValue must be 'propSelector',
* 'vCardSelector_OR' or 'vCardSelector_AND'.
*/
Sequence<vCardProperties> getVCardProperties(const BluetoothValue &aValue);
/**
* Convert string to vCardOrderType.
*
* @param aString [in] String to convert
*/
vCardOrderType ConvertStringToVCardOrderType(const nsAString& aString);
/**
* Convert string to vCardSearchKeyType.
*
* @param aString [in] String to convert
*/
vCardSearchKeyType ConvertStringToVCardSearchKeyType(
const nsAString& aString);
/**
* Fire BluetoothAttributeEvent to trigger onattributechanged event handler.
*

View File

@ -30,10 +30,12 @@ union BluetoothValue
{
int32_t;
uint32_t;
nsCString;
nsString;
bool;
nsString[];
uint8_t[];
uint32_t[];
BluetoothNamedValue[];
BluetoothGattId;
BluetoothGattId[];

View File

@ -13,6 +13,7 @@ if CONFIG['MOZ_B2G_BT']:
SOURCES += [
'BluetoothHidManager.cpp',
'BluetoothInterface.cpp',
'BluetoothPbapRequestHandle.cpp',
'BluetoothUtils.cpp',
'BluetoothUuid.cpp',
'ObexBase.cpp'
@ -144,7 +145,8 @@ EXPORTS.mozilla.dom.bluetooth += [
'bluetooth2/BluetoothManager.h',
'bluetooth2/BluetoothPairingHandle.h',
'bluetooth2/BluetoothPairingListener.h',
'BluetoothCommon.h'
'BluetoothCommon.h',
'BluetoothPbapRequestHandle.h',
]
IPDL_SOURCES += [
'bluetooth2/ipc/BluetoothTypes.ipdlh',

View File

@ -76,10 +76,22 @@ const kEventConstructors = {
return new BluetoothPairingEvent(aName, aProps);
},
},
BluetoothPhonebookPullingEvent: { create: function (aName, aProps) {
return new BluetoothPhonebookPullingEvent(aName, aProps);
},
},
BluetoothStatusChangedEvent: { create: function (aName, aProps) {
return new BluetoothStatusChangedEvent(aName, aProps);
},
},
BluetoothVCardListingEvent: { create: function (aName, aProps) {
return new BluetoothVCardListingEvent(aName, aProps);
},
},
BluetoothVCardPullingEvent: { create: function (aName, aProps) {
return new BluetoothVCardPullingEvent(aName, aProps);
},
},
CallEvent: { create: function (aName, aProps) {
return new CallEvent(aName, aProps);
},

View File

@ -216,13 +216,21 @@ var interfaceNamesInGlobalScope =
{name: "BluetoothLeDeviceEvent", b2g: true, permission: ["bluetooth"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BluetoothManager", b2g: true, permission: ["bluetooth"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BluetoothPbapRequestHandle", b2g: true, permission: ["bluetooth"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BluetoothPairingEvent", b2g: true, permission: ["bluetooth"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BluetoothPairingHandle", b2g: true, permission: ["bluetooth"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BluetoothPhonebookPullingEvent", b2g: true, permission: ["bluetooth"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BluetoothStatusChangedEvent", b2g: true,
permission: ["bluetooth"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BluetoothVCardListingEvent", b2g: true, permission: ["bluetooth"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BluetoothVCardPullingEvent", b2g: true, permission: ["bluetooth"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BoxObject", xbl: true},
// IMPORTANT: Do not change this list without review from a DOM peer!

View File

@ -69,6 +69,15 @@ interface BluetoothAdapter : EventTarget {
// Fired when remote devices query current media play status
attribute EventHandler onrequestmediaplaystatus;
// Fired when PBAP manager requests for 'pullphonebook'
attribute EventHandler onpullphonebookreq;
// Fired when PBAP manager requests for 'pullvcardentry'
attribute EventHandler onpullvcardentryreq;
// Fired when PBAP manager requests for 'pullvcardlisting'
attribute EventHandler onpullvcardlistingreq;
/**
* Enable/Disable a local bluetooth adapter by asynchronus methods and return
* its result through a Promise.

View File

@ -0,0 +1,81 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/.
*/
/**
* This enum holds the parameters to indicate the properties contained in the
* requested vCard objects.
*/
enum vCardProperties
{
"version",
"fn",
"n",
"photo",
"bday",
"adr",
"label",
"tel",
"email",
"mailer",
"tz",
"geo",
"title",
"role",
"logo",
"agent",
"org",
"note",
"rev",
"sound",
"url",
"uid",
"key",
"nickname",
"categories",
"proid",
"class",
"sort-string",
"x-irmc-call-datetime",
"x-bt-speeddialkey",
"x-bt-uci",
"x-bt-uid"
};
/**
* This enum holds the parameters to indicate the sorting order of vCard
* objects.
*/
enum vCardOrderType {
"alphabetical",
"indexed", // default
"phonetical"
};
/**
* This enum holds the parameters to indicate the search key of the search
* operation.
*/
enum vCardSearchKeyType {
"name", // default
"number",
"sound"
};
/**
* This enum holds the parameters to indicate the vCard version.
*/
enum vCardVersion {
"vCard21", // default
"vCard30"
};
/**
* This enum holds the parameters to indicate the type of vCard selector.
*/
enum vCardSelectorOp {
"OR", // default
"AND"
};

View File

@ -0,0 +1,33 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
[CheckAnyPermissions="bluetooth"]
interface BluetoothPbapRequestHandle
{
/**
* Reply vCard object to the PBAP request. The DOMRequest will get onerror
* callback if the PBAP request type is not 'pullvcardentryreq' or operation
* fails.
*/
[NewObject, Throws, AvailableIn=CertifiedApps]
DOMRequest replyTovCardPulling(Blob vcardObject);
/**
* Reply vCard object to the PBAP request. The DOMRequest will get onerror
* callback if the PBAP request type is not 'pullphonebookreq' or operation
* fails.
*/
[NewObject, Throws, AvailableIn=CertifiedApps]
DOMRequest replyToPhonebookPulling(Blob vcardObject,
unsigned long long phonebookSize);
/**
* Reply vCard object to the PBAP request. The DOMRequest will get onerror
* callback if the PBAP request type is not 'pullvcardlistingreq' or operation
* fails.
*/
[NewObject, Throws, AvailableIn=CertifiedApps]
DOMRequest replyTovCardListing(Blob vcardObject,
unsigned long long phonebookSize);
};

View File

@ -0,0 +1,36 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/.
*/
[CheckAnyPermissions="bluetooth",
Constructor(DOMString type,
optional BluetoothPhonebookPullingEventInit eventInitDict)]
interface BluetoothPhonebookPullingEvent : Event
{
readonly attribute DOMString name;
readonly attribute vCardVersion format;
[Cached, Constant]
readonly attribute sequence<vCardProperties> propSelector;
readonly attribute unsigned long maxListCount;
readonly attribute unsigned long listStartOffset;
[Cached, Constant]
readonly attribute sequence<vCardProperties> vcardSelector;
readonly attribute vCardSelectorOp vcardSelectorOperator;
readonly attribute BluetoothPbapRequestHandle? handle;
};
dictionary BluetoothPhonebookPullingEventInit : EventInit
{
DOMString name = "";
vCardVersion format = "vCard21";
sequence<vCardProperties> propSelector = [];
unsigned long maxListCount = 0;
unsigned long listStartOffset = 0;
sequence<vCardProperties> vcardSelector = [];
vCardSelectorOp vcardSelectorOperator = "OR";
BluetoothPbapRequestHandle? handle = null;
};

View File

@ -0,0 +1,37 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/.
*/
[CheckAnyPermissions="bluetooth",
Constructor(DOMString type,
optional BluetoothVCardListingEventInit eventInitDict)]
interface BluetoothVCardListingEvent : Event
{
readonly attribute DOMString name;
readonly attribute vCardOrderType order;
readonly attribute DOMString searchValue;
readonly attribute vCardSearchKeyType searchKey;
readonly attribute unsigned long maxListCount;
readonly attribute unsigned long listStartOffset;
[Cached, Constant]
readonly attribute sequence<vCardProperties> vcardSelector;
readonly attribute vCardSelectorOp vcardSelectorOperator;
readonly attribute BluetoothPbapRequestHandle? handle;
};
dictionary BluetoothVCardListingEventInit : EventInit
{
DOMString name = "";
vCardOrderType order = "indexed";
DOMString searchValue = "";
vCardSearchKeyType searchKey = "name";
unsigned long maxListCount = 0;
unsigned long listStartOffset = 0;
sequence<vCardProperties> vcardSelector = [];
vCardSelectorOp vcardSelectorOperator = "OR";
BluetoothPbapRequestHandle? handle = null;
};

View File

@ -0,0 +1,27 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/.
*/
[CheckAnyPermissions="bluetooth",
Constructor(DOMString type,
optional BluetoothVCardPullingEventInit eventInitDict)]
interface BluetoothVCardPullingEvent : Event
{
readonly attribute DOMString name;
readonly attribute vCardVersion format;
[Cached, Constant]
readonly attribute sequence<vCardProperties> propSelector;
readonly attribute BluetoothPbapRequestHandle? handle;
};
dictionary BluetoothVCardPullingEventInit : EventInit
{
DOMString name = "";
vCardVersion format = "vCard21";
sequence<vCardProperties> propSelector = [];
BluetoothPbapRequestHandle? handle = null;
};

View File

@ -684,6 +684,8 @@ if CONFIG['MOZ_B2G_BT']:
'BluetoothManager.webidl',
'BluetoothPairingHandle.webidl',
'BluetoothPairingListener.webidl',
'BluetoothPbapParameters.webidl',
'BluetoothPbapRequestHandle.webidl',
]
if CONFIG['MOZ_SIMPLEPUSH']:
@ -830,7 +832,10 @@ if CONFIG['MOZ_B2G_BT']:
'BluetoothDeviceEvent.webidl',
'BluetoothGattCharacteristicEvent.webidl',
'BluetoothPairingEvent.webidl',
'BluetoothPhonebookPullingEvent.webidl',
'BluetoothStatusChangedEvent.webidl',
'BluetoothVCardListingEvent.webidl',
'BluetoothVCardPullingEvent.webidl'
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':