Merge b2g-inbound to m-c a=merge CLOSED TREE

This commit is contained in:
Wes Kocher 2015-03-03 17:02:21 -08:00
commit a64b305a76
29 changed files with 884 additions and 312 deletions

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4352d56f8c79a51eb44e43658472236a38d6f1d8"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="3fc0ac309f5fb0c1fe82c12223b955a4efce27e6"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2e85143db5d5f6edc4c2b97263c02b558fee757e"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -128,7 +128,7 @@
<!-- Stock Android things -->
<project name="platform/external/icu4c" path="external/icu4c" revision="2bb01561780583cc37bc667f0ea79f48a122d8a2"/>
<!-- dolphin specific things -->
<project name="device/sprd" path="device/sprd" revision="8609ba49ab518822691528312b9c87b656164c58"/>
<project name="device/sprd" path="device/sprd" revision="e37e2ab9e0ac5fd78607cbbe3505f9a0a40d7a14"/>
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="4e58336019b5cbcfd134caf55b142236cf986618"/>
<project name="platform/frameworks/av" path="frameworks/av" revision="4387fe988e5a1001f29ce05fcfda03ed2d32137b"/>
<project name="platform/hardware/akm" path="hardware/akm" revision="6d3be412647b0eab0adff8a2768736cf4eb68039"/>
@ -138,7 +138,7 @@
<project name="platform/system/core" path="system/core" revision="53d584d4a4b4316e4de9ee5f210d662f89b44e7e"/>
<project name="u-boot" path="u-boot" revision="f1502910977ac88f43da7bf9277c3523ad4b0b2f"/>
<project name="vendor/sprd/gps" path="vendor/sprd/gps" revision="6974f8e771d4d8e910357a6739ab124768891e8f"/>
<project name="vendor/sprd/open-source" path="vendor/sprd/open-source" revision="39b3ad41158f71d41b549b31e30a8a63518f7362"/>
<project name="vendor/sprd/open-source" path="vendor/sprd/open-source" revision="cce8a36e1ec3d136f5eb8ec4b767d9c6ef08c427"/>
<project name="vendor/sprd/partner" path="vendor/sprd/partner" revision="8649c7145972251af11b0639997edfecabfc7c2e"/>
<project name="vendor/sprd/proprietories" path="vendor/sprd/proprietories" revision="d2466593022f7078aaaf69026adf3367c2adb7bb"/>
</manifest>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4352d56f8c79a51eb44e43658472236a38d6f1d8"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="3fc0ac309f5fb0c1fe82c12223b955a4efce27e6"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2e85143db5d5f6edc4c2b97263c02b558fee757e"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4352d56f8c79a51eb44e43658472236a38d6f1d8"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="3fc0ac309f5fb0c1fe82c12223b955a4efce27e6"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2e85143db5d5f6edc4c2b97263c02b558fee757e"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a1ddea3133e0807350326cee5dcf0d06fad00c08"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4352d56f8c79a51eb44e43658472236a38d6f1d8"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="3fc0ac309f5fb0c1fe82c12223b955a4efce27e6"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2e85143db5d5f6edc4c2b97263c02b558fee757e"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="52775e03a2d8532429dff579cb2cd56718e488c3">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4352d56f8c79a51eb44e43658472236a38d6f1d8"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="3fc0ac309f5fb0c1fe82c12223b955a4efce27e6"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2e85143db5d5f6edc4c2b97263c02b558fee757e"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4352d56f8c79a51eb44e43658472236a38d6f1d8"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="3fc0ac309f5fb0c1fe82c12223b955a4efce27e6"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2e85143db5d5f6edc4c2b97263c02b558fee757e"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4352d56f8c79a51eb44e43658472236a38d6f1d8"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="3fc0ac309f5fb0c1fe82c12223b955a4efce27e6"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2e85143db5d5f6edc4c2b97263c02b558fee757e"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4352d56f8c79a51eb44e43658472236a38d6f1d8"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="3fc0ac309f5fb0c1fe82c12223b955a4efce27e6"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2e85143db5d5f6edc4c2b97263c02b558fee757e"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a1ddea3133e0807350326cee5dcf0d06fad00c08"/>

View File

@ -1,9 +1,9 @@
{
"git": {
"git_revision": "4352d56f8c79a51eb44e43658472236a38d6f1d8",
"git_revision": "3fc0ac309f5fb0c1fe82c12223b955a4efce27e6",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
"revision": "a414e3396742a2e623feda0ba9ed654f6cd525d5",
"revision": "9e03b76f6b75d6fe3c3bccc9ae5eb104d3530c96",
"repo_path": "integration/gaia-central"
}

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4352d56f8c79a51eb44e43658472236a38d6f1d8"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="3fc0ac309f5fb0c1fe82c12223b955a4efce27e6"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2e85143db5d5f6edc4c2b97263c02b558fee757e"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a1ddea3133e0807350326cee5dcf0d06fad00c08"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="52775e03a2d8532429dff579cb2cd56718e488c3">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4352d56f8c79a51eb44e43658472236a38d6f1d8"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="3fc0ac309f5fb0c1fe82c12223b955a4efce27e6"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2e85143db5d5f6edc4c2b97263c02b558fee757e"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -317,6 +317,7 @@ PK11_DigestOp
PK11_DoesMechanism
PK11_Encrypt
PK11_ExportDERPrivateKeyInfo
PK11_ExportEncryptedPrivKeyInfo
PK11_ExtractKeyValue
PK11_FindCertFromNickname
PK11_FindCertsFromEmailAddress
@ -512,6 +513,7 @@ SECKEY_CopyPublicKey
SECKEY_CopySubjectPublicKeyInfo
SECKEY_CreateSubjectPublicKeyInfo
SECKEY_DecodeDERSubjectPublicKeyInfo
SECKEY_DestroyEncryptedPrivateKeyInfo
SECKEY_DestroyPrivateKey
SECKEY_DestroyPrivateKeyList
SECKEY_DestroyPublicKey
@ -589,6 +591,7 @@ SEC_PKCS12DecoderFinish
SEC_PKCS12DecoderImportBags
SEC_PKCS12DecoderIterateInit
SEC_PKCS12DecoderIterateNext
SEC_PKCS12DecoderRenameCertNicknames
SEC_PKCS12DecoderStart
SEC_PKCS12DecoderUpdate
SEC_PKCS12DecoderValidateBags

View File

@ -893,9 +893,10 @@ BluetoothAdapter::HandleDevicePaired(const BluetoothValue& aValue)
const InfallibleTArray<BluetoothNamedValue>& arr =
aValue.get_ArrayOfBluetoothNamedValue();
MOZ_ASSERT(arr.Length() == 2 &&
MOZ_ASSERT(arr.Length() == 3 &&
arr[0].value().type() == BluetoothValue::TnsString && // Address
arr[1].value().type() == BluetoothValue::Tbool); // Paired
arr[1].value().type() == BluetoothValue::Tbool && // Paired
arr[2].value().type() == BluetoothValue::TnsString); // Name
MOZ_ASSERT(!arr[0].value().get_nsString().IsEmpty() &&
arr[1].value().get_bool());

View File

@ -84,6 +84,14 @@ extern bool gBluetoothDebugFlag;
array.AppendElement(BluetoothNamedValue(NS_LITERAL_STRING(name), \
BluetoothValue(value)))
/**
* Wrap literal name and value into a BluetoothNamedValue
* and insert it to the array.
*/
#define BT_INSERT_NAMED_VALUE(array, index, name, value) \
array.InsertElementAt(index, BluetoothNamedValue(NS_LITERAL_STRING(name), \
BluetoothValue(value)))
/**
* Ensure success of system message broadcast with void return.
*/

View File

@ -115,8 +115,7 @@ BluetoothProfileController::AddProfileWithServiceClass(
profile = BluetoothHidManager::Get();
break;
default:
DispatchBluetoothReply(mRunnable, BluetoothValue(),
NS_LITERAL_STRING(ERR_UNKNOWN_PROFILE));
DispatchReplyError(mRunnable, NS_LITERAL_STRING(ERR_UNKNOWN_PROFILE));
mCallback();
return;
}
@ -129,8 +128,7 @@ BluetoothProfileController::AddProfile(BluetoothProfileManagerBase* aProfile,
bool aCheckConnected)
{
if (!aProfile) {
DispatchBluetoothReply(mRunnable, BluetoothValue(),
NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
DispatchReplyError(mRunnable, NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
mCallback();
return;
}
@ -255,13 +253,11 @@ BluetoothProfileController::EndSession()
// The action has completed, so the DOM request should be replied then invoke
// the callback.
if (mSuccess) {
DispatchBluetoothReply(mRunnable, BluetoothValue(true), EmptyString());
DispatchReplySuccess(mRunnable);
} else if (mConnect) {
DispatchBluetoothReply(mRunnable, BluetoothValue(true),
NS_LITERAL_STRING(ERR_CONNECTION_FAILED));
DispatchReplyError(mRunnable, NS_LITERAL_STRING(ERR_CONNECTION_FAILED));
} else {
DispatchBluetoothReply(mRunnable, BluetoothValue(true),
NS_LITERAL_STRING(ERR_DISCONNECTION_FAILED));
DispatchReplyError(mRunnable, NS_LITERAL_STRING(ERR_DISCONNECTION_FAILED));
}
mCallback();

View File

@ -64,6 +64,9 @@ StringToUuid(const char* aString, BluetoothUuid& aUuid)
memcpy(&aUuid.mUuid[14], &uuid5, sizeof(uint16_t));
}
/**
* |SetJsObject| is an internal function used by |BroadcastSystemMessage| only
*/
bool
SetJsObject(JSContext* aContext,
const BluetoothValue& aValue,
@ -119,7 +122,7 @@ BroadcastSystemMessage(const nsAString& aType,
const BluetoothValue& aData)
{
mozilla::AutoSafeJSContext cx;
NS_ASSERTION(!::JS_IsExceptionPending(cx),
MOZ_ASSERT(!::JS_IsExceptionPending(cx),
"Shouldn't get here when an exception is pending!");
nsCOMPtr<nsISystemMessagesInternal> systemMessenger =
@ -160,7 +163,7 @@ BroadcastSystemMessage(const nsAString& aType,
const InfallibleTArray<BluetoothNamedValue>& aData)
{
mozilla::AutoSafeJSContext cx;
NS_ASSERTION(!::JS_IsExceptionPending(cx),
MOZ_ASSERT(!::JS_IsExceptionPending(cx),
"Shouldn't get here when an exception is pending!");
JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
@ -186,44 +189,50 @@ BroadcastSystemMessage(const nsAString& aType,
}
void
DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable,
const BluetoothValue& aValue,
const nsAString& aErrorStr)
DispatchReplySuccess(BluetoothReplyRunnable* aRunnable)
{
// Reply will be deleted by the runnable after running on main thread
BluetoothReply* reply;
if (!aErrorStr.IsEmpty()) {
nsString err(aErrorStr);
reply = new BluetoothReply(BluetoothReplyError(STATUS_FAIL, err));
} else {
MOZ_ASSERT(aValue.type() != BluetoothValue::T__None);
reply = new BluetoothReply(BluetoothReplySuccess(aValue));
}
aRunnable->SetReply(reply);
if (NS_FAILED(NS_DispatchToMainThread(aRunnable))) {
BT_WARNING("Failed to dispatch to main thread!");
}
DispatchReplySuccess(aRunnable, BluetoothValue(true));
}
void
DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable,
const BluetoothValue& aValue,
const enum BluetoothStatus aStatusCode)
DispatchReplySuccess(BluetoothReplyRunnable* aRunnable,
const BluetoothValue& aValue)
{
// Reply will be deleted by the runnable after running on main thread
BluetoothReply* reply;
if (aStatusCode != STATUS_SUCCESS) {
reply = new BluetoothReply(BluetoothReplyError(aStatusCode, EmptyString()));
} else {
MOZ_ASSERT(aValue.type() != BluetoothValue::T__None);
reply = new BluetoothReply(BluetoothReplySuccess(aValue));
}
MOZ_ASSERT(aRunnable);
MOZ_ASSERT(aValue.type() != BluetoothValue::T__None);
aRunnable->SetReply(reply);
if (NS_FAILED(NS_DispatchToMainThread(aRunnable))) {
BT_WARNING("Failed to dispatch to main thread!");
}
BluetoothReply* reply = new BluetoothReply(BluetoothReplySuccess(aValue));
aRunnable->SetReply(reply); // runnable will delete reply after Run()
NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(aRunnable)));
}
void
DispatchReplyError(BluetoothReplyRunnable* aRunnable,
const nsAString& aErrorStr)
{
MOZ_ASSERT(aRunnable);
MOZ_ASSERT(!aErrorStr.IsEmpty());
BluetoothReply* reply =
new BluetoothReply(BluetoothReplyError(STATUS_FAIL, nsString(aErrorStr)));
aRunnable->SetReply(reply); // runnable will delete reply after Run()
NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(aRunnable)));
}
void
DispatchReplyError(BluetoothReplyRunnable* aRunnable,
const enum BluetoothStatus aStatus)
{
MOZ_ASSERT(aRunnable);
MOZ_ASSERT(aStatus != STATUS_SUCCESS);
BluetoothReply* reply =
new BluetoothReply(BluetoothReplyError(aStatus, EmptyString()));
aRunnable->SetReply(reply); // runnable will delete reply after Run()
NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(aRunnable)));
}
void

View File

@ -13,9 +13,18 @@
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothNamedValue;
class BluetoothValue;
class BluetoothReplyRunnable;
class BluetoothValue;
//
// BluetoothUuid <-> uuid string conversion
//
/**
* Convert BluetoothUuid object to xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx uuid string.
* This utility function is used by gecko internal only to convert BluetoothUuid
* created by bluetooth stack to uuid string representation.
*/
void
UuidToString(const BluetoothUuid& aUuid, nsAString& aString);
@ -27,10 +36,9 @@ UuidToString(const BluetoothUuid& aUuid, nsAString& aString);
void
StringToUuid(const char* aString, BluetoothUuid& aUuid);
bool
SetJsObject(JSContext* aContext,
const BluetoothValue& aValue,
JS::Handle<JSObject*> aObj);
//
// Broadcast system message
//
bool
BroadcastSystemMessage(const nsAString& aType,
@ -40,41 +48,59 @@ bool
BroadcastSystemMessage(const nsAString& aType,
const InfallibleTArray<BluetoothNamedValue>& aData);
//
// Dispatch bluetooth reply to main thread
//
/**
* Dispatch BluetoothReply to main thread. The reply contains an error string
* if the request fails.
* Dispatch successful bluetooth reply with NO value to reply request.
*
* @param aRunnable the runnable to reply bluetooth request.
*/
void
DispatchReplySuccess(BluetoothReplyRunnable* aRunnable);
/**
* Dispatch successful bluetooth reply with value to reply request.
*
* @param aRunnable the runnable to reply bluetooth request.
* @param aValue the BluetoothValue to reply successful request.
*/
void
DispatchReplySuccess(BluetoothReplyRunnable* aRunnable,
const BluetoothValue& aValue);
/**
* Dispatch failed bluetooth reply with error string.
*
* This function is for methods returning DOMRequest. If |aErrorStr| is not
* empty, the DOMRequest property 'error.name' would be updated to |aErrorStr|
* before callback function 'onerror' is fired.
*
* NOTE: For methods returning Promise, |aErrorStr| would be ignored and only
* STATUS_FAIL is returned in BluetoothReplyRunnable.
*
* @param aRunnable the runnable to reply bluetooth request.
* @param aValue the BluetoothValue used to reply successful request.
* @param aErrorStr the error string used to reply failed request.
* @param aErrorStr the error string to reply failed request.
*/
void
DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable,
const BluetoothValue& aValue,
const nsAString& aErrorStr);
DispatchReplyError(BluetoothReplyRunnable* aRunnable,
const nsAString& aErrorStr);
/**
* Dispatch BluetoothReply to main thread. The reply contains an error string
* if the request fails.
* Dispatch failed bluetooth reply with error status.
*
* This function is for methods returning Promise. If |aStatusCode| is not
* STATUS_SUCCESS, the Promise would reject with an Exception object with
* nsError associated with |aStatusCode|. The name and messege of Exception
* (defined in dom/base/domerr.msg) are filled automatically during promise
* rejection.
* This function is for methods returning Promise. The Promise would reject
* with an Exception object that carries nsError associated with |aStatus|.
* The name and messege of Exception (defined in dom/base/domerr.msg) are
* filled automatically during promise rejection.
*
* @param aRunnable the runnable to reply bluetooth request.
* @param aValue the BluetoothValue to reply successful request.
* @param aStatusCode the error status to reply failed request.
* @param aRunnable the runnable to reply bluetooth request.
* @param aStatus the error status to reply failed request.
*/
void
DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable,
const BluetoothValue& aValue,
const enum BluetoothStatus aStatusCode);
DispatchReplyError(BluetoothReplyRunnable* aRunnable,
const enum BluetoothStatus aStatus);
void
DispatchStatusChangedEvent(const nsAString& aType,

View File

@ -20,9 +20,8 @@
#define ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(runnable) \
do { \
if (!sBluetoothGattInterface) { \
NS_NAMED_LITERAL_STRING(errorStr, \
"BluetoothGattClientInterface is not ready"); \
DispatchBluetoothReply(runnable, BluetoothValue(), errorStr); \
DispatchReplyError(runnable, \
NS_LITERAL_STRING("BluetoothGattClientInterface is not ready")); \
return; \
} \
} while(0)
@ -270,10 +269,8 @@ public:
// Reject the connect request
if (mClient->mConnectRunnable) {
NS_NAMED_LITERAL_STRING(errorStr, "Register GATT client failed");
DispatchBluetoothReply(mClient->mConnectRunnable,
BluetoothValue(),
errorStr);
DispatchReplyError(mClient->mConnectRunnable,
NS_LITERAL_STRING("Register GATT client failed"));
mClient->mConnectRunnable = nullptr;
}
@ -308,9 +305,7 @@ public:
bs->DistributeSignal(signal);
// Resolve the unregister request
DispatchBluetoothReply(mClient->mUnregisterClientRunnable,
BluetoothValue(true),
EmptyString());
DispatchReplySuccess(mClient->mUnregisterClientRunnable);
mClient->mUnregisterClientRunnable = nullptr;
sClients->RemoveElement(mClient);
@ -323,10 +318,8 @@ public:
MOZ_ASSERT(mClient->mUnregisterClientRunnable);
// Reject the unregister request
NS_NAMED_LITERAL_STRING(errorStr, "Unregister GATT client failed");
DispatchBluetoothReply(mClient->mUnregisterClientRunnable,
BluetoothValue(),
errorStr);
DispatchReplyError(mClient->mUnregisterClientRunnable,
NS_LITERAL_STRING("Unregister GATT client failed"));
mClient->mUnregisterClientRunnable = nullptr;
}
@ -348,10 +341,8 @@ BluetoothGattManager::UnregisterClient(int aClientIf,
// Reject the unregister request if the client is not found
if (index == sClients->NoIndex) {
NS_NAMED_LITERAL_STRING(errorStr, "Unregister GATT client failed");
DispatchBluetoothReply(aRunnable,
BluetoothValue(),
errorStr);
DispatchReplyError(aRunnable,
NS_LITERAL_STRING("Unregister GATT client failed"));
return;
}
@ -390,10 +381,8 @@ public:
bs->DistributeSignal(signal);
// Reject the connect request
NS_NAMED_LITERAL_STRING(errorStr, "Connect failed");
DispatchBluetoothReply(mClient->mConnectRunnable,
BluetoothValue(),
errorStr);
DispatchReplyError(mClient->mConnectRunnable,
NS_LITERAL_STRING("Connect failed"));
mClient->mConnectRunnable = nullptr;
}
@ -462,10 +451,8 @@ public:
bs->DistributeSignal(signal);
// Reject the disconnect request
NS_NAMED_LITERAL_STRING(errorStr, "Disconnect failed");
DispatchBluetoothReply(mClient->mDisconnectRunnable,
BluetoothValue(),
errorStr);
DispatchReplyError(mClient->mDisconnectRunnable,
NS_LITERAL_STRING("Disconnect failed"));
mClient->mDisconnectRunnable = nullptr;
}
@ -487,8 +474,7 @@ BluetoothGattManager::Disconnect(const nsAString& aAppUuid,
// Reject the disconnect request if the client is not found
if (index == sClients->NoIndex) {
NS_NAMED_LITERAL_STRING(errorStr, "Disconnect failed");
DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
DispatchReplyError(aRunnable, NS_LITERAL_STRING("Disconnect failed"));
return;
}
@ -536,11 +522,9 @@ BluetoothGattManager::RegisterClientNotification(int aStatus,
// Reject the connect request
if (client->mConnectRunnable) {
NS_NAMED_LITERAL_STRING(errorStr,
"Connect failed due to registration failed");
DispatchBluetoothReply(client->mConnectRunnable,
BluetoothValue(),
errorStr);
DispatchReplyError(client->mConnectRunnable,
NS_LITERAL_STRING(
"Connect failed due to registration failed"));
client->mConnectRunnable = nullptr;
}
@ -600,10 +584,8 @@ BluetoothGattManager::ConnectNotification(int aConnId,
// Reject the connect request
if (client->mConnectRunnable) {
NS_NAMED_LITERAL_STRING(errorStr, "Connect failed");
DispatchBluetoothReply(client->mConnectRunnable,
BluetoothValue(),
errorStr);
DispatchReplyError(client->mConnectRunnable,
NS_LITERAL_STRING("Connect failed"));
client->mConnectRunnable = nullptr;
}
@ -621,9 +603,7 @@ BluetoothGattManager::ConnectNotification(int aConnId,
// Resolve the connect request
if (client->mConnectRunnable) {
DispatchBluetoothReply(client->mConnectRunnable,
BluetoothValue(true),
EmptyString());
DispatchReplySuccess(client->mConnectRunnable);
client->mConnectRunnable = nullptr;
}
}
@ -655,10 +635,8 @@ BluetoothGattManager::DisconnectNotification(int aConnId,
// Reject the disconnect request
if (client->mDisconnectRunnable) {
NS_NAMED_LITERAL_STRING(errorStr, "Disconnect failed");
DispatchBluetoothReply(client->mDisconnectRunnable,
BluetoothValue(),
errorStr);
DispatchReplyError(client->mDisconnectRunnable,
NS_LITERAL_STRING("Disconnect failed"));
client->mDisconnectRunnable = nullptr;
}
@ -676,9 +654,7 @@ BluetoothGattManager::DisconnectNotification(int aConnId,
// Resolve the disconnect request
if (client->mDisconnectRunnable) {
DispatchBluetoothReply(client->mDisconnectRunnable,
BluetoothValue(true),
EmptyString());
DispatchReplySuccess(client->mDisconnectRunnable);
client->mDisconnectRunnable = nullptr;
}
}

View File

@ -32,16 +32,13 @@
#include "mozilla/StaticMutex.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/unused.h"
#define ERR_SET_PROPERTY "SetPropertyError"
#define ERR_START_BLUETOOTH "StartBluetoothError"
#define ERR_STOP_BLUETOOTH "StopBluetoothError"
#include "nsDataHashtable.h"
#define ENSURE_BLUETOOTH_IS_READY(runnable, result) \
do { \
if (!sBtInterface || !IsEnabled()) { \
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth is not ready"); \
DispatchBluetoothReply(runnable, BluetoothValue(), errorStr); \
DispatchReplyError(runnable, \
NS_LITERAL_STRING("Bluetooth is not ready")); \
return result; \
} \
} while(0)
@ -49,8 +46,8 @@
#define ENSURE_BLUETOOTH_IS_READY_VOID(runnable) \
do { \
if (!sBtInterface || !IsEnabled()) { \
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth is not ready"); \
DispatchBluetoothReply(runnable, BluetoothValue(), errorStr); \
DispatchReplyError(runnable, \
NS_LITERAL_STRING("Bluetooth is not ready")); \
return; \
} \
} while(0)
@ -58,8 +55,8 @@
#define ENSURE_GATT_MGR_IS_READY_VOID(gatt, runnable) \
do { \
if (!gatt) { \
NS_NAMED_LITERAL_STRING(replyError, "GattManager is not ready"); \
DispatchBluetoothReply(runnable, BluetoothValue(), replyError); \
DispatchReplyError(runnable, \
NS_LITERAL_STRING("GattManager is not ready")); \
return; \
} \
} while(0)
@ -76,6 +73,12 @@ static bool sAdapterEnabled(false);
// InfallibleTArray is an alias for nsTArray.
static InfallibleTArray<nsString> sAdapterBondedAddressArray;
// Use a static hash table to keep the name of remote device during the pairing
// procedure. In this manner, BT service and adapter can get the name of paired
// device name when bond state changed.
// The hash Key is BD address, the Value is remote BD name.
static nsDataHashtable<nsStringHashKey, nsString> sPairingNameTable;
static BluetoothInterface* sBtInterface;
static nsTArray<nsRefPtr<BluetoothProfileController> > sControllerArray;
static InfallibleTArray<BluetoothNamedValue> sRemoteDevicesPack;
@ -270,36 +273,6 @@ BluetoothServiceBluedroid::StopGonkBluetooth()
return NS_OK;
}
void
BluetoothServiceBluedroid::ReplyStatusError(
BluetoothReplyRunnable* aBluetoothReplyRunnable,
BluetoothStatus aStatusCode, const nsAString& aCustomMsg)
{
MOZ_ASSERT(aBluetoothReplyRunnable, "Reply runnable is nullptr");
BT_LOGR("error code(%d)", aStatusCode);
nsAutoString replyError;
replyError.Assign(aCustomMsg);
if (aStatusCode == STATUS_BUSY) {
replyError.AppendLiteral(":BT_STATUS_BUSY");
} else if (aStatusCode == STATUS_NOT_READY) {
replyError.AppendLiteral(":BT_STATUS_NOT_READY");
} else if (aStatusCode == STATUS_DONE) {
replyError.AppendLiteral(":BT_STATUS_DONE");
} else if (aStatusCode == STATUS_AUTH_FAILURE) {
replyError.AppendLiteral(":BT_STATUS_AUTH_FAILURE");
} else if (aStatusCode == STATUS_RMT_DEV_DOWN) {
replyError.AppendLiteral(":BT_STATUS_RMT_DEV_DOWN");
} else if (aStatusCode == STATUS_FAIL) {
replyError.AppendLiteral(":BT_STATUS_FAIL");
}
DispatchBluetoothReply(aBluetoothReplyRunnable, BluetoothValue(true),
replyError);
}
/**
* Member functions
*/
@ -331,8 +304,7 @@ BluetoothServiceBluedroid::StartInternal(BluetoothReplyRunnable* aRunnable)
// Reject Promise
if(aRunnable) {
DispatchBluetoothReply(aRunnable, BluetoothValue(),
NS_LITERAL_STRING(ERR_START_BLUETOOTH));
DispatchReplyError(aRunnable, NS_LITERAL_STRING("StartBluetoothError"));
sChangeAdapterStateRunnableArray.RemoveElement(aRunnable);
}
@ -389,8 +361,7 @@ BluetoothServiceBluedroid::StopInternal(BluetoothReplyRunnable* aRunnable)
// Reject Promise
if(aRunnable) {
DispatchBluetoothReply(aRunnable, BluetoothValue(),
NS_LITERAL_STRING(ERR_STOP_BLUETOOTH));
DispatchReplyError(aRunnable, NS_LITERAL_STRING("StopBluetoothError"));
sChangeAdapterStateRunnableArray.RemoveElement(aRunnable);
}
@ -440,7 +411,7 @@ BluetoothServiceBluedroid::GetAdaptersInternal(
"Adapter", properties);
}
DispatchBluetoothReply(aRunnable, adaptersProperties, EmptyString());
DispatchReplySuccess(aRunnable, adaptersProperties);
return NS_OK;
}
@ -463,8 +434,7 @@ public:
/* dispatch result after final pending operation */
if (--sRequestedDeviceCountArray[0] == 0) {
if (!sGetDeviceRunnableArray.IsEmpty()) {
DispatchBluetoothReply(
sGetDeviceRunnableArray[0], sRemoteDevicesPack,
DispatchReplyError(sGetDeviceRunnableArray[0],
NS_LITERAL_STRING("GetRemoteDeviceProperties failed"));
sGetDeviceRunnableArray.RemoveElementAt(0);
}
@ -489,9 +459,7 @@ BluetoothServiceBluedroid::GetConnectedDevicePropertiesInternal(
BluetoothProfileManagerBase* profile =
BluetoothUuidHelper::GetBluetoothProfileManager(aServiceUuid);
if (!profile) {
InfallibleTArray<BluetoothNamedValue> emptyArr;
DispatchBluetoothReply(aRunnable, emptyArr,
NS_LITERAL_STRING(ERR_UNKNOWN_PROFILE));
DispatchReplyError(aRunnable, NS_LITERAL_STRING(ERR_UNKNOWN_PROFILE));
return NS_OK;
}
@ -505,7 +473,7 @@ BluetoothServiceBluedroid::GetConnectedDevicePropertiesInternal(
int requestedDeviceCount = deviceAddresses.Length();
if (requestedDeviceCount == 0) {
InfallibleTArray<BluetoothNamedValue> emptyArr;
DispatchBluetoothReply(aRunnable, emptyArr, EmptyString());
DispatchReplySuccess(aRunnable, emptyArr);
return NS_OK;
}
@ -531,7 +499,7 @@ BluetoothServiceBluedroid::GetPairedDevicePropertiesInternal(
int requestedDeviceCount = aDeviceAddress.Length();
if (requestedDeviceCount == 0) {
DispatchBluetoothReply(aRunnable, BluetoothValue(true), EmptyString());
DispatchReplySuccess(aRunnable);
return NS_OK;
}
@ -556,7 +524,7 @@ public:
{
MOZ_ASSERT(NS_IsMainThread());
sChangeDiscoveryRunnableArray.RemoveElement(mRunnable);
ReplyStatusError(mRunnable, aStatus, NS_LITERAL_STRING("StartDiscovery"));
DispatchReplyError(mRunnable, aStatus);
}
private:
@ -589,7 +557,7 @@ public:
{
MOZ_ASSERT(NS_IsMainThread());
sChangeDiscoveryRunnableArray.RemoveElement(mRunnable);
ReplyStatusError(mRunnable, aStatus, NS_LITERAL_STRING("StopDiscovery"));
DispatchReplyError(mRunnable, aStatus);
}
private:
@ -622,7 +590,7 @@ public:
{
MOZ_ASSERT(NS_IsMainThread());
sFetchUuidsRunnableArray.RemoveElement(mRunnable);
ReplyStatusError(mRunnable, aStatus, NS_LITERAL_STRING("FetchUuids"));
DispatchReplyError(mRunnable, aStatus);
}
private:
@ -665,7 +633,7 @@ public:
{
MOZ_ASSERT(NS_IsMainThread());
sSetPropertyRunnableArray.RemoveElement(mRunnable);
ReplyStatusError(mRunnable, aStatus, NS_LITERAL_STRING("SetProperty"));
DispatchReplyError(mRunnable, aStatus);
}
private:
BluetoothReplyRunnable* mRunnable;
@ -718,7 +686,7 @@ public:
void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
{
sBondingRunnableArray.RemoveElement(mRunnable);
ReplyStatusError(mRunnable, aStatus, NS_LITERAL_STRING("CreatedPairedDevice"));
DispatchReplyError(mRunnable, aStatus);
}
private:
@ -754,7 +722,7 @@ public:
void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
{
sUnbondingRunnableArray.RemoveElement(mRunnable);
ReplyStatusError(mRunnable, aStatus, NS_LITERAL_STRING("RemoveDevice"));
DispatchReplyError(mRunnable, aStatus);
}
private:
@ -787,12 +755,12 @@ public:
void PinReply() MOZ_OVERRIDE
{
DispatchBluetoothReply(mRunnable, BluetoothValue(true), EmptyString());
DispatchReplySuccess(mRunnable);
}
void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
{
ReplyStatusError(mRunnable, aStatus, NS_LITERAL_STRING("SetPinCode"));
DispatchReplyError(mRunnable, aStatus);
}
private:
@ -830,13 +798,12 @@ public:
void SspReply() MOZ_OVERRIDE
{
DispatchBluetoothReply(mRunnable, BluetoothValue(true), EmptyString());
DispatchReplySuccess(mRunnable);
}
void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
{
ReplyStatusError(mRunnable, aStatus,
NS_LITERAL_STRING("SetPairingConfirmation"));
DispatchReplyError(mRunnable, aStatus);
}
private:
@ -933,12 +900,12 @@ BluetoothServiceBluedroid::SendFile(const nsAString& aDeviceAddress,
// has been determined when calling 'Connect()'. Nevertheless, keep
// it for future use.
BluetoothOppManager* opp = BluetoothOppManager::Get();
nsAutoString errorStr;
if (!opp || !opp->SendFile(aDeviceAddress, aBlobParent)) {
errorStr.AssignLiteral("Calling SendFile() failed");
DispatchReplyError(aRunnable, NS_LITERAL_STRING("SendFile failed"));
return;
}
DispatchBluetoothReply(aRunnable, BluetoothValue(true), errorStr);
DispatchReplySuccess(aRunnable);
}
void
@ -953,12 +920,12 @@ BluetoothServiceBluedroid::SendFile(const nsAString& aDeviceAddress,
// has been determined when calling 'Connect()'. Nevertheless, keep
// it for future use.
BluetoothOppManager* opp = BluetoothOppManager::Get();
nsAutoString errorStr;
if (!opp || !opp->SendFile(aDeviceAddress, aBlob)) {
errorStr.AssignLiteral("Calling SendFile() failed");
DispatchReplyError(aRunnable, NS_LITERAL_STRING("SendFile failed"));
return;
}
DispatchBluetoothReply(aRunnable, BluetoothValue(true), errorStr);
DispatchReplySuccess(aRunnable);
}
void
@ -974,10 +941,11 @@ BluetoothServiceBluedroid::StopSendingFile(const nsAString& aDeviceAddress,
BluetoothOppManager* opp = BluetoothOppManager::Get();
nsAutoString errorStr;
if (!opp || !opp->StopSendingFile()) {
errorStr.AssignLiteral("Calling StopSendingFile() failed");
DispatchReplyError(aRunnable, NS_LITERAL_STRING("StopSendingFile failed"));
return;
}
DispatchBluetoothReply(aRunnable, BluetoothValue(true), errorStr);
DispatchReplySuccess(aRunnable);
}
void
@ -985,7 +953,7 @@ BluetoothServiceBluedroid::ConfirmReceivingFile(
const nsAString& aDeviceAddress, bool aConfirm,
BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread(), "Must be called from main thread!");
MOZ_ASSERT(NS_IsMainThread());
// Currently we only support one device sending one file at a time,
// so we don't need aDeviceAddress here because the target device
@ -994,10 +962,12 @@ BluetoothServiceBluedroid::ConfirmReceivingFile(
BluetoothOppManager* opp = BluetoothOppManager::Get();
nsAutoString errorStr;
if (!opp || !opp->ConfirmReceivingFile(aConfirm)) {
errorStr.AssignLiteral("Calling ConfirmReceivingFile() failed");
DispatchReplyError(aRunnable,
NS_LITERAL_STRING("ConfirmReceivingFile failed"));
return;
}
DispatchBluetoothReply(aRunnable, BluetoothValue(true), errorStr);
DispatchReplySuccess(aRunnable);
}
void
@ -1007,12 +977,11 @@ BluetoothServiceBluedroid::ConnectSco(BluetoothReplyRunnable* aRunnable)
BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
if (!hfp || !hfp->ConnectSco()) {
NS_NAMED_LITERAL_STRING(replyError, "Calling ConnectSco() failed");
DispatchBluetoothReply(aRunnable, BluetoothValue(), replyError);
DispatchReplyError(aRunnable, NS_LITERAL_STRING("ConnectSco failed"));
return;
}
DispatchBluetoothReply(aRunnable, BluetoothValue(true), EmptyString());
DispatchReplySuccess(aRunnable);
}
void
@ -1022,12 +991,11 @@ BluetoothServiceBluedroid::DisconnectSco(BluetoothReplyRunnable* aRunnable)
BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
if (!hfp || !hfp->DisconnectSco()) {
NS_NAMED_LITERAL_STRING(replyError, "Calling DisconnectSco() failed");
DispatchBluetoothReply(aRunnable, BluetoothValue(), replyError);
DispatchReplyError(aRunnable, NS_LITERAL_STRING("DisconnectSco failed"));
return;
}
DispatchBluetoothReply(aRunnable, BluetoothValue(true), EmptyString());
DispatchReplySuccess(aRunnable);
}
void
@ -1037,12 +1005,11 @@ BluetoothServiceBluedroid::IsScoConnected(BluetoothReplyRunnable* aRunnable)
BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
if (!hfp) {
NS_NAMED_LITERAL_STRING(replyError, "Fail to get BluetoothHfpManager");
DispatchBluetoothReply(aRunnable, BluetoothValue(), replyError);
DispatchReplyError(aRunnable, NS_LITERAL_STRING("IsScoConnected failed"));
return;
}
DispatchBluetoothReply(aRunnable, hfp->IsScoConnected(), EmptyString());
DispatchReplySuccess(aRunnable, BluetoothValue(hfp->IsScoConnected()));
}
void
@ -1059,7 +1026,7 @@ BluetoothServiceBluedroid::SendMetaData(const nsAString& aTitle,
a2dp->UpdateMetaData(aTitle, aArtist, aAlbum, aMediaNumber,
aTotalMediaCount, aDuration);
}
DispatchBluetoothReply(aRunnable, BluetoothValue(true), EmptyString());
DispatchReplySuccess(aRunnable);
}
void
@ -1074,7 +1041,7 @@ BluetoothServiceBluedroid::SendPlayStatus(
PlayStatusStringToControlPlayStatus(aPlayStatus);
a2dp->UpdatePlayStatus(aDuration, aPosition, playStatus);
}
DispatchBluetoothReply(aRunnable, BluetoothValue(true), EmptyString());
DispatchReplySuccess(aRunnable);
}
void
@ -1251,10 +1218,6 @@ BluetoothServiceBluedroid::AdapterStateChangedNotification(bool aState)
sAdapterDiscovering = false;
BT_APPEND_NAMED_VALUE(props, "Discovering", false);
}
if (!sAdapterBondedAddressArray.IsEmpty()) {
BT_APPEND_NAMED_VALUE(props, "PairedDevices",
InfallibleTArray<nsString>());
}
BluetoothSignal signal(NS_LITERAL_STRING("PropertyChanged"),
NS_LITERAL_STRING(KEY_ADAPTER), props);
@ -1280,8 +1243,9 @@ BluetoothServiceBluedroid::AdapterStateChangedNotification(bool aState)
sFetchUuidsRunnableArray.Clear();
sBondingRunnableArray.Clear();
sUnbondingRunnableArray.Clear();
sPairingNameTable.Clear();
// Bluetooth scan mode is SCAN_MODE_CONNECTABLE by default, i.e., It should
// Bluetooth scan mode is SCAN_MODE_CONNECTABLE by default, i.e., it should
// be connectable and non-discoverable.
NS_ENSURE_TRUE_VOID(sBtInterface);
sBtInterface->SetAdapterProperty(
@ -1297,9 +1261,7 @@ BluetoothServiceBluedroid::AdapterStateChangedNotification(bool aState)
// Resolve promise if existed
if (!sChangeAdapterStateRunnableArray.IsEmpty()) {
DispatchBluetoothReply(sChangeAdapterStateRunnableArray[0],
BluetoothValue(true), EmptyString());
DispatchReplySuccess(sChangeAdapterStateRunnableArray[0]);
sChangeAdapterStateRunnableArray.RemoveElementAt(0);
}
}
@ -1346,10 +1308,7 @@ BluetoothServiceBluedroid::AdapterPropertiesNotification(
// Whenever reloading paired devices, force refresh
sAdapterBondedAddressArray.Clear();
for (size_t index = 0; index < p.mStringArray.Length(); index++) {
sAdapterBondedAddressArray.AppendElement(p.mStringArray[index]);
}
sAdapterBondedAddressArray.AppendElements(p.mStringArray);
BT_APPEND_NAMED_VALUE(propertiesArray, "PairedDevices",
sAdapterBondedAddressArray);
@ -1369,8 +1328,7 @@ BluetoothServiceBluedroid::AdapterPropertiesNotification(
// Send reply for SetProperty
if (!sSetPropertyRunnableArray.IsEmpty()) {
DispatchBluetoothReply(sSetPropertyRunnableArray[0],
BluetoothValue(true), EmptyString());
DispatchReplySuccess(sSetPropertyRunnableArray[0]);
sSetPropertyRunnableArray.RemoveElementAt(0);
}
}
@ -1435,9 +1393,9 @@ BluetoothServiceBluedroid::RemoteDevicePropertiesNotification(
// (2) distribute the signal, and finally
// (3) send any pending Bluetooth replies.
//
// |DispatchBluetoothReply| creates its own internal runnable, which is
// |DispatchReplySuccess| creates its own internal runnable, which is
// always run after we completed the current method. This means that we
// can exchange |DistributeBluetoothReply| with other operations without
// can exchange |DispatchReplySuccess| with other operations without
// changing the order of (1,2) and (3).
// Update to registered BluetoothDevice objects
@ -1447,9 +1405,8 @@ BluetoothServiceBluedroid::RemoteDevicePropertiesNotification(
// FetchUuids task
if (!sFetchUuidsRunnableArray.IsEmpty()) {
// propertiesArray contains Address and Uuids only
DispatchBluetoothReply(sFetchUuidsRunnableArray[0],
propertiesArray[1].value() /* Uuids */,
EmptyString());
DispatchReplySuccess(sFetchUuidsRunnableArray[0],
propertiesArray[1].value()); /* Uuids */
sFetchUuidsRunnableArray.RemoveElementAt(0);
DistributeSignal(signal);
return;
@ -1469,8 +1426,7 @@ BluetoothServiceBluedroid::RemoteDevicePropertiesNotification(
if (--sRequestedDeviceCountArray[0] == 0) {
if (!sGetDeviceRunnableArray.IsEmpty()) {
DispatchBluetoothReply(sGetDeviceRunnableArray[0],
sRemoteDevicesPack, EmptyString());
DispatchReplySuccess(sGetDeviceRunnableArray[0], sRemoteDevicesPack);
sGetDeviceRunnableArray.RemoveElementAt(0);
}
@ -1550,9 +1506,7 @@ BluetoothServiceBluedroid::DiscoveryStateChangedNotification(bool aState)
// Reply that Promise is resolved
if (!sChangeDiscoveryRunnableArray.IsEmpty()) {
DispatchBluetoothReply(sChangeDiscoveryRunnableArray[0],
BluetoothValue(true), EmptyString());
DispatchReplySuccess(sChangeDiscoveryRunnableArray[0]);
sChangeDiscoveryRunnableArray.RemoveElementAt(0);
}
}
@ -1572,6 +1526,8 @@ BluetoothServiceBluedroid::PinRequestNotification(const nsAString& aRemoteBdAddr
BT_APPEND_NAMED_VALUE(propertiesArray, "type",
NS_LITERAL_STRING(PAIRING_REQ_TYPE_ENTERPINCODE));
sPairingNameTable.Put(nsString(aRemoteBdAddr), nsString(aBdName));
DistributeSignal(BluetoothSignal(NS_LITERAL_STRING("PairingRequest"),
NS_LITERAL_STRING(KEY_PAIRING_LISTENER),
BluetoothValue(propertiesArray)));
@ -1618,6 +1574,8 @@ BluetoothServiceBluedroid::SspRequestNotification(
BT_APPEND_NAMED_VALUE(propertiesArray, "passkey", passkey);
BT_APPEND_NAMED_VALUE(propertiesArray, "type", pairingType);
sPairingNameTable.Put(nsString(aRemoteBdAddr), nsString(aBdName));
DistributeSignal(BluetoothSignal(NS_LITERAL_STRING("PairingRequest"),
NS_LITERAL_STRING(KEY_PAIRING_LISTENER),
BluetoothValue(propertiesArray)));
@ -1651,14 +1609,25 @@ BluetoothServiceBluedroid::BondStateChangedNotification(
InfallibleTArray<BluetoothNamedValue> propertiesArray;
BT_APPEND_NAMED_VALUE(propertiesArray, "Paired", bonded);
// Retrieve device name from hash table of pairing device name.
nsString deviceName = EmptyString();
bool nameExists = sPairingNameTable.Get(aRemoteBdAddr, &deviceName);
if (nameExists) {
sPairingNameTable.Remove(aRemoteBdAddr);
}
// Update attribute BluetoothDevice.name if the device is paired.
if (bonded && STATUS_SUCCESS) {
MOZ_ASSERT(nameExists);
BT_APPEND_NAMED_VALUE(propertiesArray, "Name", deviceName);
}
DistributeSignal(BluetoothSignal(NS_LITERAL_STRING("PropertyChanged"),
nsString(aRemoteBdAddr),
BluetoothValue(propertiesArray)));
propertiesArray.Clear();
// Append signal properties and notify adapter.
BT_APPEND_NAMED_VALUE(propertiesArray, "Address", nsString(aRemoteBdAddr));
BT_APPEND_NAMED_VALUE(propertiesArray, "Paired", bonded);
// Insert address to signal properties and notify adapter.
BT_INSERT_NAMED_VALUE(propertiesArray, 0, "Address", nsString(aRemoteBdAddr));
nsString signalName = bonded ? NS_LITERAL_STRING(DEVICE_PAIRED_ID)
: NS_LITERAL_STRING(DEVICE_UNPAIRED_ID);
@ -1670,25 +1639,21 @@ BluetoothServiceBluedroid::BondStateChangedNotification(
if (aStatus == STATUS_SUCCESS) {
// Resolve existing pair/unpair promise when pair/unpair succeeded
if (bonded && !sBondingRunnableArray.IsEmpty()) {
DispatchBluetoothReply(sBondingRunnableArray[0],
BluetoothValue(true), EmptyString());
DispatchReplySuccess(sBondingRunnableArray[0]);
sBondingRunnableArray.RemoveElementAt(0);
} else if (!bonded && !sUnbondingRunnableArray.IsEmpty()) {
DispatchBluetoothReply(sUnbondingRunnableArray[0],
BluetoothValue(true), EmptyString());
DispatchReplySuccess(sUnbondingRunnableArray[0]);
sUnbondingRunnableArray.RemoveElementAt(0);
}
} else {
// Reject existing pair/unpair promise when pair/unpair failed
if (!bonded && !sBondingRunnableArray.IsEmpty()) {
DispatchBluetoothReply(sBondingRunnableArray[0],
BluetoothValue(),
NS_LITERAL_STRING("Pair Error"));
DispatchReplyError(sBondingRunnableArray[0],
NS_LITERAL_STRING("Pair failed"));
sBondingRunnableArray.RemoveElementAt(0);
} else if (bonded && !sUnbondingRunnableArray.IsEmpty()) {
DispatchBluetoothReply(sUnbondingRunnableArray[0],
BluetoothValue(),
NS_LITERAL_STRING("Unpair Error"));
DispatchReplyError(sUnbondingRunnableArray[0],
NS_LITERAL_STRING("Unpair failed"));
sUnbondingRunnableArray.RemoveElementAt(0);
}
}

View File

@ -240,9 +240,6 @@ protected:
static void NextBluetoothProfileController();
static ControlPlayStatus PlayStatusStringToControlPlayStatus(
const nsAString& aPlayStatus);
static void ReplyStatusError(BluetoothReplyRunnable* aReplyRunnable,
BluetoothStatus aStatusCode,
const nsAString& aCustomMsg);
};
END_BLUETOOTH_NAMESPACE

View File

@ -408,6 +408,18 @@ DispatchToBtThread(nsIRunnable* aRunnable)
return sBluetoothThread->Dispatch(aRunnable, NS_DISPATCH_NORMAL);
}
static void
DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable,
const BluetoothValue& aValue,
const nsAString& aErrorStr)
{
if (!aErrorStr.IsEmpty()) {
DispatchReplyError(aRunnable, aErrorStr);
} else {
DispatchReplySuccess(aRunnable, aValue);
}
}
BluetoothDBusService::BluetoothDBusService()
{
sGetPropertyMonitor = new Monitor("BluetoothService.sGetPropertyMonitor");

View File

@ -1885,8 +1885,7 @@ BluetoothHfpManager::OnScoConnectSuccess()
{
// For active connection request, we need to reply the DOMRequest
if (mScoRunnable) {
DispatchBluetoothReply(mScoRunnable,
BluetoothValue(true), EmptyString());
DispatchReplySuccess(mScoRunnable);
mScoRunnable = nullptr;
}
@ -1900,9 +1899,8 @@ void
BluetoothHfpManager::OnScoConnectError()
{
if (mScoRunnable) {
NS_NAMED_LITERAL_STRING(replyError, "Failed to create SCO socket!");
DispatchBluetoothReply(mScoRunnable, BluetoothValue(), replyError);
DispatchReplyError(mScoRunnable,
NS_LITERAL_STRING("Failed to create SCO socket!"));
mScoRunnable = nullptr;
}

View File

@ -111,6 +111,8 @@ public:
IMPL_EVENT_HANDLER(stksessionend)
private:
~Icc() {}
bool mLive;
uint32_t mClientId;
nsString mIccId;

View File

@ -124,7 +124,7 @@ let FormVisibility = {
let visible = this.yAxisVisible(
adjustedTop,
pos.height,
pos.width
offset.height
);
if (!visible)

View File

@ -10,6 +10,7 @@
#include "WifiCertService.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/Endian.h"
#include "mozilla/ModuleUtils.h"
#include "mozilla/RefPtr.h"
#include "mozilla/dom/ToJSValue.h"
@ -71,9 +72,14 @@ private:
return NS_ERROR_OUT_OF_MEMORY;
}
// Only support DER format now.
return ImportDERBlob(buf, size, mResult.mNickname,
&mResult.mUsageFlag);
// Try import as DER format first.
rv = ImportDERBlob(buf, size);
if (NS_SUCCEEDED(rv)) {
return rv;
}
// Try import as PKCS#12 format.
return ImportPKCS12Blob(buf, size, mPassword);
}
virtual void CallCallback(nsresult rv)
@ -84,20 +90,148 @@ private:
gWifiCertService->DispatchResult(mResult);
}
nsresult ImportDERBlob(char* buf, uint32_t size,
const nsAString& aNickname,
/*out*/ uint16_t* aUsageFlag)
nsresult ImportDERBlob(char* buf, uint32_t size)
{
NS_ENSURE_ARG_POINTER(aUsageFlag);
// Create certificate object.
ScopedCERTCertificate cert(CERT_DecodeCertFromPackage(buf, size));
if (!cert) {
return MapSECStatus(SECFailure);
}
// Import certificate with nickname.
return ImportCert(cert, aNickname, aUsageFlag);
// Import certificate.
return ImportCert(cert);
}
static SECItem*
HandleNicknameCollision(SECItem* aOldNickname, PRBool* aCancel, void* aWincx)
{
const char* dummyName = "Imported User Cert";
const size_t dummyNameLen = strlen(dummyName);
SECItem* newNick = ::SECITEM_AllocItem(nullptr, nullptr, dummyNameLen + 1);
if (!newNick) {
return nullptr;
}
newNick->type = siAsciiString;
// Dummy name, will be renamed later.
memcpy(newNick->data, dummyName, dummyNameLen + 1);
newNick->len = dummyNameLen;
return newNick;
}
static SECStatus
HandleNicknameUpdate(const CERTCertificate *aCert,
const SECItem *default_nickname,
SECItem **new_nickname,
void *arg)
{
WifiCertServiceResultOptions *result = (WifiCertServiceResultOptions *)arg;
nsCString userNickname;
CopyUTF16toUTF8(result->mNickname, userNickname);
nsCString fullNickname;
if (aCert->isRoot && (aCert->nsCertType & NS_CERT_TYPE_SSL_CA)) {
// Accept self-signed SSL CA as server certificate.
fullNickname.AssignLiteral("WIFI_SERVERCERT_");
fullNickname += userNickname;
result->mUsageFlag |= nsIWifiCertService::WIFI_CERT_USAGE_FLAG_SERVER;
} else if (aCert->nsCertType & NS_CERT_TYPE_SSL_CLIENT) {
// User Certificate
fullNickname.AssignLiteral("WIFI_USERCERT_");
fullNickname += userNickname;
result->mUsageFlag |= nsIWifiCertService::WIFI_CERT_USAGE_FLAG_USER;
}
char* nickname;
uint32_t length = fullNickname.GetMutableData(&nickname);
SECItem* newNick = ::SECITEM_AllocItem(nullptr, nullptr, length + 1);
if (!newNick) {
return SECFailure;
}
newNick->type = siAsciiString;
memcpy(newNick->data, nickname, length + 1);
newNick->len = length;
*new_nickname = newNick;
return SECSuccess;
}
nsresult ImportPKCS12Blob(char* buf, uint32_t size, const nsAString& aPassword)
{
nsString password(aPassword);
// password is null-terminated wide-char string.
// passwordItem is required to be big-endian form of password, stored in char
// array, including the null-termination.
uint32_t length = password.Length() + 1;
ScopedSECItem passwordItem(
::SECITEM_AllocItem(nullptr, nullptr, length * sizeof(nsString::char_type)));
if (!passwordItem) {
return NS_ERROR_FAILURE;
}
mozilla::NativeEndian::copyAndSwapToBigEndian(passwordItem->data,
password.BeginReading(),
length);
// Create a decoder.
ScopedSEC_PKCS12DecoderContext p12dcx(SEC_PKCS12DecoderStart(
passwordItem, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr,
nullptr));
if (!p12dcx) {
return NS_ERROR_FAILURE;
}
// Assign data to decorder.
SECStatus srv = SEC_PKCS12DecoderUpdate(p12dcx,
reinterpret_cast<unsigned char*>(buf),
size);
if (srv != SECSuccess) {
return MapSECStatus(srv);
}
// Verify certificates.
srv = SEC_PKCS12DecoderVerify(p12dcx);
if (srv != SECSuccess) {
return MapSECStatus(srv);
}
// Set certificate nickname and usage flag.
srv = SEC_PKCS12DecoderRenameCertNicknames(p12dcx, HandleNicknameUpdate,
&mResult);
// Validate certificates.
srv = SEC_PKCS12DecoderValidateBags(p12dcx, HandleNicknameCollision);
if (srv != SECSuccess) {
return MapSECStatus(srv);
}
// Initialize slot.
ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
if (!slot) {
return NS_ERROR_FAILURE;
}
if (PK11_NeedLogin(slot) && PK11_NeedUserInit(slot)) {
srv = PK11_InitPin(slot, "", "");
if (srv != SECSuccess) {
return MapSECStatus(srv);
}
}
// Import cert and key.
srv = SEC_PKCS12DecoderImportBags(p12dcx);
if (srv != SECSuccess) {
return MapSECStatus(srv);
}
// User certificate must be imported from PKCS#12.
return (mResult.mUsageFlag & nsIWifiCertService::WIFI_CERT_USAGE_FLAG_USER)
? NS_OK : NS_ERROR_FAILURE;
}
nsresult ReadBlob(/*out*/ nsCString& aBuf)
@ -128,20 +262,22 @@ private:
return NS_OK;
}
nsresult ImportCert(CERTCertificate* aCert, const nsAString& aNickname,
/*out*/ uint16_t* aUsageFlag)
nsresult ImportCert(CERTCertificate* aCert)
{
NS_ENSURE_ARG_POINTER(aUsageFlag);
nsCString userNickname, fullNickname;
CopyUTF16toUTF8(aNickname, userNickname);
CopyUTF16toUTF8(mResult.mNickname, userNickname);
// Determine certificate nickname by adding prefix according to its type.
if (aCert->isRoot && (aCert->nsCertType & NS_CERT_TYPE_SSL_CA)) {
// Accept self-signed SSL CA as server certificate.
fullNickname.AssignLiteral("WIFI_SERVERCERT_");
fullNickname += userNickname;
*aUsageFlag |= nsIWifiCertService::WIFI_CERT_USAGE_FLAG_SERVER;
mResult.mUsageFlag |= nsIWifiCertService::WIFI_CERT_USAGE_FLAG_SERVER;
} else if (aCert->nsCertType & NS_CERT_TYPE_SSL_CLIENT) {
// User Certificate
fullNickname.AssignLiteral("WIFI_USERCERT_");
fullNickname += userNickname;
mResult.mUsageFlag |= nsIWifiCertService::WIFI_CERT_USAGE_FLAG_USER;
} else {
return NS_ERROR_ABORT;
}
@ -154,7 +290,7 @@ private:
}
// Import certificate, duplicated nickname will cause error.
SECStatus srv = CERT_AddTempCertToPerm(aCert, nickname, NULL);
SECStatus srv = CERT_AddTempCertToPerm(aCert, nickname, nullptr);
if (srv != SECSuccess) {
return MapSECStatus(srv);
}
@ -193,15 +329,45 @@ private:
// Delete server certificate.
nsCString serverCertName("WIFI_SERVERCERT_", 16);
serverCertName += userNickname;
ScopedCERTCertificate cert(
CERT_FindCertByNickname(CERT_GetDefaultCertDB(), serverCertName.get())
);
if (!cert) {
return MapSECStatus(SECFailure);
nsresult rv = deleteCert(serverCertName);
if (NS_FAILED(rv)) {
return rv;
}
// Delete user certificate and private key.
nsCString userCertName("WIFI_USERCERT_", 14);
userCertName += userNickname;
rv = deleteCert(userCertName);
if (NS_FAILED(rv)) {
return rv;
}
return NS_OK;
}
nsresult deleteCert(const nsCString &aCertNickname)
{
ScopedCERTCertificate cert(
CERT_FindCertByNickname(CERT_GetDefaultCertDB(), aCertNickname.get())
);
// Because we delete certificates in blind, so it's acceptable to delete
// a non-exist certificate.
if (!cert) {
return NS_OK;
}
ScopedPK11SlotInfo slot(
PK11_KeyForCertExists(cert, nullptr, nullptr)
);
SECStatus srv;
if (slot) {
// Delete private key along with certificate.
srv = PK11_DeleteTokenCertAndKey(cert, nullptr);
} else {
srv = SEC_DeletePermCertificate(cert);
}
SECStatus srv = SEC_DeletePermCertificate(cert);
if (srv != SECSuccess) {
return MapSECStatus(srv);
}

View File

@ -3469,7 +3469,7 @@ WifiWorker.prototype = {
WifiManager.importCert(msg.data, function(data) {
if (data.status === 0) {
let usageString = ["ServerCert"];
let usageString = ["ServerCert", "UserCert"];
let usageArray = [];
for (let i = 0; i < usageString.length; i++) {
if (data.usageFlag & (0x01 << i)) {
@ -3513,9 +3513,11 @@ WifiWorker.prototype = {
}
let importedCerts = {
ServerCert: [],
UserCert: [],
};
let UsageMapping = {
SERVERCERT: "ServerCert",
USERCERT: "UserCert",
};
while (certListEnum.hasMoreElements()) {

View File

@ -20,6 +20,7 @@
#include "KeyStore.h"
#include "jsfriendapi.h"
#include "MainThreadUtils.h" // For NS_IsMainThread.
#include "nsICryptoHash.h"
#include "plbase64.h"
#include "certdb.h"
@ -108,19 +109,65 @@ status_t BnKeystoreService::onTransact(uint32_t code, const Parcel& data, Parcel
reply->writeInt32(dataLength);
void* buf = reply->writeInplace(dataLength);
memcpy(buf, data, dataLength);
free(data);
moz_free(data);
} else {
reply->writeInt32(-1);
}
return NO_ERROR;
} break;
case GET_PUBKEY: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 name = data.readString16();
uint8_t* data = nullptr;
size_t dataLength = 0;
int32_t ret = get_pubkey(name, &data, &dataLength);
reply->writeNoException();
if (dataLength > 0 && data != nullptr) {
reply->writeInt32(dataLength);
void* buf = reply->writeInplace(dataLength);
memcpy(buf, data, dataLength);
moz_free(data);
} else {
reply->writeInt32(-1);
}
reply->writeInt32(ret);
return NO_ERROR;
} break;
case SIGN: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 name = data.readString16();
size_t signDataSize = data.readInt32();
const uint8_t *signData = nullptr;
if (signDataSize >= 0 && signDataSize <= data.dataAvail()) {
signData = (const uint8_t *)data.readInplace(signDataSize);
}
uint8_t *signResult = nullptr;
size_t signResultSize;
int32_t ret = sign(name, signData, signDataSize, &signResult,
&signResultSize);
reply->writeNoException();
if (signResultSize > 0 && signResult != nullptr) {
reply->writeInt32(signResultSize);
void* buf = reply->writeInplace(signResultSize);
memcpy(buf, signResult, signResultSize);
moz_free(signResult);
} else {
reply->writeInt32(-1);
}
reply->writeInt32(ret);
return NO_ERROR;
} break;
default:
return NO_ERROR;
}
}
// Provide service for binder.
class KeyStoreService: public BnKeystoreService
class KeyStoreService : public BnKeystoreService
, public nsNSSShutDownObject
{
public:
int32_t test() {
@ -133,13 +180,22 @@ public:
}
int32_t get(const String16& name, uint8_t** item, size_t* itemLength) {
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown()) {
return ::SYSTEM_ERROR;
}
uid_t callingUid = IPCThreadState::self()->getCallingUid();
if (!mozilla::ipc::checkPermission(callingUid)) {
return ::PERMISSION_DENIED;
}
String8 certName(name);
return mozilla::ipc::getCertificate(certName.string(), (const uint8_t **)item, (int *)itemLength);
if (!strncmp(certName.string(), "WIFI_USERKEY_", 13)) {
return getPrivateKey(certName.string(), (const uint8_t**)item, itemLength);
}
return getCertificate(certName.string(), (const uint8_t**)item, itemLength);
}
int32_t insert(const String16& name, const uint8_t* item, size_t itemLength, int uid, int32_t flags) {return ::UNDEFINED_ACTION;}
@ -152,9 +208,50 @@ public:
int32_t unlock(const String16& password) {return ::UNDEFINED_ACTION;}
int32_t zero() {return ::UNDEFINED_ACTION;}
int32_t import(const String16& name, const uint8_t* data, size_t length, int uid, int32_t flags) {return ::UNDEFINED_ACTION;}
int32_t sign(const String16& name, const uint8_t* data, size_t length, uint8_t** out, size_t* outLength) {return ::UNDEFINED_ACTION;}
int32_t sign(const String16& name, const uint8_t* data, size_t length, uint8_t** out, size_t* outLength)
{
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown()) {
return ::SYSTEM_ERROR;
}
uid_t callingUid = IPCThreadState::self()->getCallingUid();
if (!mozilla::ipc::checkPermission(callingUid)) {
return ::PERMISSION_DENIED;
}
if (data == nullptr) {
return ::SYSTEM_ERROR;
}
String8 keyName(name);
if (!strncmp(keyName.string(), "WIFI_USERKEY_", 13)) {
return signData(keyName.string(), data, length, out, outLength);
}
return ::UNDEFINED_ACTION;
}
int32_t verify(const String16& name, const uint8_t* data, size_t dataLength, const uint8_t* signature, size_t signatureLength) {return ::UNDEFINED_ACTION;}
int32_t get_pubkey(const String16& name, uint8_t** pubkey, size_t* pubkeyLength) {return ::UNDEFINED_ACTION;}
int32_t get_pubkey(const String16& name, uint8_t** pubkey, size_t* pubkeyLength) {
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown()) {
return ::SYSTEM_ERROR;
}
uid_t callingUid = IPCThreadState::self()->getCallingUid();
if (!mozilla::ipc::checkPermission(callingUid)) {
return ::PERMISSION_DENIED;
}
String8 keyName(name);
if (!strncmp(keyName.string(), "WIFI_USERKEY_", 13)) {
return getPublicKey(keyName.string(), (const uint8_t**)pubkey, pubkeyLength);
}
return ::UNDEFINED_ACTION;
}
int32_t del_key(const String16& name, int uid) {return ::UNDEFINED_ACTION;}
int32_t grant(const String16& name, int32_t granteeUid) {return ::UNDEFINED_ACTION;}
int32_t ungrant(const String16& name, int32_t granteeUid) {return ::UNDEFINED_ACTION;}
@ -174,6 +271,18 @@ public:
virtual int32_t generate(const String16& name, int32_t uid, int32_t keyType, int32_t keySize, int32_t flags, Vector<sp<KeystoreArg> >* args) {return ::UNDEFINED_ACTION;}
virtual int32_t is_hardware_backed(const String16& keyType) {return ::UNDEFINED_ACTION;}
#endif
protected:
virtual void virtualDestroyNSSReference() {}
private:
~KeyStoreService() {
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown()) {
return;
}
shutdown(calledFromObject);
}
};
} // namespace android
@ -210,19 +319,24 @@ static const char* KEYSTORE_ALLOWED_PREFIXES[] = {
// Transform base64 certification data into DER format
void
FormatCaData(const uint8_t *aCaData, int aCaDataLength,
FormatCaData(const char *aCaData, int aCaDataLength,
const char *aName, const uint8_t **aFormatData,
int *aFormatDataLength)
size_t *aFormatDataLength)
{
int bufSize = strlen(CA_BEGIN) + strlen(CA_END) + strlen(CA_TAILER) * 2 +
strlen(aName) * 2 + aCaDataLength + aCaDataLength/CA_LINE_SIZE + 2;
char *buf = (char *)malloc(bufSize);
size_t bufSize = strlen(CA_BEGIN) + strlen(CA_END) + strlen(CA_TAILER) * 2 +
strlen(aName) * 2 + aCaDataLength + aCaDataLength/CA_LINE_SIZE
+ 2;
char *buf = (char *)moz_malloc(bufSize);
if (!buf) {
*aFormatData = nullptr;
return;
}
*aFormatDataLength = bufSize;
*aFormatData = (const uint8_t *)buf;
char *ptr = buf;
int len;
size_t len;
// Create DER header.
len = snprintf(ptr, bufSize, "%s%s%s", CA_BEGIN, aName, CA_TAILER);
@ -250,7 +364,8 @@ FormatCaData(const uint8_t *aCaData, int aCaDataLength,
}
ResponseCode
getCertificate(const char *aCertName, const uint8_t **aCertData, int *aCertDataLength)
getCertificate(const char *aCertName, const uint8_t **aCertData,
size_t *aCertDataLength)
{
// certificate name prefix check.
if (!aCertName) {
@ -281,10 +396,266 @@ getCertificate(const char *aCertName, const uint8_t **aCertData, int *aCertDataL
return SYSTEM_ERROR;
}
FormatCaData((const uint8_t *)certDER, strlen(certDER), "CERTIFICATE",
aCertData, aCertDataLength);
FormatCaData(certDER, strlen(certDER), "CERTIFICATE", aCertData,
aCertDataLength);
PL_strfree(certDER);
if (!(*aCertData)) {
return SYSTEM_ERROR;
}
return SUCCESS;
}
ResponseCode getPrivateKey(const char *aKeyName, const uint8_t **aKeyData,
size_t *aKeyDataLength)
{
*aKeyData = nullptr;
// Get corresponding user certificate nickname
char userCertName[128] = {0};
snprintf(userCertName, sizeof(userCertName) - 1, "WIFI_USERCERT_%s", aKeyName + 13);
// Get private key from user certificate.
ScopedCERTCertificate userCert(
CERT_FindCertByNickname(CERT_GetDefaultCertDB(), userCertName));
if (!userCert) {
return KEY_NOT_FOUND;
}
ScopedSECKEYPrivateKey privateKey(
PK11_FindKeyByAnyCert(userCert.get(), nullptr));
if (!privateKey) {
return KEY_NOT_FOUND;
}
// Export private key in PKCS#12 encrypted format, no password.
unsigned char pwstr[] = {0, 0};
SECItem password = {siBuffer, pwstr, sizeof(pwstr)};
ScopedSECKEYEncryptedPrivateKeyInfo encryptedPrivateKey(
PK11_ExportEncryptedPrivKeyInfo(privateKey->pkcs11Slot,
SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4, &password, privateKey, 1,
privateKey->wincx));
if (!encryptedPrivateKey) {
return KEY_NOT_FOUND;
}
// Decrypt into RSA private key.
//
// Generate key for PKCS#12 encryption, we use SHA1 with 1 iteration, as the
// parameters used in PK11_ExportEncryptedPrivKeyInfo() above.
// see: PKCS#12 v1.0, B.2.
//
uint8_t DSP[192] = {0};
memset(DSP, 0x01, 64); // Diversifier part, ID = 1 for decryption.
memset(DSP + 128, 0x00, 64); // Password part, no password.
uint8_t *S = &DSP[64]; // Salt part.
uint8_t *salt = encryptedPrivateKey->algorithm.parameters.data + 4;
int saltLength = (int)encryptedPrivateKey->algorithm.parameters.data[3];
if (saltLength <= 0) {
return SYSTEM_ERROR;
}
for (int i = 0; i < 64; i++) {
S[i] = salt[i % saltLength];
}
// Generate key by SHA-1
nsresult rv;
nsCOMPtr<nsICryptoHash> hash =
do_CreateInstance("@mozilla.org/security/hash;1", &rv);
if (NS_FAILED(rv)) {
return SYSTEM_ERROR;
}
rv = hash->Init(nsICryptoHash::SHA1);
if (NS_FAILED(rv)) {
return SYSTEM_ERROR;
}
rv = hash->Update(DSP, sizeof(DSP));
if (NS_FAILED(rv)) {
return SYSTEM_ERROR;
}
nsCString hashResult;
rv = hash->Finish(false, hashResult);
if (NS_FAILED(rv)) {
return SYSTEM_ERROR;
}
// First 40-bit as key for RC4.
uint8_t key[5];
memcpy(key, hashResult.get(), sizeof(key));
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
if (!slot) {
return SYSTEM_ERROR;
}
SECItem keyItem = {siBuffer, key, sizeof(key)};
ScopedPK11SymKey symKey(PK11_ImportSymKey(slot, CKM_RC4, PK11_OriginUnwrap,
CKA_DECRYPT, &keyItem, nullptr));
if (!symKey) {
return SYSTEM_ERROR;
}
// Get expected decrypted data size then allocate memory.
uint8_t *encryptedData = (uint8_t *)encryptedPrivateKey->encryptedData.data;
unsigned int encryptedDataLen = encryptedPrivateKey->encryptedData.len;
unsigned int decryptedDataLen = encryptedDataLen;
SECStatus srv = PK11_Decrypt(symKey, CKM_RC4, &keyItem, nullptr,
&decryptedDataLen, encryptedDataLen,
encryptedData, encryptedDataLen);
if (srv != SECSuccess) {
return SYSTEM_ERROR;
}
ScopedSECItem decryptedData(::SECITEM_AllocItem(nullptr, nullptr,
decryptedDataLen));
if (!decryptedData) {
return SYSTEM_ERROR;
}
// Decrypt by RC4.
srv = PK11_Decrypt(symKey, CKM_RC4, &keyItem, decryptedData->data,
&decryptedDataLen, decryptedData->len, encryptedData,
encryptedDataLen);
if (srv != SECSuccess) {
return SYSTEM_ERROR;
}
// Export key in PEM format.
char *keyPEM = PL_Base64Encode((const char *)decryptedData->data,
decryptedDataLen, nullptr);
if (!keyPEM) {
return SYSTEM_ERROR;
}
FormatCaData(keyPEM, strlen(keyPEM), "PRIVATE KEY", aKeyData, aKeyDataLength);
PL_strfree(keyPEM);
if (!(*aKeyData)) {
return SYSTEM_ERROR;
}
return SUCCESS;
}
ResponseCode getPublicKey(const char *aKeyName, const uint8_t **aKeyData,
size_t *aKeyDataLength)
{
*aKeyData = nullptr;
// Get corresponding user certificate nickname
char userCertName[128] = {0};
snprintf(userCertName, sizeof(userCertName) - 1, "WIFI_USERCERT_%s", aKeyName + 13);
// Get public key from user certificate.
ScopedCERTCertificate userCert(
CERT_FindCertByNickname(CERT_GetDefaultCertDB(), userCertName));
if (!userCert) {
return KEY_NOT_FOUND;
}
// Get public key.
ScopedSECKEYPublicKey publicKey(CERT_ExtractPublicKey(userCert));
if (!publicKey) {
return KEY_NOT_FOUND;
}
ScopedSECItem keyItem(PK11_DEREncodePublicKey(publicKey));
if (!keyItem) {
return KEY_NOT_FOUND;
}
size_t bufSize = keyItem->len;
char *buf = (char *)moz_malloc(bufSize);
if (!buf) {
return SYSTEM_ERROR;
}
memcpy(buf, keyItem->data, bufSize);
*aKeyData = (const uint8_t *)buf;
*aKeyDataLength = bufSize;
return SUCCESS;
}
ResponseCode signData(const char *aKeyName, const uint8_t *data, size_t length,
uint8_t **out, size_t *outLength)
{
*out = nullptr;
// Get corresponding user certificate nickname
char userCertName[128] = {0};
snprintf(userCertName, sizeof(userCertName) - 1, "WIFI_USERCERT_%s", aKeyName + 13);
// Get private key from user certificate.
ScopedCERTCertificate userCert(
CERT_FindCertByNickname(CERT_GetDefaultCertDB(), userCertName));
if (!userCert) {
return KEY_NOT_FOUND;
}
ScopedSECKEYPrivateKey privateKey(
PK11_FindKeyByAnyCert(userCert.get(), nullptr));
if (!privateKey) {
return KEY_NOT_FOUND;
}
//
// Find hash data from incoming data.
//
// Incoming data might be padded by PKCS-1 format:
// 00 01 FF FF ... FF 00 || Hash of length 36
// If the padding part exists, we have to ignore them.
//
uint8_t *hash = (uint8_t *)data;
const size_t HASH_LENGTH = 36;
if (length < HASH_LENGTH) {
return VALUE_CORRUPTED;
}
if (hash[0] == 0x00 && hash[1] == 0x01 && hash[2] == 0xFF && hash[3] == 0xFF) {
hash += 4;
while (*hash == 0xFF) {
if (hash + HASH_LENGTH > data + length) {
return VALUE_CORRUPTED;
}
hash++;
}
if (*hash != 0x00) {
return VALUE_CORRUPTED;
}
hash++;
}
if (hash + HASH_LENGTH != data + length) {
return VALUE_CORRUPTED;
}
SECItem hashItem = {siBuffer, hash, HASH_LENGTH};
// Sign hash.
ScopedSECItem signItem(::SECITEM_AllocItem(nullptr, nullptr,
PK11_SignatureLen(privateKey)));
if (!signItem) {
return SYSTEM_ERROR;
}
SECStatus srv;
srv = PK11_Sign(privateKey, signItem.get(), &hashItem);
if (srv != SECSuccess) {
return SYSTEM_ERROR;
}
uint8_t *buf = (uint8_t *)moz_malloc(signItem->len);
if (!buf) {
return SYSTEM_ERROR;
}
memcpy(buf, signItem->data, signItem->len);
*out = buf;
*outLength = signItem->len;
return SUCCESS;
}
@ -465,8 +836,15 @@ KeyStore::KeyStore()
KeyStore::~KeyStore()
{
nsNSSShutDownPreventionLock locker;
MOZ_COUNT_DTOR(KeyStore);
if (isAlreadyShutDown()) {
return;
}
shutdown(calledFromObject);
MOZ_ASSERT(!mListenSocket);
MOZ_ASSERT(!mStreamSocket);
}
@ -671,20 +1049,31 @@ KeyStore::ReceiveSocketData(nsAutoPtr<UnixSocketRawData>& aMessage)
break;
case STATE_PROCESSING:
if (mHandlerInfo.command == 'g') {
// Get CA
const uint8_t *certData;
int certDataLength;
const char *certName = (const char *)mHandlerInfo.param[0].data;
result = SYSTEM_ERROR;
result = getCertificate(certName, &certData, &certDataLength);
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown()) {
break;
}
// Get CA
const uint8_t *data;
size_t dataLength;
const char *name = (const char *)mHandlerInfo.param[0].data;
if (!strncmp(name, "WIFI_USERKEY_", 13)) {
result = getPrivateKey(name, &data, &dataLength);
} else {
result = getCertificate(name, &data, &dataLength);
}
if (result != SUCCESS) {
break;
}
SendResponse(SUCCESS);
SendData(certData, certDataLength);
SendData(data, (int)dataLength);
free((void *)certData);
moz_free((void *)data);
}
ResetHandlerInfo();

View File

@ -13,6 +13,7 @@
#include "mozilla/ipc/ListenSocket.h"
#include "mozilla/ipc/StreamSocket.h"
#include "mozilla/ipc/UnixSocketConnector.h"
#include "nsNSSShutDown.h"
namespace mozilla {
namespace ipc {
@ -36,10 +37,16 @@ enum ResponseCode {
void FormatCaData(const uint8_t *aCaData, int aCaDataLength,
const char *aName, const uint8_t **aFormatData,
int *aFormatDataLength);
size_t *aFormatDataLength);
ResponseCode getCertificate(const char *aCertName, const uint8_t **aCertData,
int *aCertDataLength);
size_t *aCertDataLength);
ResponseCode getPrivateKey(const char *aKeyName, const uint8_t **aKeyData,
size_t *aKeyDataLength);
ResponseCode getPublicKey(const char *aKeyName, const uint8_t **aKeyData,
size_t *aKeyDataLength);
ResponseCode signData(const char *aKeyName, const uint8_t *data, size_t length,
uint8_t **out, size_t *outLength);
bool checkPermission(uid_t uid);
@ -92,7 +99,7 @@ public:
nsAString& aAddrStr);
};
class KeyStore MOZ_FINAL
class KeyStore MOZ_FINAL : public nsNSSShutDownObject
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(KeyStore)
@ -101,6 +108,9 @@ public:
void Shutdown();
protected:
virtual void virtualDestroyNSSReference() {}
private:
enum SocketType {
LISTEN_SOCKET,

View File

@ -23,6 +23,7 @@
#include "keyhi.h"
#include "cryptohi.h"
#include "pk11pub.h"
#include "pkcs12.h"
#include "sechash.h"
#include "secpkcs7.h"
#include "secport.h"
@ -240,6 +241,9 @@ MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedSEC_PKCS7ContentInfo,
SEC_PKCS7ContentInfo,
SEC_PKCS7DestroyContentInfo)
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedSEC_PKCS12DecoderContext,
SEC_PKCS12DecoderContext,
SEC_PKCS12DecoderFinish)
namespace internal {
inline void
@ -307,6 +311,11 @@ inline void SECOID_DestroyAlgorithmID_true(SECAlgorithmID * a)
return SECOID_DestroyAlgorithmID(a, true);
}
inline void SECKEYEncryptedPrivateKeyInfo_true(SECKEYEncryptedPrivateKeyInfo * epki)
{
return SECKEY_DestroyEncryptedPrivateKeyInfo(epki, PR_TRUE);
}
} // namespace internal
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedSECItem,
@ -316,6 +325,9 @@ MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedSECItem,
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedSECKEYPrivateKey,
SECKEYPrivateKey,
SECKEY_DestroyPrivateKey)
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedSECKEYEncryptedPrivateKeyInfo,
SECKEYEncryptedPrivateKeyInfo,
internal::SECKEYEncryptedPrivateKeyInfo_true)
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedSECKEYPublicKey,
SECKEYPublicKey,
SECKEY_DestroyPublicKey)