Bug 1238842 - Add error codes to Gecko by following W3C spec. r=brsun

This commit is contained in:
Tom Tung 2016-02-24 17:56:22 +08:00
parent bbb42aacb6
commit 1f6dab0c61
10 changed files with 254 additions and 8 deletions

View File

@ -1124,7 +1124,10 @@ enum BluetoothGattStatus {
GATT_STATUS_INSUFFICIENT_ENCRYPTION,
GATT_STATUS_UNSUPPORTED_GROUP_TYPE,
GATT_STATUS_INSUFFICIENT_RESOURCES,
GATT_STATUS_UNKNOWN_ERROR
GATT_STATUS_UNKNOWN_ERROR,
GATT_STATUS_BEGIN_OF_APPLICATION_ERROR = 0x80,
GATT_STATUS_END_OF_APPLICATION_ERROR = 0x9f,
GATT_STATUS_END_OF_ERROR = 0x100
};
enum BluetoothGattAuthReq {

View File

@ -0,0 +1,117 @@
/* -*- 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 "BluetoothGattReplyRunnable.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
#include "mozilla/dom/Promise.h"
using namespace mozilla::dom;
USING_BLUETOOTH_NAMESPACE
BluetoothGattReplyRunnable::BluetoothGattReplyRunnable(Promise* aPromise)
: BluetoothReplyRunnable(nullptr, aPromise)
{
MOZ_ASSERT(aPromise);
}
void
BluetoothGattReplyRunnable::GattStatusToDOMStatus(
const BluetoothGattStatus aGattStatus, nsresult& aDOMStatus)
{
/**
* https://webbluetoothcg.github.io/web-bluetooth/#error-handling
*
* ToDo:
* If the procedure times out or the ATT Bearer is terminated for any
* reason, return |NS_ERROR_DOM_NETWORK_ERR|.
*/
// Error Code Mapping
if ((aGattStatus >= GATT_STATUS_BEGIN_OF_APPLICATION_ERROR) &&
(aGattStatus <= GATT_STATUS_END_OF_APPLICATION_ERROR) &&
IsWrite()) {
aDOMStatus = NS_ERROR_DOM_INVALID_MODIFICATION_ERR;
return;
}
switch (aGattStatus) {
case GATT_STATUS_INVALID_ATTRIBUTE_LENGTH:
aDOMStatus = NS_ERROR_DOM_INVALID_MODIFICATION_ERR;
break;
case GATT_STATUS_ATTRIBUTE_NOT_LONG:
/**
* ToDo:
* While receiving |GATT_STATUS_ATTRIBUTE_NOT_LONG|, we need to check
* whether 'Long' sub-procedure has been used or not.
* If we have used 'Long' sub-procedure, we need to retry the step
* without using 'Long' sub-procedure (e.g. Read Blob Request) based on
* W3C reuqirements. If it fails again due to the length of the value
* being written, convert the error status to
* |NS_ERROR_DOM_INVALID_MODIFICATION_ERR|.
* If 'Long' sub-procedure has not been used, convert the error status to
* |NS_ERROR_DOM_NOT_SUPPORTED_ERR|.
*/
aDOMStatus = NS_ERROR_DOM_INVALID_MODIFICATION_ERR;
break;
case GATT_STATUS_INSUFFICIENT_AUTHENTICATION:
case GATT_STATUS_INSUFFICIENT_ENCRYPTION:
case GATT_STATUS_INSUFFICIENT_ENCRYPTION_KEY_SIZE:
/**
* ToDo:
* In W3C requirement, UA SHOULD attempt to increase the security level
* of the connection while receiving those error statuses. If it fails or
* UA doesn't suuport return the |NS_ERROR_DOM_SECURITY_ERR|.
*
* Note: The Gecko have already attempted to increase the security level
* after receiving |GATT_STATUS_INSUFFICIENT_AUTHENTICATION| or
* |GATT_STATUS_INSUFFICIENT_ENCRYPTION|. Only need to handle
* |GATT_STATUS_INSUFFICIENT_ENCRYPTION_KEY_SIZE| in the future.
*/
aDOMStatus = NS_ERROR_DOM_SECURITY_ERR;
break;
case GATT_STATUS_INSUFFICIENT_AUTHORIZATION:
aDOMStatus = NS_ERROR_DOM_SECURITY_ERR;
break;
case GATT_STATUS_INVALID_HANDLE:
case GATT_STATUS_INVALID_PDU:
case GATT_STATUS_INVALID_OFFSET:
case GATT_STATUS_ATTRIBUTE_NOT_FOUND:
case GATT_STATUS_UNSUPPORTED_GROUP_TYPE:
case GATT_STATUS_READ_NOT_PERMITTED:
case GATT_STATUS_WRITE_NOT_PERMITTED:
case GATT_STATUS_REQUEST_NOT_SUPPORTED:
case GATT_STATUS_PREPARE_QUEUE_FULL:
case GATT_STATUS_INSUFFICIENT_RESOURCES:
case GATT_STATUS_UNLIKELY_ERROR:
default:
aDOMStatus = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
break;
}
}
nsresult
BluetoothGattReplyRunnable::FireErrorString()
{
MOZ_ASSERT(mReply);
if (!mPromise ||
mReply->type() != BluetoothReply::TBluetoothReplyError ||
mReply->get_BluetoothReplyError().errorStatus().type() !=
BluetoothErrorStatus::TBluetoothGattStatus) {
return BluetoothReplyRunnable::FireErrorString();
}
nsresult domStatus = NS_OK;
GattStatusToDOMStatus(
mReply->get_BluetoothReplyError().errorStatus().get_BluetoothGattStatus(),
domStatus);
nsresult rv = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM, domStatus);
mPromise->MaybeReject(rv);
return NS_OK;
}

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_BluetoothGattReplyRunnable_h
#define mozilla_dom_bluetooth_BluetoothGattReplyRunnable_h
#include "BluetoothReplyRunnable.h"
class nsIDOMDOMRequest;
namespace mozilla {
namespace dom {
class Promise;
}
}
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothReply;
class BluetoothGattReplyRunnable : public BluetoothReplyRunnable
{
public:
BluetoothGattReplyRunnable(Promise* aPromise);
protected:
virtual ~BluetoothGattReplyRunnable() {}
private:
virtual nsresult FireErrorString() override;
void GattStatusToDOMStatus(const BluetoothGattStatus aGattStatus,
nsresult& aDOMStatus);
virtual bool IsWrite()
{
return false;
}
};
class BluetoothGattVoidReplyRunnable : public BluetoothGattReplyRunnable
{
public:
BluetoothGattVoidReplyRunnable(Promise* aPromise)
: BluetoothGattReplyRunnable(aPromise) {}
~BluetoothGattVoidReplyRunnable() {}
protected:
virtual bool
ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue) override
{
aValue.setUndefined();
return true;
}
};
END_BLUETOOTH_NAMESPACE
#endif // mozilla_dom_bluetooth_BluetoothGattReplyRunnable_h

View File

@ -19,8 +19,8 @@ USING_BLUETOOTH_NAMESPACE
BluetoothReplyRunnable::BluetoothReplyRunnable(nsIDOMDOMRequest* aReq,
Promise* aPromise)
: mDOMRequest(aReq)
, mPromise(aPromise)
: mPromise(aPromise)
, mDOMRequest(aReq)
, mErrorStatus(STATUS_FAIL)
{}
@ -97,8 +97,7 @@ BluetoothReplyRunnable::Run()
nsresult rv;
if (mReply->type() != BluetoothReply::TBluetoothReplySuccess) {
SetError(mReply->get_BluetoothReplyError().errorString(),
mReply->get_BluetoothReplyError().errorStatus());
ParseErrorStatus();
rv = FireErrorString();
} else if (!ParseSuccessfulReply(&v)) {
rv = FireErrorString();
@ -129,6 +128,22 @@ void
BluetoothReplyRunnable::OnErrorFired()
{}
void
BluetoothReplyRunnable::ParseErrorStatus()
{
MOZ_ASSERT(mReply);
MOZ_ASSERT(mReply->type() == BluetoothReply::TBluetoothReplyError);
if (mReply->get_BluetoothReplyError().errorStatus().type() ==
BluetoothErrorStatus::TBluetoothStatus) {
SetError(
mReply->get_BluetoothReplyError().errorString(),
mReply->get_BluetoothReplyError().errorStatus().get_BluetoothStatus());
} else {
SetError(mReply->get_BluetoothReplyError().errorString(), STATUS_FAIL);
}
}
BluetoothVoidReplyRunnable::BluetoothVoidReplyRunnable(nsIDOMDOMRequest* aReq,
Promise* aPromise)
: BluetoothReplyRunnable(aReq, aPromise)

View File

@ -48,14 +48,19 @@ protected:
virtual bool ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue) = 0;
virtual nsresult FireErrorString();
// 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;
RefPtr<Promise> mPromise;
private:
virtual void ParseErrorStatus();
nsresult FireReplySuccess(JS::Handle<JS::Value> aVal);
nsresult FireErrorString();
virtual void OnSuccessFired();
virtual void OnErrorFired();
@ -69,7 +74,6 @@ private:
* TODO: remove mDOMRequest once all methods adopt Promise.
*/
nsCOMPtr<nsIDOMDOMRequest> mDOMRequest;
RefPtr<Promise> mPromise;
BluetoothStatus mErrorStatus;
nsString mErrorString;

View File

@ -812,6 +812,20 @@ DispatchReplyError(BluetoothReplyRunnable* aRunnable,
NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(aRunnable)));
}
void
DispatchReplyError(BluetoothReplyRunnable* aRunnable,
const enum BluetoothGattStatus aGattStatus)
{
MOZ_ASSERT(aRunnable);
// Reply will be deleted by the runnable after running on main thread
BluetoothReply* reply =
new BluetoothReply(BluetoothReplyError(aGattStatus, EmptyString()));
aRunnable->SetReply(reply);
NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(aRunnable)));
}
void
DispatchStatusChangedEvent(const nsAString& aType,
const BluetoothAddress& aAddress,

View File

@ -379,6 +379,20 @@ void
DispatchReplyError(BluetoothReplyRunnable* aRunnable,
const enum BluetoothStatus aStatus);
/**
* Dispatch failed bluetooth reply with error bluetooth gatt status and
* string.
*
* This function is for bluetooth to return Promise as the error status is
* bluetooth gatt status.
*
* @param aRunnable the runnable to reply bluetooth request.
* @param aGattStatus the bluettoh gatt error status to reply failed request.
*/
void
DispatchReplyError(BluetoothReplyRunnable* aRunnable,
const enum BluetoothGattStatus aGattStatus);
void
DispatchStatusChangedEvent(const nsAString& aType,
const BluetoothAddress& aDeviceAddress,

View File

@ -367,6 +367,14 @@ struct ParamTraits<mozilla::dom::bluetooth::BluetoothGattAdvertisingData>
}
};
template <>
struct ParamTraits<mozilla::dom::bluetooth::BluetoothGattStatus>
: public ContiguousEnumSerializer<
mozilla::dom::bluetooth::BluetoothGattStatus,
mozilla::dom::bluetooth::GATT_STATUS_SUCCESS,
mozilla::dom::bluetooth::GATT_STATUS_END_OF_ERROR>
{ };
} // namespace IPC
#endif // mozilla_dom_bluetooth_ipc_BluetoothMessageUtils_h

View File

@ -20,6 +20,8 @@ using mozilla::dom::bluetooth::BluetoothGattResponse
from "mozilla/dom/bluetooth/BluetoothCommon.h";
using mozilla::dom::bluetooth::BluetoothGattServiceId
from "mozilla/dom/bluetooth/BluetoothCommon.h";
using mozilla::dom::bluetooth::BluetoothGattStatus
from "mozilla/dom/bluetooth/BluetoothCommon.h";
using mozilla::dom::bluetooth::BluetoothGattWriteType
from "mozilla/dom/bluetooth/BluetoothCommon.h";
using mozilla::dom::bluetooth::BluetoothRemoteName
@ -86,9 +88,15 @@ struct BluetoothReplySuccess
BluetoothValue value;
};
union BluetoothErrorStatus
{
BluetoothStatus;
BluetoothGattStatus;
};
struct BluetoothReplyError
{
BluetoothStatus errorStatus;
BluetoothErrorStatus errorStatus;
nsString errorString;
};

View File

@ -16,6 +16,7 @@ if CONFIG['MOZ_B2G_BT']:
]
SOURCES += [
'common/BluetoothGattReplyRunnable.cpp',
'common/BluetoothHidManager.cpp',
'common/BluetoothInterface.cpp',
'common/BluetoothProfileController.cpp',