Search in sources :

Example 1 with MXCryptoError

use of org.matrix.androidsdk.crypto.MXCryptoError in project matrix-android-sdk by matrix-org.

the class CryptoTest method test07_testAliceAndBobInACryptedRoom.

@Test
public void test07_testAliceAndBobInACryptedRoom() throws Exception {
    Log.e(LOG_TAG, "test07_testAliceAndBobInACryptedRoom");
    Context context = InstrumentationRegistry.getContext();
    final HashMap<String, Object> results = new HashMap<>();
    doE2ETestWithAliceAndBobInARoom(true);
    final String messageFromAlice = "Hello I'm Alice!";
    Room roomFromBobPOV = mBobSession.getDataHandler().getRoom(mRoomId);
    Room roomFromAlicePOV = mAliceSession.getDataHandler().getRoom(mRoomId);
    assertTrue(roomFromBobPOV.isEncrypted());
    assertTrue(roomFromAlicePOV.isEncrypted());
    final CountDownLatch lock1 = new CountDownLatch(1);
    roomFromAlicePOV.sendEvent(buildTextEvent(messageFromAlice, mAliceSession), new ApiCallback<Void>() {

        @Override
        public void onSuccess(Void info) {
            lock1.countDown();
        }

        @Override
        public void onNetworkError(Exception e) {
            lock1.countDown();
        }

        @Override
        public void onMatrixError(MatrixError e) {
            results.put("sendEventError", e);
            lock1.countDown();
        }

        @Override
        public void onUnexpectedError(Exception e) {
            lock1.countDown();
        }
    });
    lock1.await(2000, TimeUnit.MILLISECONDS);
    assertTrue(results.containsKey("sendEventError"));
    MXCryptoError error = (MXCryptoError) results.get("sendEventError");
    assertTrue(TextUtils.equals(error.errcode, MXCryptoError.UNKNOWN_DEVICES_CODE));
    MXUsersDevicesMap<MXDeviceInfo> unknownDevices = (MXUsersDevicesMap<MXDeviceInfo>) error.mExceptionData;
    List<String> deviceInfos = unknownDevices.getUserDeviceIds(mBobSession.getMyUserId());
    assertTrue(1 == deviceInfos.size());
    assertTrue(TextUtils.equals(deviceInfos.get(0), mBobSession.getCrypto().getMyDevice().deviceId));
    final CountDownLatch lock2 = new CountDownLatch(1);
    mAliceSession.getCrypto().setDevicesKnown(Arrays.asList(mBobSession.getCrypto().getMyDevice()), new ApiCallback<Void>() {

        @Override
        public void onSuccess(Void info) {
            results.put("setDevicesKnown", "setDevicesKnown");
            lock2.countDown();
        }

        @Override
        public void onNetworkError(Exception e) {
            lock2.countDown();
        }

        @Override
        public void onMatrixError(MatrixError e) {
            lock2.countDown();
        }

        @Override
        public void onUnexpectedError(Exception e) {
            lock2.countDown();
        }
    });
    lock2.await(2000, TimeUnit.MILLISECONDS);
    assertTrue(results.containsKey("setDevicesKnown"));
    final CountDownLatch lock3 = new CountDownLatch(3);
    MXEventListener eventListener = new MXEventListener() {

        @Override
        public void onLiveEvent(Event event, RoomState roomState) {
            try {
                if (TextUtils.equals(event.getType(), Event.EVENT_TYPE_MESSAGE)) {
                    if (checkEncryptedEvent(event, mRoomId, messageFromAlice, mAliceSession)) {
                        results.put("onLiveEvent", "onLiveEvent");
                        lock3.countDown();
                    }
                }
            } catch (Exception e) {
            }
        }
    };
    mBobSession.getDataHandler().addListener(new MXEventListener() {

        @Override
        public void onToDeviceEvent(Event event) {
            results.put("onToDeviceEvent", event);
            lock3.countDown();
        }
    });
    roomFromBobPOV.addEventListener(eventListener);
    roomFromAlicePOV.sendEvent(buildTextEvent(messageFromAlice, mAliceSession), new ApiCallback<Void>() {

        @Override
        public void onSuccess(Void info) {
            lock3.countDown();
        }

        @Override
        public void onNetworkError(Exception e) {
            lock3.countDown();
        }

        @Override
        public void onMatrixError(MatrixError e) {
            lock3.countDown();
        }

        @Override
        public void onUnexpectedError(Exception e) {
            lock3.countDown();
        }
    });
    lock3.await(2000, TimeUnit.MILLISECONDS);
    assertTrue(results.containsKey("onToDeviceEvent"));
    assertTrue(results.containsKey("onLiveEvent"));
    assertTrue(mBobSession.getCrypto().getDeviceTrackingStatus(mBobSession.getMyUserId()) == MXDeviceList.TRACKING_STATUS_UP_TO_DATE);
    assertTrue(mBobSession.getCrypto().getDeviceTrackingStatus(mAliceSession.getMyUserId()) == MXDeviceList.TRACKING_STATUS_UP_TO_DATE);
    assertTrue(mAliceSession.getCrypto().getDeviceTrackingStatus(mBobSession.getMyUserId()) == MXDeviceList.TRACKING_STATUS_UP_TO_DATE);
    assertTrue(mAliceSession.getCrypto().getDeviceTrackingStatus(mAliceSession.getMyUserId()) == MXDeviceList.TRACKING_STATUS_UP_TO_DATE);
    mBobSession.clear(context);
}
Also used : Context(android.content.Context) HashMap(java.util.HashMap) MXDeviceInfo(org.matrix.androidsdk.crypto.data.MXDeviceInfo) CountDownLatch(java.util.concurrent.CountDownLatch) MXUsersDevicesMap(org.matrix.androidsdk.crypto.data.MXUsersDevicesMap) MXEventListener(org.matrix.androidsdk.listeners.MXEventListener) Event(org.matrix.androidsdk.rest.model.Event) JsonObject(com.google.gson.JsonObject) MatrixError(org.matrix.androidsdk.rest.model.MatrixError) Room(org.matrix.androidsdk.data.Room) MXCryptoError(org.matrix.androidsdk.crypto.MXCryptoError) RoomState(org.matrix.androidsdk.data.RoomState) Test(org.junit.Test)

Example 2 with MXCryptoError

use of org.matrix.androidsdk.crypto.MXCryptoError in project matrix-android-sdk by matrix-org.

the class MXMegolmDecryption method decryptEvent.

public MXEventDecryptionResult decryptEvent(Event event, String timeline, boolean requestKeysOnFail) throws MXDecryptionException {
    // sanity check
    if (null == event) {
        Log.e(LOG_TAG, "## decryptEvent() : null event");
        return null;
    }
    EncryptedEventContent encryptedEventContent = JsonUtils.toEncryptedEventContent(event.getWireContent().getAsJsonObject());
    String senderKey = encryptedEventContent.sender_key;
    String ciphertext = encryptedEventContent.ciphertext;
    String sessionId = encryptedEventContent.session_id;
    if (TextUtils.isEmpty(senderKey) || TextUtils.isEmpty(sessionId) || TextUtils.isEmpty(ciphertext)) {
        throw new MXDecryptionException(new MXCryptoError(MXCryptoError.MISSING_FIELDS_ERROR_CODE, MXCryptoError.UNABLE_TO_DECRYPT, MXCryptoError.MISSING_FIELDS_REASON));
    }
    MXEventDecryptionResult eventDecryptionResult = null;
    MXCryptoError cryptoError = null;
    MXDecryptionResult decryptGroupMessageResult = null;
    try {
        decryptGroupMessageResult = mOlmDevice.decryptGroupMessage(ciphertext, event.roomId, timeline, sessionId, senderKey);
    } catch (MXDecryptionException e) {
        cryptoError = e.getCryptoError();
    }
    // the decryption succeeds
    if ((null != decryptGroupMessageResult) && (null != decryptGroupMessageResult.mPayload) && (null == cryptoError)) {
        eventDecryptionResult = new MXEventDecryptionResult();
        eventDecryptionResult.mClearEvent = decryptGroupMessageResult.mPayload;
        eventDecryptionResult.mSenderCurve25519Key = decryptGroupMessageResult.mSenderKey;
        if (null != decryptGroupMessageResult.mKeysClaimed) {
            eventDecryptionResult.mClaimedEd25519Key = decryptGroupMessageResult.mKeysClaimed.get("ed25519");
        }
        eventDecryptionResult.mForwardingCurve25519KeyChain = decryptGroupMessageResult.mForwardingCurve25519KeyChain;
    } else if (null != cryptoError) {
        if (cryptoError.isOlmError()) {
            if (TextUtils.equals("UNKNOWN_MESSAGE_INDEX", cryptoError.error)) {
                addEventToPendingList(event, timeline);
                if (requestKeysOnFail) {
                    requestKeysForEvent(event);
                }
            }
            String reason = String.format(MXCryptoError.OLM_REASON, cryptoError.error);
            String detailedReason = String.format(MXCryptoError.DETAILLED_OLM_REASON, ciphertext, cryptoError.error);
            throw new MXDecryptionException(new MXCryptoError(MXCryptoError.OLM_ERROR_CODE, reason, detailedReason));
        } else if (TextUtils.equals(cryptoError.errcode, MXCryptoError.UNKNOWN_INBOUND_SESSION_ID_ERROR_CODE)) {
            addEventToPendingList(event, timeline);
            if (requestKeysOnFail) {
                requestKeysForEvent(event);
            }
        }
        throw new MXDecryptionException(cryptoError);
    }
    return eventDecryptionResult;
}
Also used : MXDecryptionResult(org.matrix.androidsdk.crypto.algorithms.MXDecryptionResult) MXEventDecryptionResult(org.matrix.androidsdk.crypto.MXEventDecryptionResult) MXDecryptionException(org.matrix.androidsdk.crypto.MXDecryptionException) EncryptedEventContent(org.matrix.androidsdk.rest.model.crypto.EncryptedEventContent) MXCryptoError(org.matrix.androidsdk.crypto.MXCryptoError)

Example 3 with MXCryptoError

use of org.matrix.androidsdk.crypto.MXCryptoError in project matrix-android-sdk by matrix-org.

the class MXMegolmEncryption method getDevicesInRoom.

/**
 * Get the list of devices which can encrypt data to.
 * This method must be called in getDecryptingThreadHandler() thread.
 *
 * @param userIds  the user ids whose devices must be checked.
 * @param callback the asynchronous callback
 */
private void getDevicesInRoom(final List<String> userIds, final ApiCallback<MXUsersDevicesMap<MXDeviceInfo>> callback) {
    // We are happy to use a cached version here: we assume that if we already
    // have a list of the user's devices, then we already share an e2e room
    // with them, which means that they will have announced any new devices via
    // an m.new_device.
    mCrypto.getDeviceList().downloadKeys(userIds, false, new ApiCallback<MXUsersDevicesMap<MXDeviceInfo>>() {

        @Override
        public void onSuccess(final MXUsersDevicesMap<MXDeviceInfo> devices) {
            mCrypto.getEncryptingThreadHandler().post(new Runnable() {

                @Override
                public void run() {
                    boolean encryptToVerifiedDevicesOnly = mCrypto.getGlobalBlacklistUnverifiedDevices() || mCrypto.isRoomBlacklistUnverifiedDevices(mRoomId);
                    final MXUsersDevicesMap<MXDeviceInfo> devicesInRoom = new MXUsersDevicesMap<>();
                    final MXUsersDevicesMap<MXDeviceInfo> unknownDevices = new MXUsersDevicesMap<>();
                    List<String> userIds = devices.getUserIds();
                    for (String userId : userIds) {
                        List<String> deviceIds = devices.getUserDeviceIds(userId);
                        for (String deviceId : deviceIds) {
                            MXDeviceInfo deviceInfo = devices.getObject(deviceId, userId);
                            if (mCrypto.warnOnUnknownDevices() && deviceInfo.isUnknown()) {
                                // The device is not yet known by the user
                                unknownDevices.setObject(deviceInfo, userId, deviceId);
                                continue;
                            }
                            if (deviceInfo.isBlocked()) {
                                // Remove any blocked devices
                                continue;
                            }
                            if (!deviceInfo.isVerified() && encryptToVerifiedDevicesOnly) {
                                continue;
                            }
                            if (TextUtils.equals(deviceInfo.identityKey(), mCrypto.getOlmDevice().getDeviceCurve25519Key())) {
                                // Don't bother sending to ourself
                                continue;
                            }
                            devicesInRoom.setObject(deviceInfo, userId, deviceId);
                        }
                    }
                    mCrypto.getUIHandler().post(new Runnable() {

                        @Override
                        public void run() {
                            // if so, warn the user so they can verify or ignore.
                            if (0 != unknownDevices.getMap().size()) {
                                callback.onMatrixError(new MXCryptoError(MXCryptoError.UNKNOWN_DEVICES_CODE, MXCryptoError.UNABLE_TO_ENCRYPT, MXCryptoError.UNKNOWN_DEVICES_REASON, unknownDevices));
                            } else {
                                callback.onSuccess(devicesInRoom);
                            }
                        }
                    });
                }
            });
        }

        @Override
        public void onNetworkError(Exception e) {
            callback.onNetworkError(e);
        }

        @Override
        public void onMatrixError(MatrixError e) {
            callback.onMatrixError(e);
        }

        @Override
        public void onUnexpectedError(Exception e) {
            callback.onUnexpectedError(e);
        }
    });
}
Also used : MXDeviceInfo(org.matrix.androidsdk.crypto.data.MXDeviceInfo) MXUsersDevicesMap(org.matrix.androidsdk.crypto.data.MXUsersDevicesMap) MatrixError(org.matrix.androidsdk.rest.model.MatrixError) MXCryptoError(org.matrix.androidsdk.crypto.MXCryptoError)

Example 4 with MXCryptoError

use of org.matrix.androidsdk.crypto.MXCryptoError in project matrix-android-sdk by matrix-org.

the class EventDisplay method getTextualDisplay.

/**
 * Stringify the linked event.
 *
 * @param displayNameColor the display name highlighted color.
 * @return The text or null if it isn't possible.
 */
public CharSequence getTextualDisplay(Integer displayNameColor) {
    CharSequence text = null;
    try {
        JsonObject jsonEventContent = mEvent.getContentAsJsonObject();
        String userDisplayName = getUserDisplayName(mEvent.getSender(), mRoomState);
        String eventType = mEvent.getType();
        if (mEvent.isCallEvent()) {
            if (Event.EVENT_TYPE_CALL_INVITE.equals(eventType)) {
                boolean isVideo = false;
                // detect call type from the sdp
                try {
                    JsonObject offer = jsonEventContent.get("offer").getAsJsonObject();
                    JsonElement sdp = offer.get("sdp");
                    String sdpValue = sdp.getAsString();
                    isVideo = sdpValue.contains("m=video");
                } catch (Exception e) {
                    Log.e(LOG_TAG, "getTextualDisplay : " + e.getMessage());
                }
                if (isVideo) {
                    return mContext.getString(R.string.notice_placed_video_call, userDisplayName);
                } else {
                    return mContext.getString(R.string.notice_placed_voice_call, userDisplayName);
                }
            } else if (Event.EVENT_TYPE_CALL_ANSWER.equals(eventType)) {
                return mContext.getString(R.string.notice_answered_call, userDisplayName);
            } else if (Event.EVENT_TYPE_CALL_HANGUP.equals(eventType)) {
                return mContext.getString(R.string.notice_ended_call, userDisplayName);
            } else {
                return eventType;
            }
        } else if (Event.EVENT_TYPE_STATE_HISTORY_VISIBILITY.equals(eventType)) {
            CharSequence subpart;
            String historyVisibility = (null != jsonEventContent.get("history_visibility")) ? jsonEventContent.get("history_visibility").getAsString() : RoomState.HISTORY_VISIBILITY_SHARED;
            if (TextUtils.equals(historyVisibility, RoomState.HISTORY_VISIBILITY_SHARED)) {
                subpart = mContext.getString(R.string.notice_room_visibility_shared);
            } else if (TextUtils.equals(historyVisibility, RoomState.HISTORY_VISIBILITY_INVITED)) {
                subpart = mContext.getString(R.string.notice_room_visibility_invited);
            } else if (TextUtils.equals(historyVisibility, RoomState.HISTORY_VISIBILITY_JOINED)) {
                subpart = mContext.getString(R.string.notice_room_visibility_joined);
            } else if (TextUtils.equals(historyVisibility, RoomState.HISTORY_VISIBILITY_WORLD_READABLE)) {
                subpart = mContext.getString(R.string.notice_room_visibility_world_readable);
            } else {
                subpart = mContext.getString(R.string.notice_room_visibility_unknown, historyVisibility);
            }
            text = mContext.getString(R.string.notice_made_future_room_visibility, userDisplayName, subpart);
        } else if (Event.EVENT_TYPE_RECEIPT.equals(eventType)) {
            // the read receipt should not be displayed
            text = "Read Receipt";
        } else if (Event.EVENT_TYPE_MESSAGE.equals(eventType)) {
            String msgtype = (null != jsonEventContent.get("msgtype")) ? jsonEventContent.get("msgtype").getAsString() : "";
            // all m.room.message events should support the 'body' key fallback, so use it.
            text = jsonEventContent.get("body") == null ? null : jsonEventContent.get("body").getAsString();
            // check for html formatting
            if (jsonEventContent.has("formatted_body") && jsonEventContent.has("format")) {
                String format = jsonEventContent.getAsJsonPrimitive("format").getAsString();
                if (Message.FORMAT_MATRIX_HTML.equals(format)) {
                    String htmlBody = jsonEventContent.getAsJsonPrimitive("formatted_body").getAsString();
                    // an issue has been created https://github.com/vector-im/vector-android/issues/38
                    if (!TextUtils.isEmpty(htmlBody) && !htmlBody.contains("<ol>") && !htmlBody.contains("<li>")) {
                        text = Html.fromHtml(jsonEventContent.getAsJsonPrimitive("formatted_body").getAsString());
                    }
                }
            }
            // avoid empty image name
            if (TextUtils.equals(msgtype, Message.MSGTYPE_IMAGE) && TextUtils.isEmpty(text)) {
                text = mContext.getString(R.string.summary_user_sent_image, userDisplayName);
            } else if (TextUtils.equals(msgtype, Message.MSGTYPE_EMOTE)) {
                text = "* " + userDisplayName + " " + text;
            } else if (TextUtils.isEmpty(text)) {
                text = "";
            } else if (mPrependAuthor) {
                text = new SpannableStringBuilder(mContext.getString(R.string.summary_message, userDisplayName, text));
                if (null != displayNameColor) {
                    ((SpannableStringBuilder) text).setSpan(new ForegroundColorSpan(displayNameColor), 0, userDisplayName.length() + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    ((SpannableStringBuilder) text).setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0, userDisplayName.length() + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                }
            }
        } else if (Event.EVENT_TYPE_STICKER.equals(eventType)) {
            // all m.stickers events should support the 'body' key fallback, so use it.
            text = jsonEventContent.get("body") == null ? null : jsonEventContent.get("body").getAsString();
            if (TextUtils.isEmpty(text)) {
                text = mContext.getString(R.string.summary_user_sent_sticker, userDisplayName);
            }
        } else if (Event.EVENT_TYPE_MESSAGE_ENCRYPTION.equals(eventType)) {
            text = mContext.getString(R.string.notice_end_to_end, userDisplayName, mEvent.getWireEventContent().algorithm);
        } else if (Event.EVENT_TYPE_MESSAGE_ENCRYPTED.equals(eventType)) {
            // don't display
            if (mEvent.isRedacted()) {
                String redactedInfo = EventDisplay.getRedactionMessage(mContext, mEvent, mRoomState);
                if (TextUtils.isEmpty(redactedInfo)) {
                    return null;
                } else {
                    return redactedInfo;
                }
            } else {
                String message = null;
                if (null != mEvent.getCryptoError()) {
                    String errorDescription;
                    MXCryptoError error = mEvent.getCryptoError();
                    if (TextUtils.equals(error.errcode, MXCryptoError.UNKNOWN_INBOUND_SESSION_ID_ERROR_CODE)) {
                        errorDescription = mContext.getResources().getString(R.string.notice_crypto_error_unkwown_inbound_session_id);
                    } else {
                        errorDescription = error.getLocalizedMessage();
                    }
                    message = mContext.getString(R.string.notice_crypto_unable_to_decrypt, errorDescription);
                }
                if (TextUtils.isEmpty(message)) {
                    message = mContext.getString(R.string.encrypted_message);
                }
                SpannableString spannableStr = new SpannableString(message);
                spannableStr.setSpan(new android.text.style.StyleSpan(Typeface.ITALIC), 0, message.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                text = spannableStr;
            }
        } else if (Event.EVENT_TYPE_STATE_ROOM_TOPIC.equals(eventType)) {
            String topic = jsonEventContent.getAsJsonPrimitive("topic").getAsString();
            if (mEvent.isRedacted()) {
                String redactedInfo = EventDisplay.getRedactionMessage(mContext, mEvent, mRoomState);
                if (TextUtils.isEmpty(redactedInfo)) {
                    return null;
                }
                topic = redactedInfo;
            }
            if (!TextUtils.isEmpty(topic)) {
                text = mContext.getString(R.string.notice_topic_changed, userDisplayName, topic);
            } else {
                text = mContext.getString(R.string.notice_room_topic_removed, userDisplayName);
            }
        } else if (Event.EVENT_TYPE_STATE_ROOM_NAME.equals(eventType)) {
            JsonPrimitive nameAsJson = jsonEventContent.getAsJsonPrimitive("name");
            String roomName = (null == nameAsJson) ? null : nameAsJson.getAsString();
            if (mEvent.isRedacted()) {
                String redactedInfo = EventDisplay.getRedactionMessage(mContext, mEvent, mRoomState);
                if (TextUtils.isEmpty(redactedInfo)) {
                    return null;
                }
                roomName = redactedInfo;
            }
            if (!TextUtils.isEmpty(roomName)) {
                text = mContext.getString(R.string.notice_room_name_changed, userDisplayName, roomName);
            } else {
                text = mContext.getString(R.string.notice_room_name_removed, userDisplayName);
            }
        } else if (Event.EVENT_TYPE_STATE_ROOM_THIRD_PARTY_INVITE.equals(eventType)) {
            RoomThirdPartyInvite invite = JsonUtils.toRoomThirdPartyInvite(mEvent.getContent());
            String displayName = invite.display_name;
            if (mEvent.isRedacted()) {
                String redactedInfo = EventDisplay.getRedactionMessage(mContext, mEvent, mRoomState);
                if (TextUtils.isEmpty(redactedInfo)) {
                    return null;
                }
                displayName = redactedInfo;
            }
            text = mContext.getString(R.string.notice_room_third_party_invite, userDisplayName, displayName);
        } else if (Event.EVENT_TYPE_STATE_ROOM_MEMBER.equals(eventType)) {
            text = getMembershipNotice(mContext, mEvent, mRoomState);
        }
    } catch (Exception e) {
        Log.e(LOG_TAG, "getTextualDisplay() " + e.getMessage());
    }
    return text;
}
Also used : ForegroundColorSpan(android.text.style.ForegroundColorSpan) JsonPrimitive(com.google.gson.JsonPrimitive) StyleSpan(android.text.style.StyleSpan) JsonObject(com.google.gson.JsonObject) SpannableString(android.text.SpannableString) SpannableString(android.text.SpannableString) RoomThirdPartyInvite(org.matrix.androidsdk.rest.model.pid.RoomThirdPartyInvite) JsonElement(com.google.gson.JsonElement) StyleSpan(android.text.style.StyleSpan) SpannableStringBuilder(android.text.SpannableStringBuilder) MXCryptoError(org.matrix.androidsdk.crypto.MXCryptoError)

Example 5 with MXCryptoError

use of org.matrix.androidsdk.crypto.MXCryptoError in project matrix-android-sdk by matrix-org.

the class CryptoTest method test26_testBlackListUnverifiedDevices.

@Test
public // Check that the message can be decrypted by the Bob's device and the Sam's device
void test26_testBlackListUnverifiedDevices() throws Exception {
    Log.e(LOG_TAG, "test26_testBlackListUnverifiedDevices");
    Context context = InstrumentationRegistry.getContext();
    final HashMap<String, Object> results = new HashMap<>();
    doE2ETestWithAliceAndBobAndSamInARoom();
    final String messageFromAlice = "Hello I'm Alice!";
    Room roomFromBobPOV = mBobSession.getDataHandler().getRoom(mRoomId);
    Room roomFromAlicePOV = mAliceSession.getDataHandler().getRoom(mRoomId);
    Room roomFromSamPOV = mSamSession.getDataHandler().getRoom(mRoomId);
    assertTrue(roomFromBobPOV.isEncrypted());
    assertTrue(roomFromAlicePOV.isEncrypted());
    assertTrue(roomFromSamPOV.isEncrypted());
    final CountDownLatch lock1 = new CountDownLatch(1);
    roomFromAlicePOV.sendEvent(buildTextEvent(messageFromAlice, mAliceSession), new ApiCallback<Void>() {

        @Override
        public void onSuccess(Void info) {
            lock1.countDown();
        }

        @Override
        public void onNetworkError(Exception e) {
            lock1.countDown();
        }

        @Override
        public void onMatrixError(MatrixError e) {
            results.put("sendEventError", e);
            lock1.countDown();
        }

        @Override
        public void onUnexpectedError(Exception e) {
            lock1.countDown();
        }
    });
    lock1.await(3000, TimeUnit.MILLISECONDS);
    assertTrue(results.containsKey("sendEventError"));
    MXCryptoError error = (MXCryptoError) results.get("sendEventError");
    assertTrue(TextUtils.equals(error.errcode, MXCryptoError.UNKNOWN_DEVICES_CODE));
    MXUsersDevicesMap<MXDeviceInfo> unknownDevices = (MXUsersDevicesMap<MXDeviceInfo>) error.mExceptionData;
    // only one bob device
    List<String> deviceInfos = unknownDevices.getUserDeviceIds(mBobSession.getMyUserId());
    assertTrue(1 == deviceInfos.size());
    assertTrue(deviceInfos.contains(mBobSession.getCrypto().getMyDevice().deviceId));
    // only one Sam device
    deviceInfos = unknownDevices.getUserDeviceIds(mSamSession.getMyUserId());
    assertTrue(1 == deviceInfos.size());
    assertTrue(deviceInfos.contains(mSamSession.getCrypto().getMyDevice().deviceId));
    final CountDownLatch lock2 = new CountDownLatch(1);
    mAliceSession.getCrypto().setDevicesKnown(Arrays.asList(mBobSession.getCrypto().getMyDevice(), mSamSession.getCrypto().getMyDevice()), new ApiCallback<Void>() {

        @Override
        public void onSuccess(Void info) {
            results.put("setDevicesKnown", "setDevicesKnown");
            lock2.countDown();
        }

        @Override
        public void onNetworkError(Exception e) {
            lock2.countDown();
        }

        @Override
        public void onMatrixError(MatrixError e) {
            lock2.countDown();
        }

        @Override
        public void onUnexpectedError(Exception e) {
            lock2.countDown();
        }
    });
    lock2.await(3000, TimeUnit.MILLISECONDS);
    assertTrue(results.containsKey("setDevicesKnown"));
    final CountDownLatch lock3 = new CountDownLatch(5);
    MXEventListener eventListenerBob1 = new MXEventListener() {

        @Override
        public void onLiveEvent(Event event, RoomState roomState) {
            try {
                if (TextUtils.equals(event.getType(), Event.EVENT_TYPE_MESSAGE)) {
                    if (checkEncryptedEvent(event, mRoomId, messageFromAlice, mAliceSession)) {
                        results.put("onLiveEventBob1", "onLiveEvent");
                        lock3.countDown();
                    }
                }
            } catch (Exception e) {
            }
        }
    };
    MXEventListener eventListenerSam1 = new MXEventListener() {

        @Override
        public void onLiveEvent(Event event, RoomState roomState) {
            try {
                if (TextUtils.equals(event.getType(), Event.EVENT_TYPE_MESSAGE)) {
                    if (checkEncryptedEvent(event, mRoomId, messageFromAlice, mAliceSession)) {
                        results.put("onLiveEventSam1", "onLiveEvent");
                        lock3.countDown();
                    }
                }
            } catch (Exception e) {
            }
        }
    };
    mBobSession.getDataHandler().addListener(new MXEventListener() {

        @Override
        public void onToDeviceEvent(Event event) {
            results.put("onToDeviceEventBob", event);
            lock3.countDown();
        }
    });
    mSamSession.getDataHandler().addListener(new MXEventListener() {

        @Override
        public void onToDeviceEvent(Event event) {
            results.put("onToDeviceEventSam", event);
            lock3.countDown();
        }
    });
    roomFromBobPOV.addEventListener(eventListenerBob1);
    roomFromSamPOV.addEventListener(eventListenerSam1);
    roomFromAlicePOV.sendEvent(buildTextEvent(messageFromAlice, mAliceSession), new ApiCallback<Void>() {

        @Override
        public void onSuccess(Void info) {
            lock3.countDown();
        }

        @Override
        public void onNetworkError(Exception e) {
            lock3.countDown();
        }

        @Override
        public void onMatrixError(MatrixError e) {
            lock3.countDown();
        }

        @Override
        public void onUnexpectedError(Exception e) {
            lock3.countDown();
        }
    });
    lock3.await(3000, TimeUnit.MILLISECONDS);
    assertTrue(results.containsKey("onToDeviceEventBob"));
    assertTrue(results.containsKey("onToDeviceEventSam"));
    assertTrue(results.containsKey("onLiveEventBob1"));
    assertTrue(results.containsKey("onLiveEventSam1"));
    roomFromBobPOV.removeEventListener(eventListenerBob1);
    roomFromSamPOV.removeEventListener(eventListenerSam1);
    // play with the device black listing
    final List<CountDownLatch> activeLock = new ArrayList<>();
    final List<String> activeMessage = new ArrayList<>();
    MXEventListener eventListenerBob2 = new MXEventListener() {

        @Override
        public void onLiveEvent(Event event, RoomState roomState) {
            try {
                if (TextUtils.equals(event.getType(), Event.EVENT_TYPE_MESSAGE)) {
                    if (checkEncryptedEvent(event, mRoomId, activeMessage.get(0), mAliceSession)) {
                        results.put("eventListenerBob2", "onLiveEvent");
                        activeLock.get(0).countDown();
                    }
                } else if (TextUtils.equals(event.getType(), Event.EVENT_TYPE_MESSAGE_ENCRYPTED)) {
                    results.put("eventListenerEncyptedBob2", "onLiveEvent");
                    activeLock.get(0).countDown();
                }
            } catch (Exception e) {
            }
        }
    };
    MXEventListener eventListenerSam2 = new MXEventListener() {

        @Override
        public void onLiveEvent(Event event, RoomState roomState) {
            try {
                if (TextUtils.equals(event.getType(), Event.EVENT_TYPE_MESSAGE)) {
                    if (checkEncryptedEvent(event, mRoomId, activeMessage.get(0), mAliceSession)) {
                        results.put("eventListenerSam2", "onLiveEvent");
                        activeLock.get(0).countDown();
                    }
                } else if (TextUtils.equals(event.getType(), Event.EVENT_TYPE_MESSAGE_ENCRYPTED)) {
                    results.put("eventListenerEncyptedSam2", "onLiveEvent");
                    activeLock.get(0).countDown();
                }
            } catch (Exception e) {
            }
        }
    };
    roomFromBobPOV.addEventListener(eventListenerBob2);
    roomFromSamPOV.addEventListener(eventListenerSam2);
    final CountDownLatch lock4 = new CountDownLatch(1);
    mAliceSession.getCrypto().setGlobalBlacklistUnverifiedDevices(true, new ApiCallback<Void>() {

        @Override
        public void onSuccess(Void info) {
            results.put("setGlobalBlacklistUnverifiedDevicesTrue", "setGlobalBlacklistUnverifiedDevices");
            lock4.countDown();
        }

        @Override
        public void onNetworkError(Exception e) {
            lock4.countDown();
        }

        @Override
        public void onMatrixError(MatrixError e) {
            lock4.countDown();
        }

        @Override
        public void onUnexpectedError(Exception e) {
            lock4.countDown();
        }
    });
    lock4.await(3000, TimeUnit.MILLISECONDS);
    assertTrue(results.containsKey("setGlobalBlacklistUnverifiedDevicesTrue"));
    // ensure that there is no received message
    results.clear();
    final CountDownLatch lock5 = new CountDownLatch(3);
    activeLock.clear();
    activeLock.add(lock5);
    activeMessage.clear();
    activeMessage.add("message 1");
    roomFromAlicePOV.sendEvent(buildTextEvent(activeMessage.get(0), mAliceSession), new ApiCallback<Void>() {

        @Override
        public void onSuccess(Void info) {
            lock5.countDown();
        }

        @Override
        public void onNetworkError(Exception e) {
            lock5.countDown();
        }

        @Override
        public void onMatrixError(MatrixError e) {
            lock5.countDown();
        }

        @Override
        public void onUnexpectedError(Exception e) {
            lock5.countDown();
        }
    });
    lock5.await(3000, TimeUnit.MILLISECONDS);
    assertTrue(!results.containsKey("eventListenerBob2"));
    assertTrue(!results.containsKey("eventListenerSam2"));
    assertTrue(results.containsKey("eventListenerEncyptedBob2"));
    assertTrue(results.containsKey("eventListenerEncyptedSam2"));
    final CountDownLatch lock6 = new CountDownLatch(1);
    mAliceSession.getCrypto().setGlobalBlacklistUnverifiedDevices(false, new ApiCallback<Void>() {

        @Override
        public void onSuccess(Void info) {
            results.put("setGlobalBlacklistUnverifiedDevicesfalse", "setGlobalBlacklistUnverifiedDevices");
            lock6.countDown();
        }

        @Override
        public void onNetworkError(Exception e) {
            lock6.countDown();
        }

        @Override
        public void onMatrixError(MatrixError e) {
            lock6.countDown();
        }

        @Override
        public void onUnexpectedError(Exception e) {
            lock6.countDown();
        }
    });
    lock6.await(3000, TimeUnit.MILLISECONDS);
    assertTrue(results.containsKey("setGlobalBlacklistUnverifiedDevicesfalse"));
    // ensure that the messages are received
    results.clear();
    final CountDownLatch lock7 = new CountDownLatch(3);
    activeLock.clear();
    activeLock.add(lock7);
    activeMessage.clear();
    activeMessage.add("message 2");
    roomFromAlicePOV.sendEvent(buildTextEvent(activeMessage.get(0), mAliceSession), new ApiCallback<Void>() {

        @Override
        public void onSuccess(Void info) {
            lock7.countDown();
        }

        @Override
        public void onNetworkError(Exception e) {
            lock7.countDown();
        }

        @Override
        public void onMatrixError(MatrixError e) {
            lock7.countDown();
        }

        @Override
        public void onUnexpectedError(Exception e) {
            lock7.countDown();
        }
    });
    lock7.await(3000, TimeUnit.MILLISECONDS);
    assertTrue(results.containsKey("eventListenerBob2"));
    assertTrue(results.containsKey("eventListenerSam2"));
    assertTrue(!results.containsKey("eventListenerEncyptedBob2"));
    assertTrue(!results.containsKey("eventListenerEncyptedSam2"));
    // verify the bob device
    final CountDownLatch lock8 = new CountDownLatch(3);
    mAliceSession.getCrypto().setDeviceVerification(MXDeviceInfo.DEVICE_VERIFICATION_VERIFIED, mBobSession.getCrypto().getMyDevice().deviceId, mBobSession.getMyUserId(), new ApiCallback<Void>() {

        @Override
        public void onSuccess(Void info) {
            results.put("setDeviceVerificationBob", "setDeviceVerificationBob");
            lock8.countDown();
        }

        @Override
        public void onNetworkError(Exception e) {
            lock8.countDown();
        }

        @Override
        public void onMatrixError(MatrixError e) {
            lock8.countDown();
        }

        @Override
        public void onUnexpectedError(Exception e) {
            lock8.countDown();
        }
    });
    lock8.await(3000, TimeUnit.MILLISECONDS);
    assertTrue(results.containsKey("setDeviceVerificationBob"));
    final CountDownLatch lock9 = new CountDownLatch(3);
    mAliceSession.getCrypto().setRoomBlacklistUnverifiedDevices(roomFromAlicePOV.getRoomId(), new ApiCallback<Void>() {

        @Override
        public void onSuccess(Void info) {
            results.put("setRoomBlacklistUnverifiedDevices", "setRoomBlacklistUnverifiedDevices");
            lock9.countDown();
        }

        @Override
        public void onNetworkError(Exception e) {
            lock9.countDown();
        }

        @Override
        public void onMatrixError(MatrixError e) {
            lock9.countDown();
        }

        @Override
        public void onUnexpectedError(Exception e) {
            lock9.countDown();
        }
    });
    lock9.await(3000, TimeUnit.MILLISECONDS);
    assertTrue(results.containsKey("setRoomBlacklistUnverifiedDevices"));
    // ensure that the messages are received
    results.clear();
    final CountDownLatch lock10 = new CountDownLatch(3);
    activeLock.clear();
    activeLock.add(lock10);
    activeMessage.clear();
    activeMessage.add("message 3");
    roomFromAlicePOV.sendEvent(buildTextEvent(activeMessage.get(0), mAliceSession), new ApiCallback<Void>() {

        @Override
        public void onSuccess(Void info) {
            lock10.countDown();
        }

        @Override
        public void onNetworkError(Exception e) {
            lock10.countDown();
        }

        @Override
        public void onMatrixError(MatrixError e) {
            lock10.countDown();
        }

        @Override
        public void onUnexpectedError(Exception e) {
            lock10.countDown();
        }
    });
    lock10.await(3000, TimeUnit.MILLISECONDS);
    assertTrue(results.containsKey("eventListenerBob2"));
    assertTrue(!results.containsKey("eventListenerSam2"));
    assertTrue(!results.containsKey("eventListenerEncyptedBob2"));
    assertTrue(results.containsKey("eventListenerEncyptedSam2"));
    final CountDownLatch lock11 = new CountDownLatch(3);
    mAliceSession.getCrypto().setRoomUnblacklistUnverifiedDevices(roomFromAlicePOV.getRoomId(), new ApiCallback<Void>() {

        @Override
        public void onSuccess(Void info) {
            results.put("setRoomUnblacklistUnverifiedDevices", "setRoomUnblacklistUnverifiedDevices");
            lock11.countDown();
        }

        @Override
        public void onNetworkError(Exception e) {
            lock11.countDown();
        }

        @Override
        public void onMatrixError(MatrixError e) {
            lock11.countDown();
        }

        @Override
        public void onUnexpectedError(Exception e) {
            lock11.countDown();
        }
    });
    lock11.await(3000, TimeUnit.MILLISECONDS);
    assertTrue(results.containsKey("setRoomUnblacklistUnverifiedDevices"));
    // ensure that the messages are received
    results.clear();
    final CountDownLatch lock12 = new CountDownLatch(3);
    activeLock.clear();
    activeLock.add(lock12);
    activeMessage.clear();
    activeMessage.add("message 3");
    roomFromAlicePOV.sendEvent(buildTextEvent(activeMessage.get(0), mAliceSession), new ApiCallback<Void>() {

        @Override
        public void onSuccess(Void info) {
            lock12.countDown();
        }

        @Override
        public void onNetworkError(Exception e) {
            lock12.countDown();
        }

        @Override
        public void onMatrixError(MatrixError e) {
            lock12.countDown();
        }

        @Override
        public void onUnexpectedError(Exception e) {
            lock12.countDown();
        }
    });
    lock12.await(3000, TimeUnit.MILLISECONDS);
    assertTrue(results.containsKey("eventListenerBob2"));
    assertTrue(results.containsKey("eventListenerSam2"));
    assertTrue(!results.containsKey("eventListenerEncyptedBob2"));
    assertTrue(!results.containsKey("eventListenerEncyptedSam2"));
    mBobSession.clear(context);
}
Also used : Context(android.content.Context) HashMap(java.util.HashMap) MXDeviceInfo(org.matrix.androidsdk.crypto.data.MXDeviceInfo) ArrayList(java.util.ArrayList) CountDownLatch(java.util.concurrent.CountDownLatch) MXUsersDevicesMap(org.matrix.androidsdk.crypto.data.MXUsersDevicesMap) MXEventListener(org.matrix.androidsdk.listeners.MXEventListener) Event(org.matrix.androidsdk.rest.model.Event) JsonObject(com.google.gson.JsonObject) MatrixError(org.matrix.androidsdk.rest.model.MatrixError) Room(org.matrix.androidsdk.data.Room) MXCryptoError(org.matrix.androidsdk.crypto.MXCryptoError) RoomState(org.matrix.androidsdk.data.RoomState) Test(org.junit.Test)

Aggregations

MXCryptoError (org.matrix.androidsdk.crypto.MXCryptoError)8 MatrixError (org.matrix.androidsdk.rest.model.MatrixError)5 MXDeviceInfo (org.matrix.androidsdk.crypto.data.MXDeviceInfo)4 JsonObject (com.google.gson.JsonObject)3 MXUsersDevicesMap (org.matrix.androidsdk.crypto.data.MXUsersDevicesMap)3 Room (org.matrix.androidsdk.data.Room)3 Event (org.matrix.androidsdk.rest.model.Event)3 Context (android.content.Context)2 JsonElement (com.google.gson.JsonElement)2 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2 CountDownLatch (java.util.concurrent.CountDownLatch)2 Test (org.junit.Test)2 MXDecryptionException (org.matrix.androidsdk.crypto.MXDecryptionException)2 MXEventDecryptionResult (org.matrix.androidsdk.crypto.MXEventDecryptionResult)2 RoomState (org.matrix.androidsdk.data.RoomState)2 MXEventListener (org.matrix.androidsdk.listeners.MXEventListener)2 ApiCallback (org.matrix.androidsdk.rest.callback.ApiCallback)2 SimpleApiCallback (org.matrix.androidsdk.rest.callback.SimpleApiCallback)2 Activity (android.app.Activity)1