Search in sources :

Example 1 with KeysQueryResponse

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);
            }
        }
    });
}
Also used : IMXCryptoStore(org.matrix.androidsdk.data.cryptostore.IMXCryptoStore) HashMap(java.util.HashMap) MXDeviceInfo(org.matrix.androidsdk.crypto.data.MXDeviceInfo) ArrayList(java.util.ArrayList) KeysQueryResponse(org.matrix.androidsdk.rest.model.crypto.KeysQueryResponse) MatrixError(org.matrix.androidsdk.rest.model.MatrixError)

Example 2 with KeysQueryResponse

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);
}
Also used : Context(android.content.Context) KeysUploadResponse(org.matrix.androidsdk.rest.model.crypto.KeysUploadResponse) HashMap(java.util.HashMap) MXDeviceInfo(org.matrix.androidsdk.crypto.data.MXDeviceInfo) CountDownLatch(java.util.concurrent.CountDownLatch) MXUsersDevicesMap(org.matrix.androidsdk.crypto.data.MXUsersDevicesMap) KeysQueryResponse(org.matrix.androidsdk.rest.model.crypto.KeysQueryResponse) MatrixError(org.matrix.androidsdk.rest.model.MatrixError)

Aggregations

HashMap (java.util.HashMap)2 MXDeviceInfo (org.matrix.androidsdk.crypto.data.MXDeviceInfo)2 MatrixError (org.matrix.androidsdk.rest.model.MatrixError)2 KeysQueryResponse (org.matrix.androidsdk.rest.model.crypto.KeysQueryResponse)2 Context (android.content.Context)1 ArrayList (java.util.ArrayList)1 CountDownLatch (java.util.concurrent.CountDownLatch)1 MXUsersDevicesMap (org.matrix.androidsdk.crypto.data.MXUsersDevicesMap)1 IMXCryptoStore (org.matrix.androidsdk.data.cryptostore.IMXCryptoStore)1 KeysUploadResponse (org.matrix.androidsdk.rest.model.crypto.KeysUploadResponse)1