Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F2837090
D11232.id38334.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
26 KB
Referenced Files
None
Subscribers
None
D11232.id38334.diff
View Options
diff --git a/native/cpp/CommonCpp/NativeModules/CommCoreModule.h b/native/cpp/CommonCpp/NativeModules/CommCoreModule.h
--- a/native/cpp/CommonCpp/NativeModules/CommCoreModule.h
+++ b/native/cpp/CommonCpp/NativeModules/CommCoreModule.h
@@ -28,7 +28,9 @@
const std::string secureStoreAccountDataKey = "cryptoAccountDataKey";
const std::string publicCryptoAccountID = "publicCryptoAccountID";
- std::unique_ptr<crypto::CryptoModule> cryptoModule;
+ std::unique_ptr<crypto::CryptoModule> contentCryptoModule;
+ const std::string notifsCryptoAccountID = "notifsCryptoAccountID";
+ std::unique_ptr<crypto::CryptoModule> notifsCryptoModule;
DraftStore draftStore;
ThreadStore threadStore;
MessageStore messageStore;
@@ -38,7 +40,8 @@
CommunityStore communityStore;
IntegrityStore integrityStore;
- void persistCryptoModule();
+ void
+ persistCryptoModules(bool persistContentModule, bool persistNotifsModule);
virtual jsi::Value getDraft(jsi::Runtime &rt, jsi::String key) override;
virtual jsi::Value
diff --git a/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp b/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp
--- a/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp
+++ b/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp
@@ -351,7 +351,9 @@
TerminateApp::terminate();
}
-void CommCoreModule::persistCryptoModule() {
+void CommCoreModule::persistCryptoModules(
+ bool persistContentModule,
+ bool persistNotifsModule) {
folly::Optional<std::string> storedSecretKey =
CommSecureStore::get(this->secureStoreAccountDataKey);
if (!storedSecretKey.hasValue()) {
@@ -360,17 +362,37 @@
this->secureStoreAccountDataKey, storedSecretKey.value());
}
- crypto::Persist newPersist =
- this->cryptoModule->storeAsB64(storedSecretKey.value());
+ if (!persistContentModule && !persistNotifsModule) {
+ return;
+ }
+
+ crypto::Persist newContentPersist;
+ if (persistContentModule) {
+ newContentPersist =
+ this->contentCryptoModule->storeAsB64(storedSecretKey.value());
+ }
+
+ crypto::Persist newNotifsPersist;
+ if (persistNotifsModule) {
+ newNotifsPersist =
+ this->notifsCryptoModule->storeAsB64(storedSecretKey.value());
+ }
std::promise<void> persistencePromise;
std::future<void> persistenceFuture = persistencePromise.get_future();
GlobalDBSingleton::instance.scheduleOrRunCancellable(
[=, &persistencePromise]() {
try {
- DatabaseManager::getQueryExecutor().storeOlmPersistData(
- DatabaseManager::getQueryExecutor().getContentAccountID(),
- newPersist);
+ if (persistContentModule) {
+ DatabaseManager::getQueryExecutor().storeOlmPersistData(
+ DatabaseManager::getQueryExecutor().getContentAccountID(),
+ newContentPersist);
+ }
+ if (persistNotifsModule) {
+ DatabaseManager::getQueryExecutor().storeOlmPersistData(
+ DatabaseManager::getQueryExecutor().getNotifsAccountID(),
+ newNotifsPersist);
+ }
persistencePromise.set_value();
} catch (std::system_error &e) {
persistencePromise.set_exception(std::make_exception_ptr(e));
@@ -391,15 +413,16 @@
return createPromiseAsJSIValue(
rt, [=](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
taskType job = [=]() {
- crypto::Persist persist;
+ crypto::Persist contentPersist;
+ crypto::Persist notifsPersist;
std::string error;
try {
- std::optional<std::string> accountData =
+ std::optional<std::string> contentAccountData =
DatabaseManager::getQueryExecutor().getOlmPersistAccountData(
DatabaseManager::getQueryExecutor().getContentAccountID());
- if (accountData.has_value()) {
- persist.account =
- crypto::OlmBuffer(accountData->begin(), accountData->end());
+ if (contentAccountData.has_value()) {
+ contentPersist.account = crypto::OlmBuffer(
+ contentAccountData->begin(), contentAccountData->end());
// handle sessions data
std::vector<OlmPersistSession> sessionsData =
DatabaseManager::getQueryExecutor()
@@ -408,65 +431,51 @@
crypto::OlmBuffer sessionDataBuffer(
sessionsDataItem.session_data.begin(),
sessionsDataItem.session_data.end());
- persist.sessions.insert(std::make_pair(
+ contentPersist.sessions.insert(std::make_pair(
sessionsDataItem.target_user_id, sessionDataBuffer));
}
}
+
+ std::optional<std::string> notifsAccountData =
+ DatabaseManager::getQueryExecutor().getOlmPersistAccountData(
+ DatabaseManager::getQueryExecutor().getNotifsAccountID());
+ if (notifsAccountData.has_value()) {
+ notifsPersist.account = crypto::OlmBuffer(
+ notifsAccountData->begin(), notifsAccountData->end());
+ }
+
} catch (std::system_error &e) {
error = e.what();
}
this->cryptoThread->scheduleTask([=]() {
std::string error;
- this->cryptoModule.reset(new crypto::CryptoModule(
- this->publicCryptoAccountID, storedSecretKey.value(), persist));
- if (persist.isEmpty()) {
- crypto::Persist newPersist =
- this->cryptoModule->storeAsB64(storedSecretKey.value());
- GlobalDBSingleton::instance.scheduleOrRunCancellable(
- [=]() {
- std::string error;
- try {
- DatabaseManager::getQueryExecutor().storeOlmPersistData(
- DatabaseManager::getQueryExecutor()
- .getContentAccountID(),
- newPersist);
- } catch (std::system_error &e) {
- error = e.what();
- }
- this->jsInvoker_->invokeAsync([=]() {
- if (error.size()) {
- promise->reject(error);
- return;
- }
- });
- },
- promise,
- this->jsInvoker_);
+ this->contentCryptoModule.reset(new crypto::CryptoModule(
+ this->publicCryptoAccountID,
+ storedSecretKey.value(),
+ contentPersist));
+
+ this->notifsCryptoModule.reset(new crypto::CryptoModule(
+ this->notifsCryptoAccountID,
+ storedSecretKey.value(),
+ notifsPersist));
- } else {
- this->cryptoModule->restoreFromB64(
- storedSecretKey.value(), persist);
- this->jsInvoker_->invokeAsync([=]() {
- if (error.size()) {
- promise->reject(error);
- return;
- }
- });
- }
try {
- NotificationsCryptoModule::initializeNotificationsCryptoAccount(
- "Comm");
+ this->persistCryptoModules(
+ contentPersist.isEmpty(), notifsPersist.isEmpty());
} catch (const std::exception &e) {
error = e.what();
}
+
this->jsInvoker_->invokeAsync([=]() {
if (error.size()) {
promise->reject(error);
return;
}
- promise->resolve(jsi::Value::undefined());
});
+
+ this->jsInvoker_->invokeAsync(
+ [=]() { promise->resolve(jsi::Value::undefined()); });
});
};
GlobalDBSingleton::instance.scheduleOrRunCancellable(
@@ -481,19 +490,13 @@
std::string error;
std::string primaryKeysResult;
std::string notificationsKeysResult;
- if (this->cryptoModule == nullptr) {
+ if (this->contentCryptoModule == nullptr ||
+ this->notifsCryptoModule == nullptr) {
error = "user has not been initialized";
} else {
- primaryKeysResult = this->cryptoModule->getIdentityKeys();
- }
- try {
- if (!error.size()) {
- notificationsKeysResult =
- NotificationsCryptoModule::getNotificationsIdentityKeys(
- "Comm");
- }
- } catch (const std::exception &e) {
- error = e.what();
+ primaryKeysResult = this->contentCryptoModule->getIdentityKeys();
+ notificationsKeysResult =
+ this->notifsCryptoModule->getIdentityKeys();
}
std::string notificationsCurve25519Cpp, notificationsEd25519Cpp,
@@ -534,7 +537,8 @@
"curve25519", notificationsCurve25519Cpp));
blobPayloadCpp = folly::toJson(blobPayloadJSON);
- signatureCpp = this->cryptoModule->signMessage(blobPayloadCpp);
+ signatureCpp =
+ this->contentCryptoModule->signMessage(blobPayloadCpp);
}
}
}
@@ -650,19 +654,20 @@
std::string error;
std::string contentResult;
std::string notifResult;
- if (this->cryptoModule == nullptr) {
+ if (this->contentCryptoModule == nullptr ||
+ this->notifsCryptoModule == nullptr) {
this->jsInvoker_->invokeAsync([=, &innerRt]() {
promise->reject("user has not been initialized");
});
return;
}
try {
- contentResult = this->cryptoModule->getOneTimeKeysForPublishing(
+ contentResult =
+ this->contentCryptoModule->getOneTimeKeysForPublishing(
+ oneTimeKeysAmount);
+ notifResult = this->notifsCryptoModule->getOneTimeKeysForPublishing(
oneTimeKeysAmount);
- this->persistCryptoModule();
- notifResult = NotificationsCryptoModule::
- getNotificationsOneTimeKeysForPublishing(
- oneTimeKeysAmount, "Comm");
+ this->persistCryptoModules(true, true);
} catch (const std::exception &e) {
error = e.what();
}
@@ -679,18 +684,6 @@
});
}
-std::pair<std::string, std::string> getNotificationsPrekeyAndSignature() {
- // TODO: Implement notifs prekey rotation.
- // Notifications prekey is not rotated at this moment. It
- // is fetched with signature to match identity service API.
- std::string notificationsPrekey =
- NotificationsCryptoModule::getNotificationsPrekey("Comm");
- std::string notificationsPrekeySignature =
- NotificationsCryptoModule::getNotificationsPrekeySignature("Comm");
-
- return std::make_pair(notificationsPrekey, notificationsPrekeySignature);
-}
-
jsi::Value CommCoreModule::validateAndUploadPrekeys(
jsi::Runtime &rt,
jsi::String authUserID,
@@ -703,9 +696,11 @@
rt, [=](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
taskType job = [=, &innerRt]() {
std::string error;
- std::optional<std::string> maybePrekeyToUpload;
+ std::optional<std::string> maybeContentPrekeyToUpload;
+ std::optional<std::string> maybeNotifsPrekeyToUpload;
- if (this->cryptoModule == nullptr) {
+ if (this->contentCryptoModule == nullptr ||
+ this->notifsCryptoModule == nullptr) {
this->jsInvoker_->invokeAsync([=, &innerRt]() {
promise->reject("user has not been initialized");
});
@@ -713,10 +708,19 @@
}
try {
- maybePrekeyToUpload = this->cryptoModule->validatePrekey();
- this->persistCryptoModule();
- if (!maybePrekeyToUpload.has_value()) {
- maybePrekeyToUpload = this->cryptoModule->getUnpublishedPrekey();
+ maybeContentPrekeyToUpload =
+ this->contentCryptoModule->validatePrekey();
+ maybeNotifsPrekeyToUpload =
+ this->notifsCryptoModule->validatePrekey();
+ this->persistCryptoModules(true, true);
+
+ if (!maybeContentPrekeyToUpload.has_value()) {
+ maybeContentPrekeyToUpload =
+ this->contentCryptoModule->getUnpublishedPrekey();
+ }
+ if (!maybeNotifsPrekeyToUpload.has_value()) {
+ maybeNotifsPrekeyToUpload =
+ this->notifsCryptoModule->getUnpublishedPrekey();
}
} catch (const std::exception &e) {
error = e.what();
@@ -726,21 +730,36 @@
this->jsInvoker_->invokeAsync(
[=, &innerRt]() { promise->reject(error); });
return;
- } else if (!maybePrekeyToUpload.has_value()) {
+ }
+
+ if (!maybeContentPrekeyToUpload.has_value() &&
+ !maybeNotifsPrekeyToUpload.has_value()) {
this->jsInvoker_->invokeAsync(
[=]() { promise->resolve(jsi::Value::undefined()); });
return;
}
- std::string prekeyToUpload = maybePrekeyToUpload.value();
+ std::string contentPrekeyToUpload;
+ if (maybeContentPrekeyToUpload.has_value()) {
+ contentPrekeyToUpload = maybeContentPrekeyToUpload.value();
+ } else {
+ contentPrekeyToUpload = this->contentCryptoModule->getPrekey();
+ }
+
+ std::string notifsPrekeyToUpload;
+ if (maybeNotifsPrekeyToUpload.has_value()) {
+ notifsPrekeyToUpload = maybeNotifsPrekeyToUpload.value();
+ } else {
+ notifsPrekeyToUpload = this->notifsCryptoModule->getPrekey();
+ }
+
std::string prekeyUploadError;
try {
- std::string prekeySignature =
- this->cryptoModule->getPrekeySignature();
- std::string notificationsPrekey, notificationsPrekeySignature;
- std::tie(notificationsPrekey, notificationsPrekeySignature) =
- getNotificationsPrekeyAndSignature();
+ std::string contentPrekeySignature =
+ this->contentCryptoModule->getPrekeySignature();
+ std::string notifsPrekeySignature =
+ this->notifsCryptoModule->getPrekeySignature();
try {
std::promise<folly::dynamic> prekeyPromise;
@@ -750,20 +769,20 @@
std::move(prekeyPromise)};
auto currentID = RustPromiseManager::instance.addPromise(
std::move(promiseInfo));
- auto prekeyToUploadRust =
- rust::String(parseOLMPrekey(prekeyToUpload));
- auto prekeySignatureRust = rust::string(prekeySignature);
- auto notificationsPrekeyRust =
- rust::String(parseOLMPrekey(notificationsPrekey));
+ auto contentPrekeyToUploadRust =
+ rust::String(parseOLMPrekey(contentPrekeyToUpload));
+ auto prekeySignatureRust = rust::string(contentPrekeySignature);
+ auto notifsPrekeyToUploadRust =
+ rust::String(parseOLMPrekey(notifsPrekeyToUpload));
auto notificationsPrekeySignatureRust =
- rust::string(notificationsPrekeySignature);
+ rust::string(notifsPrekeySignature);
::identityRefreshUserPrekeys(
authUserIDRust,
authDeviceIDRust,
authAccessTokenRust,
- prekeyToUploadRust,
+ contentPrekeyToUploadRust,
prekeySignatureRust,
- notificationsPrekeyRust,
+ notifsPrekeyToUploadRust,
notificationsPrekeySignatureRust,
currentID);
prekeyFuture.get();
@@ -772,8 +791,9 @@
}
if (!prekeyUploadError.size()) {
- this->cryptoModule->markPrekeyAsPublished();
- this->persistCryptoModule();
+ this->contentCryptoModule->markPrekeyAsPublished();
+ this->notifsCryptoModule->markPrekeyAsPublished();
+ this->persistCryptoModules(true, true);
}
} catch (std::exception &e) {
error = e.what();
@@ -801,32 +821,44 @@
taskType job = [=, &innerRt]() {
std::string error;
std::string contentPrekey, notifPrekey, contentPrekeySignature,
- notifPrekeyBlob, notifPrekeySignature;
+ notifPrekeySignature;
std::optional<std::string> contentPrekeyBlob;
+ std::optional<std::string> notifPrekeyBlob;
- if (this->cryptoModule == nullptr) {
+ if (this->contentCryptoModule == nullptr ||
+ this->notifsCryptoModule == nullptr) {
this->jsInvoker_->invokeAsync([=, &innerRt]() {
promise->reject("user has not been initialized");
});
return;
}
try {
- contentPrekeyBlob = this->cryptoModule->validatePrekey();
+ contentPrekeyBlob = this->contentCryptoModule->validatePrekey();
if (!contentPrekeyBlob) {
- contentPrekeyBlob = this->cryptoModule->getUnpublishedPrekey();
+ contentPrekeyBlob =
+ this->contentCryptoModule->getUnpublishedPrekey();
}
if (!contentPrekeyBlob) {
- contentPrekeyBlob = this->cryptoModule->getPrekey();
+ contentPrekeyBlob = this->contentCryptoModule->getPrekey();
}
- this->persistCryptoModule();
- contentPrekeySignature = this->cryptoModule->getPrekeySignature();
+ notifPrekeyBlob = this->notifsCryptoModule->validatePrekey();
+ if (!notifPrekeyBlob) {
+ notifPrekeyBlob =
+ this->notifsCryptoModule->getUnpublishedPrekey();
+ }
+ if (!notifPrekeyBlob) {
+ notifPrekeyBlob = this->notifsCryptoModule->getPrekey();
+ }
+ this->persistCryptoModules(true, true);
- std::tie(notifPrekeyBlob, notifPrekeySignature) =
- getNotificationsPrekeyAndSignature();
+ contentPrekeySignature =
+ this->contentCryptoModule->getPrekeySignature();
+ notifPrekeySignature =
+ this->notifsCryptoModule->getPrekeySignature();
contentPrekey = parseOLMPrekey(contentPrekeyBlob.value());
- notifPrekey = parseOLMPrekey(notifPrekeyBlob);
+ notifPrekey = parseOLMPrekey(notifPrekeyBlob.value());
} catch (const std::exception &e) {
error = e.what();
}
@@ -880,6 +912,9 @@
std::string error;
crypto::EncryptedData result;
try {
+ // Introduced temporarily to make this diff non-breaking change
+ NotificationsCryptoModule::initializeNotificationsCryptoAccount(
+ "Comm");
result = NotificationsCryptoModule::initializeNotificationsSession(
identityKeysCpp,
prekeyCpp,
@@ -1075,7 +1110,7 @@
std::string error;
crypto::EncryptedData initialEncryptedMessage;
try {
- this->cryptoModule->initializeOutboundForSendingSession(
+ this->contentCryptoModule->initializeOutboundForSendingSession(
deviceIDCpp,
std::vector<uint8_t>(
identityKeysCpp.begin(), identityKeysCpp.end()),
@@ -1087,8 +1122,8 @@
const std::string initMessage = "{\"type\": \"init\"}";
initialEncryptedMessage =
- cryptoModule->encrypt(deviceIDCpp, initMessage);
- this->persistCryptoModule();
+ contentCryptoModule->encrypt(deviceIDCpp, initMessage);
+ this->persistCryptoModules(true, false);
} catch (const std::exception &e) {
error = e.what();
}
@@ -1122,7 +1157,7 @@
std::string error;
std::string decryptedMessage;
try {
- this->cryptoModule->initializeInboundForReceivingSession(
+ this->contentCryptoModule->initializeInboundForReceivingSession(
deviceIDCpp,
std::vector<uint8_t>(
encryptedMessageCpp.begin(), encryptedMessageCpp.end()),
@@ -1131,8 +1166,8 @@
crypto::EncryptedData encryptedData{std::vector<uint8_t>(
encryptedMessageCpp.begin(), encryptedMessageCpp.end())};
decryptedMessage =
- cryptoModule->decrypt(deviceIDCpp, encryptedData);
- this->persistCryptoModule();
+ this->contentCryptoModule->decrypt(deviceIDCpp, encryptedData);
+ this->persistCryptoModules(true, false);
} catch (const std::exception &e) {
error = e.what();
}
@@ -1161,8 +1196,9 @@
std::string error;
crypto::EncryptedData encryptedMessage;
try {
- encryptedMessage = cryptoModule->encrypt(deviceIDCpp, messageCpp);
- this->persistCryptoModule();
+ encryptedMessage =
+ contentCryptoModule->encrypt(deviceIDCpp, messageCpp);
+ this->persistCryptoModules(true, false);
} catch (const std::exception &e) {
error = e.what();
}
@@ -1198,8 +1234,8 @@
std::vector<uint8_t>(messageCpp.begin(), messageCpp.end()),
ENCRYPTED_MESSAGE_TYPE};
decryptedMessage =
- cryptoModule->decrypt(deviceIDCpp, encryptedData);
- this->persistCryptoModule();
+ this->contentCryptoModule->decrypt(deviceIDCpp, encryptedData);
+ this->persistCryptoModules(true, false);
} catch (const std::exception &e) {
error = e.what();
}
@@ -1224,7 +1260,7 @@
std::string error;
std::string signature;
try {
- signature = this->cryptoModule->signMessage(messageStr);
+ signature = this->contentCryptoModule->signMessage(messageStr);
} catch (const std::exception &e) {
error = "signing message failed with: " + std::string(e.what());
}
@@ -1650,7 +1686,7 @@
try {
pickleKey = crypto::Tools::generateRandomString(64);
crypto::Persist persist =
- this->cryptoModule->storeAsB64(pickleKey);
+ this->contentCryptoModule->storeAsB64(pickleKey);
pickledAccount =
std::string(persist.account.begin(), persist.account.end());
} catch (const std::exception &e) {
diff --git a/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.h b/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.h
--- a/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.h
+++ b/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.h
@@ -31,15 +31,6 @@
static void
initializeNotificationsCryptoAccount(const std::string &callingProcessName);
static void clearSensitiveData();
- static std::string
- getNotificationsIdentityKeys(const std::string &callingProcessName);
- static std::string
- getNotificationsPrekey(const std::string &callingProcessName);
- static std::string
- getNotificationsPrekeySignature(const std::string &callingProcessName);
- static std::string getNotificationsOneTimeKeysForPublishing(
- const size_t oneTimeKeysAmount,
- const std::string &callingProcessName);
static crypto::EncryptedData initializeNotificationsSession(
const std::string &identityKeys,
const std::string &prekey,
diff --git a/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.cpp b/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.cpp
--- a/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.cpp
+++ b/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.cpp
@@ -192,51 +192,6 @@
callingProcessName);
}
-std::string NotificationsCryptoModule::getNotificationsIdentityKeys(
- const std::string &callingProcessName) {
- std::string identityKeys;
- auto caller = [&identityKeys](
- const std::unique_ptr<crypto::CryptoModule> &cryptoModule) {
- identityKeys = cryptoModule->getIdentityKeys();
- };
- NotificationsCryptoModule::callCryptoModule(caller, callingProcessName);
- return identityKeys;
-}
-
-std::string NotificationsCryptoModule::getNotificationsPrekey(
- const std::string &callingProcessName) {
- std::string prekey;
- auto caller =
- [&prekey](const std::unique_ptr<crypto::CryptoModule> &cryptoModule) {
- prekey = cryptoModule->getPrekey();
- };
- NotificationsCryptoModule::callCryptoModule(caller, callingProcessName);
- return prekey;
-}
-
-std::string NotificationsCryptoModule::getNotificationsPrekeySignature(
- const std::string &callingProcessName) {
- std::string prekeySignature;
- auto caller = [&prekeySignature](
- const std::unique_ptr<crypto::CryptoModule> &cryptoModule) {
- prekeySignature = cryptoModule->getPrekeySignature();
- };
- NotificationsCryptoModule::callCryptoModule(caller, callingProcessName);
- return prekeySignature;
-}
-
-std::string NotificationsCryptoModule::getNotificationsOneTimeKeysForPublishing(
- const size_t oneTimeKeysAmount,
- const std::string &callingProcessName) {
- std::string oneTimeKeys;
- auto caller = [&oneTimeKeys, oneTimeKeysAmount](
- const std::unique_ptr<crypto::CryptoModule> &cryptoModule) {
- oneTimeKeys = cryptoModule->getOneTimeKeysForPublishing(oneTimeKeysAmount);
- };
- NotificationsCryptoModule::callCryptoModule(caller, callingProcessName);
- return oneTimeKeys;
-}
-
crypto::EncryptedData NotificationsCryptoModule::initializeNotificationsSession(
const std::string &identityKeys,
const std::string &prekey,
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Sep 29, 5:50 PM (19 h, 33 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2201979
Default Alt Text
D11232.id38334.diff (26 KB)
Attached To
Mode
D11232: Introduce notifications crypto module to CommCoreModule
Attached
Detach File
Event Timeline
Log In to Comment