use of org.matrix.androidsdk.rest.model.crypto.KeysQueryResponse in project matrix-android-sdk by matrix-org.
the class MXDeviceList method doKeyDownloadForUsers.
/**
* Download the devices keys for a set of users.
* It must be called in getEncryptingThreadHandler() thread.
* The callback is called in the UI thread.
*
* @param downloadUsers the user ids list
* @param callback the asynchronous callback
*/
private void doKeyDownloadForUsers(final List<String> downloadUsers, final ApiCallback<MXUsersDevicesMap<MXDeviceInfo>> callback) {
Log.d(LOG_TAG, "## doKeyDownloadForUsers() : doKeyDownloadForUsers " + downloadUsers);
// get the user ids which did not already trigger a keys download
final List<String> filteredUsers = addDownloadKeysPromise(downloadUsers, callback);
// if there is no new keys request
if (0 == filteredUsers.size()) {
// trigger nothing
return;
}
// sanity check
if ((null == mxSession.getDataHandler()) || (null == mxSession.getDataHandler().getStore())) {
return;
}
mIsDownloadingKeys = true;
// track the race condition while sending requests
// we defines a tag for each request
// and test if the response is the latest request one
final String downloadToken = filteredUsers.hashCode() + " " + System.currentTimeMillis();
for (String userId : filteredUsers) {
mPendingDownloadKeysRequestToken.put(userId, downloadToken);
}
mxSession.getCryptoRestClient().downloadKeysForUsers(filteredUsers, mxSession.getDataHandler().getStore().getEventStreamToken(), new ApiCallback<KeysQueryResponse>() {
@Override
public void onSuccess(final KeysQueryResponse keysQueryResponse) {
mxCrypto.getEncryptingThreadHandler().post(new Runnable() {
@Override
public void run() {
Log.d(LOG_TAG, "## doKeyDownloadForUsers() : Got keys for " + filteredUsers.size() + " users");
MXDeviceInfo myDevice = mxCrypto.getMyDevice();
IMXCryptoStore cryptoStore = mxCrypto.getCryptoStore();
List<String> userIdsList = new ArrayList<>(filteredUsers);
for (String userId : userIdsList) {
// test if the response is the latest request one
if (!TextUtils.equals(mPendingDownloadKeysRequestToken.get(userId), downloadToken)) {
Log.e(LOG_TAG, "## doKeyDownloadForUsers() : Another update in the queue for " + userId + " not marking up-to-date");
filteredUsers.remove(userId);
} else {
Map<String, MXDeviceInfo> devices = keysQueryResponse.deviceKeys.get(userId);
Log.d(LOG_TAG, "## doKeyDownloadForUsers() : Got keys for " + userId + " : " + devices);
if (null != devices) {
HashMap<String, MXDeviceInfo> mutableDevices = new HashMap<>(devices);
ArrayList<String> deviceIds = new ArrayList<>(mutableDevices.keySet());
for (String deviceId : deviceIds) {
// the user has been logged out
if (null == cryptoStore) {
break;
}
// Get the potential previously store device keys for this device
MXDeviceInfo previouslyStoredDeviceKeys = cryptoStore.getUserDevice(deviceId, userId);
MXDeviceInfo deviceInfo = mutableDevices.get(deviceId);
// the self device must be seen as verified
if (TextUtils.equals(deviceInfo.deviceId, myDevice.deviceId) && TextUtils.equals(userId, myDevice.userId)) {
deviceInfo.mVerified = MXDeviceInfo.DEVICE_VERIFICATION_VERIFIED;
}
// Validate received keys
if (!validateDeviceKeys(deviceInfo, userId, deviceId, previouslyStoredDeviceKeys)) {
// New device keys are not valid. Do not store them
mutableDevices.remove(deviceId);
if (null != previouslyStoredDeviceKeys) {
// But keep old validated ones if any
mutableDevices.put(deviceId, previouslyStoredDeviceKeys);
}
} else if (null != previouslyStoredDeviceKeys) {
// The verified status is not sync'ed with hs.
// This is a client side information, valid only for this client.
// So, transfer its previous value
mutableDevices.get(deviceId).mVerified = previouslyStoredDeviceKeys.mVerified;
}
}
// Update the store
// Note that devices which aren't in the response will be removed from the stores
cryptoStore.storeUserDevices(userId, mutableDevices);
}
// the response is the latest request one
mPendingDownloadKeysRequestToken.remove(userId);
}
}
onKeysDownloadSucceed(filteredUsers, keysQueryResponse.failures);
}
});
}
private void onFailed() {
mxCrypto.getEncryptingThreadHandler().post(new Runnable() {
@Override
public void run() {
List<String> userIdsList = new ArrayList<>(filteredUsers);
// test if the response is the latest request one
for (String userId : userIdsList) {
if (!TextUtils.equals(mPendingDownloadKeysRequestToken.get(userId), downloadToken)) {
Log.e(LOG_TAG, "## doKeyDownloadForUsers() : Another update in the queue for " + userId + " not marking up-to-date");
filteredUsers.remove(userId);
} else {
// the response is the latest request one
mPendingDownloadKeysRequestToken.remove(userId);
}
}
onKeysDownloadFailed(filteredUsers);
}
});
}
@Override
public void onNetworkError(Exception e) {
Log.e(LOG_TAG, "##doKeyDownloadForUsers() : onNetworkError " + e.getMessage());
onFailed();
if (null != callback) {
callback.onNetworkError(e);
}
}
@Override
public void onMatrixError(MatrixError e) {
Log.e(LOG_TAG, "##doKeyDownloadForUsers() : onMatrixError " + e.getMessage());
onFailed();
if (null != callback) {
callback.onMatrixError(e);
}
}
@Override
public void onUnexpectedError(Exception e) {
Log.e(LOG_TAG, "##doKeyDownloadForUsers() : onUnexpectedError " + e.getMessage());
onFailed();
if (null != callback) {
callback.onUnexpectedError(e);
}
}
});
}
use of org.matrix.androidsdk.rest.model.crypto.KeysQueryResponse in project matrix-android-sdk by matrix-org.
the class CryptoRestTest method test01_testDeviceKeys.
public void test01_testDeviceKeys() throws Exception {
Context context = InstrumentationRegistry.getContext();
createBobAccount();
final HashMap<String, Object> results = new HashMap<>();
String ed25519key = "wV5E3EUSHpHuoZLljNzojlabjGdXT3Mz7rugG9zgbkI";
MXDeviceInfo bobDevice = new MXDeviceInfo("dev1");
bobDevice.userId = mBobSession.getMyUserId();
bobDevice.algorithms = Arrays.asList(MXCryptoAlgorithms.MXCRYPTO_ALGORITHM_OLM);
HashMap<String, String> keysMap = new HashMap();
keysMap.put("ed25519:" + bobDevice.deviceId, ed25519key);
bobDevice.keys = keysMap;
final CountDownLatch lock0 = new CountDownLatch(1);
mBobSession.getCryptoRestClient().uploadKeys(bobDevice.JSONDictionary(), null, "dev1", new ApiCallback<KeysUploadResponse>() {
@Override
public void onSuccess(KeysUploadResponse keysUploadResponse) {
results.put("keysUploadResponse", keysUploadResponse);
lock0.countDown();
}
@Override
public void onNetworkError(Exception e) {
lock0.countDown();
}
@Override
public void onMatrixError(MatrixError e) {
lock0.countDown();
}
@Override
public void onUnexpectedError(Exception e) {
lock0.countDown();
}
});
lock0.await(1000, TimeUnit.MILLISECONDS);
KeysUploadResponse keysUploadResponse = (KeysUploadResponse) results.get("keysUploadResponse");
assertTrue(null != keysUploadResponse);
assertTrue(null != keysUploadResponse.oneTimeKeyCounts);
assertTrue(0 == keysUploadResponse.oneTimeKeyCounts.size());
assertTrue(0 == keysUploadResponse.oneTimeKeyCountsForAlgorithm("deded"));
final CountDownLatch lock1 = new CountDownLatch(1);
mBobSession.getCryptoRestClient().downloadKeysForUsers(Arrays.asList(mBobSession.getMyUserId()), null, new ApiCallback<KeysQueryResponse>() {
@Override
public void onSuccess(KeysQueryResponse keysQueryResponse) {
results.put("keysQueryResponse", keysQueryResponse);
lock1.countDown();
}
@Override
public void onNetworkError(Exception e) {
lock1.countDown();
}
@Override
public void onMatrixError(MatrixError e) {
lock1.countDown();
}
@Override
public void onUnexpectedError(Exception e) {
lock1.countDown();
}
});
lock1.await(1000, TimeUnit.MILLISECONDS);
KeysQueryResponse keysQueryResponse = (KeysQueryResponse) results.get("keysQueryResponse");
assertTrue(null != keysQueryResponse);
assertTrue(null != keysQueryResponse.deviceKeys);
MXUsersDevicesMap<MXDeviceInfo> deviceInfos = new MXUsersDevicesMap<>(keysQueryResponse.deviceKeys);
assertTrue(null != deviceInfos.getUserIds());
assertTrue(1 == deviceInfos.getUserIds().size());
List<String> deviceIds = deviceInfos.getUserDeviceIds(mBobSession.getMyUserId());
assertTrue(null != deviceIds);
assertTrue(1 == deviceIds.size());
MXDeviceInfo bobDevice2 = deviceInfos.getObject("dev1", mBobSession.getMyUserId());
assertTrue(null != bobDevice2);
assertTrue(TextUtils.equals(bobDevice2.deviceId, "dev1"));
assertTrue(TextUtils.equals(bobDevice2.userId, mBobSession.getMyUserId()));
mBobSession.clear(context);
}
Aggregations