зеркало из https://github.com/mozilla/gecko-dev.git
Merge b2g-inbound to m-c a=merge CLOSED TREE
This commit is contained in:
Коммит
0de76a4c17
|
@ -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>
|
||||
|
|
|
@ -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"/>
|
||||
|
|
|
@ -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"/>
|
||||
|
|
|
@ -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"/>
|
||||
|
|
|
@ -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"/>
|
||||
|
|
|
@ -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"/>
|
||||
|
|
|
@ -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"/>
|
||||
|
|
|
@ -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"/>
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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"/>
|
||||
|
|
|
@ -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"/>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -111,6 +111,8 @@ public:
|
|||
IMPL_EVENT_HANDLER(stksessionend)
|
||||
|
||||
private:
|
||||
~Icc() {}
|
||||
|
||||
bool mLive;
|
||||
uint32_t mClientId;
|
||||
nsString mIccId;
|
||||
|
|
|
@ -124,7 +124,7 @@ let FormVisibility = {
|
|||
let visible = this.yAxisVisible(
|
||||
adjustedTop,
|
||||
pos.height,
|
||||
pos.width
|
||||
offset.height
|
||||
);
|
||||
|
||||
if (!visible)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче