Merge branch 'develop' into johannes/widget-system-permissions
This commit is contained in:
commit
4ebb26d3d3
24
.github/workflows/quality.yml
vendored
24
.github/workflows/quality.yml
vendored
@ -5,6 +5,11 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches: [ main, develop ]
|
branches: [ main, develop ]
|
||||||
|
|
||||||
|
# Enrich gradle.properties for CI/CD
|
||||||
|
env:
|
||||||
|
CI_GRADLE_ARG_PROPERTIES: >
|
||||||
|
-Porg.gradle.jvmargs=-Xmx4g
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check:
|
check:
|
||||||
name: Project Check Suite
|
name: Project Check Suite
|
||||||
@ -97,6 +102,25 @@ jobs:
|
|||||||
comment_id: ${{ steps.fc.outputs.comment-id }}
|
comment_id: ${{ steps.fc.outputs.comment-id }}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# Gradle dependency analysis using https://github.com/autonomousapps/dependency-analysis-android-gradle-plugin
|
||||||
|
dependency-analysis:
|
||||||
|
name: Dependency analysis
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
# Allow all jobs on main and develop. Just one per PR.
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.ref == 'refs/heads/main' && format('dep-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('dep-develop-{0}', github.sha) || format('dep-{0}', github.ref) }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Dependency analysis
|
||||||
|
run: ./gradlew buildHealth $CI_GRADLE_ARG_PROPERTIES
|
||||||
|
- name: Upload dependency analysis
|
||||||
|
if: always()
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: dependency-analysis
|
||||||
|
path: build/reports/dependency-analysis/build-health-report.txt
|
||||||
|
|
||||||
# Lint for main module
|
# Lint for main module
|
||||||
android-lint:
|
android-lint:
|
||||||
name: Android Linter
|
name: Android Linter
|
||||||
|
55
build.gradle
55
build.gradle
@ -41,6 +41,9 @@ plugins {
|
|||||||
id "org.jlleitschuh.gradle.ktlint" version "10.3.0"
|
id "org.jlleitschuh.gradle.ktlint" version "10.3.0"
|
||||||
// Detekt
|
// Detekt
|
||||||
id "io.gitlab.arturbosch.detekt" version "1.20.0"
|
id "io.gitlab.arturbosch.detekt" version "1.20.0"
|
||||||
|
|
||||||
|
// Dependency Analysis
|
||||||
|
id 'com.autonomousapps.dependency-analysis' version "1.4.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/jeremylong/DependencyCheck
|
// https://github.com/jeremylong/DependencyCheck
|
||||||
@ -219,3 +222,55 @@ project(":library:diff-match-patch") {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
dependencyAnalysis {
|
||||||
|
dependencies {
|
||||||
|
bundle("kotlin-stdlib") {
|
||||||
|
includeGroup("org.jetbrains.kotlin")
|
||||||
|
}
|
||||||
|
bundle("react") {
|
||||||
|
includeGroup("com.facebook.react")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
issues {
|
||||||
|
all {
|
||||||
|
ignoreKtx(true)
|
||||||
|
onUsedTransitiveDependencies {
|
||||||
|
// Transitively used dependencies that should be declared directly
|
||||||
|
severity("ignore")
|
||||||
|
}
|
||||||
|
onUnusedDependencies {
|
||||||
|
severity("fail")
|
||||||
|
}
|
||||||
|
onUnusedAnnotationProcessors {
|
||||||
|
severity("fail")
|
||||||
|
exclude("com.airbnb.android:epoxy-processor", "com.google.dagger:hilt-compiler") // False positives
|
||||||
|
}
|
||||||
|
}
|
||||||
|
project(":library:jsonviewer") {
|
||||||
|
onUnusedDependencies {
|
||||||
|
exclude("org.json:json") // Used in unit tests, overwrites the one bundled into Android
|
||||||
|
}
|
||||||
|
}
|
||||||
|
project(":library:ui-styles") {
|
||||||
|
onUnusedDependencies {
|
||||||
|
exclude("com.github.vector-im:PFLockScreen-Android") // False positive
|
||||||
|
}
|
||||||
|
}
|
||||||
|
project(":matrix-sdk-android") {
|
||||||
|
onUnusedDependencies {
|
||||||
|
exclude("io.reactivex.rxjava2:rxkotlin") // Transitively required for mocking realm as monarchy doesn't expose Rx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
project(":matrix-sdk-android-flow") {
|
||||||
|
onUnusedDependencies {
|
||||||
|
exclude("androidx.paging:paging-runtime-ktx") // False positive
|
||||||
|
}
|
||||||
|
}
|
||||||
|
project(":vector") {
|
||||||
|
onUnusedDependencies {
|
||||||
|
exclude("org.maplibre.gl:android-sdk", "org.maplibre.gl:android-plugin-annotation-v9") // False positives
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
1
changelog.d/4862.bugfix
Normal file
1
changelog.d/4862.bugfix
Normal file
@ -0,0 +1 @@
|
|||||||
|
Fix some notifications not clearing when read
|
1
changelog.d/5283.wip
Normal file
1
changelog.d/5283.wip
Normal file
@ -0,0 +1 @@
|
|||||||
|
FTUE - Adds the redesigned Sign In screen
|
1
changelog.d/5783.wip
Normal file
1
changelog.d/5783.wip
Normal file
@ -0,0 +1 @@
|
|||||||
|
FTUE - Overrides sign up flow ordering for matrix.org only
|
1
changelog.d/5860.feature
Normal file
1
changelog.d/5860.feature
Normal file
@ -0,0 +1 @@
|
|||||||
|
Adds space or user id as a subtitle under rooms in search
|
4
changelog.d/5952.sdk
Normal file
4
changelog.d/5952.sdk
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
- Some `val` have been changed to `fun` to increase their visibility in the generated documentation. Just add `()` if you were using them.
|
||||||
|
- `KeysBackupService.state` has been replaced by `KeysBackupService.getState()`
|
||||||
|
- `KeysBackupService.isStucked` has been replaced by `KeysBackupService.isStuck()`
|
||||||
|
- SDK documentation improved
|
@ -1 +1,2 @@
|
|||||||
Live location sharing: navigation from timeline to map screen
|
Live location sharing: navigation from timeline to map screen
|
||||||
|
Live location sharing: show user pins on map screen
|
||||||
|
1
changelog.d/6073.feature
Normal file
1
changelog.d/6073.feature
Normal file
@ -0,0 +1 @@
|
|||||||
|
Adds up navigation in spaces
|
1
changelog.d/6077.sdk
Normal file
1
changelog.d/6077.sdk
Normal file
@ -0,0 +1 @@
|
|||||||
|
Improve replay attacks and reduce duplicate message index errors
|
1
changelog.d/6100.misc
Normal file
1
changelog.d/6100.misc
Normal file
@ -0,0 +1 @@
|
|||||||
|
Excludes transitive optional non FOSS google location dependency from fdroid builds
|
1
changelog.d/6123.wip
Normal file
1
changelog.d/6123.wip
Normal file
@ -0,0 +1 @@
|
|||||||
|
[Live location sharing] Update entity in DB when a live is timed out
|
1
changelog.d/6132.misc
Normal file
1
changelog.d/6132.misc
Normal file
@ -0,0 +1 @@
|
|||||||
|
Fixed grammar errors in /vector/src/main/res/values/strings.xml
|
1
changelog.d/6140.bugfix
Normal file
1
changelog.d/6140.bugfix
Normal file
@ -0,0 +1 @@
|
|||||||
|
Prevent widget web view from reloading on screen / orientation change
|
1
changelog.d/6141.misc
Normal file
1
changelog.d/6141.misc
Normal file
@ -0,0 +1 @@
|
|||||||
|
Downgrade gradle from 7.2.0 to 7.1.3
|
3
changelog.d/6143.sdk
Normal file
3
changelog.d/6143.sdk
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
Remove `RoomSummaryQueryParams.roomId`. If you need to observe a single room, use the new API `RoomService.getRoomSummaryLive(roomId: String)`
|
||||||
|
- `ActiveSpaceFilter` has been renamed to `SpaceFilter`
|
||||||
|
- `RoomCategoryFilter.ALL` has been removed, just pass `null` to not filter on Room category.
|
1
changelog.d/6148.bugfix
Normal file
1
changelog.d/6148.bugfix
Normal file
@ -0,0 +1 @@
|
|||||||
|
Fix decrypting redacted event from sending errors
|
1
changelog.d/6163.feature
Normal file
1
changelog.d/6163.feature
Normal file
@ -0,0 +1 @@
|
|||||||
|
Security - Asking for user confirmation when tapping URLs which contain unicode directional overrides
|
1
changelog.d/6166.feature
Normal file
1
changelog.d/6166.feature
Normal file
@ -0,0 +1 @@
|
|||||||
|
Add settings switch to allow autoplaying animated images
|
1
changelog.d/6170.feature
Normal file
1
changelog.d/6170.feature
Normal file
@ -0,0 +1 @@
|
|||||||
|
Live Location Sharing - User List Bottom Sheet
|
@ -7,10 +7,13 @@ ext.versions = [
|
|||||||
'targetCompat' : JavaVersion.VERSION_11,
|
'targetCompat' : JavaVersion.VERSION_11,
|
||||||
]
|
]
|
||||||
|
|
||||||
def gradle = "7.2.0"
|
|
||||||
|
// Pinned to 7.1.3 because of https://github.com/vector-im/element-android/issues/6142
|
||||||
|
// Please test carefully before upgrading again.
|
||||||
|
def gradle = "7.1.3"
|
||||||
// Ref: https://kotlinlang.org/releases.html
|
// Ref: https://kotlinlang.org/releases.html
|
||||||
def kotlin = "1.6.21"
|
def kotlin = "1.6.21"
|
||||||
def kotlinCoroutines = "1.6.1"
|
def kotlinCoroutines = "1.6.2"
|
||||||
def dagger = "2.42"
|
def dagger = "2.42"
|
||||||
def retrofit = "2.9.0"
|
def retrofit = "2.9.0"
|
||||||
def arrow = "0.8.2"
|
def arrow = "0.8.2"
|
||||||
@ -23,7 +26,7 @@ def mavericks = "2.6.1"
|
|||||||
def glide = "4.13.2"
|
def glide = "4.13.2"
|
||||||
def bigImageViewer = "1.8.1"
|
def bigImageViewer = "1.8.1"
|
||||||
def jjwt = "0.11.5"
|
def jjwt = "0.11.5"
|
||||||
def vanniktechEmoji = "0.9.0"
|
def vanniktechEmoji = "0.15.0"
|
||||||
|
|
||||||
// Testing
|
// Testing
|
||||||
def mockk = "1.12.4"
|
def mockk = "1.12.4"
|
||||||
@ -45,6 +48,7 @@ ext.libs = [
|
|||||||
'coroutinesTest' : "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinCoroutines"
|
'coroutinesTest' : "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinCoroutines"
|
||||||
],
|
],
|
||||||
androidx : [
|
androidx : [
|
||||||
|
'activity' : "androidx.activity:activity:1.4.0",
|
||||||
'appCompat' : "androidx.appcompat:appcompat:1.4.1",
|
'appCompat' : "androidx.appcompat:appcompat:1.4.1",
|
||||||
'core' : "androidx.core:core-ktx:1.7.0",
|
'core' : "androidx.core:core-ktx:1.7.0",
|
||||||
'recyclerview' : "androidx.recyclerview:recyclerview:1.2.1",
|
'recyclerview' : "androidx.recyclerview:recyclerview:1.2.1",
|
||||||
@ -69,7 +73,9 @@ ext.libs = [
|
|||||||
'testRules' : "androidx.test:rules:$androidxTest",
|
'testRules' : "androidx.test:rules:$androidxTest",
|
||||||
'espressoCore' : "androidx.test.espresso:espresso-core:$espresso",
|
'espressoCore' : "androidx.test.espresso:espresso-core:$espresso",
|
||||||
'espressoContrib' : "androidx.test.espresso:espresso-contrib:$espresso",
|
'espressoContrib' : "androidx.test.espresso:espresso-contrib:$espresso",
|
||||||
'espressoIntents' : "androidx.test.espresso:espresso-intents:$espresso"
|
'espressoIntents' : "androidx.test.espresso:espresso-intents:$espresso",
|
||||||
|
'viewpager2' : "androidx.viewpager2:viewpager2:1.0.0",
|
||||||
|
'transition' : "androidx.transition:transition:1.2.0",
|
||||||
],
|
],
|
||||||
google : [
|
google : [
|
||||||
'material' : "com.google.android.material:material:1.6.0"
|
'material' : "com.google.android.material:material:1.6.0"
|
||||||
@ -81,7 +87,7 @@ ext.libs = [
|
|||||||
'hiltCompiler' : "com.google.dagger:hilt-compiler:$dagger"
|
'hiltCompiler' : "com.google.dagger:hilt-compiler:$dagger"
|
||||||
],
|
],
|
||||||
squareup : [
|
squareup : [
|
||||||
'moshi' : "com.squareup.moshi:moshi-adapters:$moshi",
|
'moshi' : "com.squareup.moshi:moshi:$moshi",
|
||||||
'moshiKotlin' : "com.squareup.moshi:moshi-kotlin-codegen:$moshi",
|
'moshiKotlin' : "com.squareup.moshi:moshi-kotlin-codegen:$moshi",
|
||||||
'retrofit' : "com.squareup.retrofit2:retrofit:$retrofit",
|
'retrofit' : "com.squareup.retrofit2:retrofit:$retrofit",
|
||||||
'retrofitMoshi' : "com.squareup.retrofit2:converter-moshi:$retrofit"
|
'retrofitMoshi' : "com.squareup.retrofit2:converter-moshi:$retrofit"
|
||||||
@ -107,6 +113,10 @@ ext.libs = [
|
|||||||
'mavericks' : "com.airbnb.android:mavericks:$mavericks",
|
'mavericks' : "com.airbnb.android:mavericks:$mavericks",
|
||||||
'mavericksTesting' : "com.airbnb.android:mavericks-testing:$mavericks"
|
'mavericksTesting' : "com.airbnb.android:mavericks-testing:$mavericks"
|
||||||
],
|
],
|
||||||
|
maplibre : [
|
||||||
|
'androidSdk' : "org.maplibre.gl:android-sdk:9.5.2",
|
||||||
|
'pluginAnnotation' : "org.maplibre.gl:android-plugin-annotation-v9:1.0.0"
|
||||||
|
],
|
||||||
mockk : [
|
mockk : [
|
||||||
'mockk' : "io.mockk:mockk:$mockk",
|
'mockk' : "io.mockk:mockk:$mockk",
|
||||||
'mockkAndroid' : "io.mockk:mockk-android:$mockk"
|
'mockkAndroid' : "io.mockk:mockk-android:$mockk"
|
||||||
|
@ -1,5 +1,34 @@
|
|||||||
# Adding and removing ThreePids to an account
|
# Adding and removing ThreePids to an account
|
||||||
|
|
||||||
|
<!--- TOC -->
|
||||||
|
|
||||||
|
* [Add email](#add-email)
|
||||||
|
* [User enter the email](#user-enter-the-email)
|
||||||
|
* [The email is already added to an account](#the-email-is-already-added-to-an-account)
|
||||||
|
* [The email is free](#the-email-is-free)
|
||||||
|
* [User receives an e-mail](#user-receives-an-e-mail)
|
||||||
|
* [User clicks on the link](#user-clicks-on-the-link)
|
||||||
|
* [User returns on Element](#user-returns-on-element)
|
||||||
|
* [User enters his password](#user-enters-his-password)
|
||||||
|
* [The link has not been clicked](#the-link-has-not-been-clicked)
|
||||||
|
* [Wrong password](#wrong-password)
|
||||||
|
* [The link has been clicked and the account password is correct](#the-link-has-been-clicked-and-the-account-password-is-correct)
|
||||||
|
* [Remove email](#remove-email)
|
||||||
|
* [User want to remove an email from his account](#user-want-to-remove-an-email-from-his-account)
|
||||||
|
* [Email was not bound to an identity server](#email-was-not-bound-to-an-identity-server)
|
||||||
|
* [Email was bound to an identity server](#email-was-bound-to-an-identity-server)
|
||||||
|
* [Add phone number](#add-phone-number)
|
||||||
|
* [The phone number is already added to an account](#the-phone-number-is-already-added-to-an-account)
|
||||||
|
* [The phone number is free](#the-phone-number-is-free)
|
||||||
|
* [User receive a text message](#user-receive-a-text-message)
|
||||||
|
* [User enter the code to the app](#user-enter-the-code-to-the-app)
|
||||||
|
* [Wrong code](#wrong-code)
|
||||||
|
* [Correct code](#correct-code)
|
||||||
|
* [Remove phone number](#remove-phone-number)
|
||||||
|
* [User wants to remove a phone number from his account](#user-wants-to-remove-a-phone-number-from-his-account)
|
||||||
|
|
||||||
|
<!--- END -->
|
||||||
|
|
||||||
## Add email
|
## Add email
|
||||||
|
|
||||||
### User enter the email
|
### User enter the email
|
||||||
|
@ -1,5 +1,13 @@
|
|||||||
# Analytics in Element
|
# Analytics in Element
|
||||||
|
|
||||||
|
<!--- TOC -->
|
||||||
|
|
||||||
|
* [Solution](#solution)
|
||||||
|
* [How to add a new Event](#how-to-add-a-new-event)
|
||||||
|
* [Forks of Element](#forks-of-element)
|
||||||
|
|
||||||
|
<!--- END -->
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
|
|
||||||
Element is using PostHog to send analytics event.
|
Element is using PostHog to send analytics event.
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
# Color migration
|
# Color migration
|
||||||
|
|
||||||
|
<!--- TOC -->
|
||||||
|
|
||||||
|
* [Changes](#changes)
|
||||||
|
* [Main change for developers](#main-change-for-developers)
|
||||||
|
* [Remaining work](#remaining-work)
|
||||||
|
* [Migration guide](#migration-guide)
|
||||||
|
|
||||||
|
<!--- END -->
|
||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
|
|
||||||
- use colors defined in https://www.figma.com/file/X4XTH9iS2KGJ2wFKDqkyed/Compound?node-id=557%3A0
|
- use colors defined in https://www.figma.com/file/X4XTH9iS2KGJ2wFKDqkyed/Compound?node-id=557%3A0
|
||||||
|
@ -1,5 +1,31 @@
|
|||||||
# Element Android design
|
# Element Android design
|
||||||
|
|
||||||
|
<!--- TOC -->
|
||||||
|
|
||||||
|
* [Introduction](#introduction)
|
||||||
|
* [How to import from Figma to the Element Android project](#how-to-import-from-figma-to-the-element-android-project)
|
||||||
|
* [Colors](#colors)
|
||||||
|
* [Text](#text)
|
||||||
|
* [Dimension, position and margin](#dimension-position-and-margin)
|
||||||
|
* [Icons](#icons)
|
||||||
|
* [Export drawable from Figma](#export-drawable-from-figma)
|
||||||
|
* [Import in Android Studio](#import-in-android-studio)
|
||||||
|
* [Images](#images)
|
||||||
|
* [Figma links](#figma-links)
|
||||||
|
* [Coumpound](#coumpound)
|
||||||
|
* [Login](#login)
|
||||||
|
* [Login v2](#login-v2)
|
||||||
|
* [Room list](#room-list)
|
||||||
|
* [Timeline](#timeline)
|
||||||
|
* [Voice message](#voice-message)
|
||||||
|
* [Room settings](#room-settings)
|
||||||
|
* [VoIP](#voip)
|
||||||
|
* [Presence](#presence)
|
||||||
|
* [Spaces](#spaces)
|
||||||
|
* [List to be continued...](#list-to-be-continued)
|
||||||
|
|
||||||
|
<!--- END -->
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
Design at element.io is done using Figma - https://www.figma.com
|
Design at element.io is done using Figma - https://www.figma.com
|
||||||
|
@ -1,5 +1,19 @@
|
|||||||
# Identity server
|
# Identity server
|
||||||
|
|
||||||
|
<!--- TOC -->
|
||||||
|
|
||||||
|
* [Introduction](#introduction)
|
||||||
|
* [Implementation](#implementation)
|
||||||
|
* [Related MSCs](#related-mscs)
|
||||||
|
* [Steps and requirements](#steps-and-requirements)
|
||||||
|
* [Screens](#screens)
|
||||||
|
* [Settings](#settings)
|
||||||
|
* [Discovery screen](#discovery-screen)
|
||||||
|
* [Set identity server screen](#set-identity-server-screen)
|
||||||
|
* [Ref:](#ref:)
|
||||||
|
|
||||||
|
<!--- END -->
|
||||||
|
|
||||||
Issue: #607
|
Issue: #607
|
||||||
PR: #1354
|
PR: #1354
|
||||||
|
|
||||||
|
@ -1,5 +1,18 @@
|
|||||||
# Integration tests
|
# Integration tests
|
||||||
|
|
||||||
|
<!--- TOC -->
|
||||||
|
|
||||||
|
* [Pre requirements](#pre-requirements)
|
||||||
|
* [Install and run Synapse](#install-and-run-synapse)
|
||||||
|
* [Run the test](#run-the-test)
|
||||||
|
* [Stop Synapse](#stop-synapse)
|
||||||
|
* [Troubleshoot](#troubleshoot)
|
||||||
|
* [Android Emulator does cannot reach the homeserver](#android-emulator-does-cannot-reach-the-homeserver)
|
||||||
|
* [Tests partially run but some fail with "Unable to contact localhost:8080"](#tests-partially-run-but-some-fail-with-"unable-to-contact-localhost:8080")
|
||||||
|
* [virtualenv command fails](#virtualenv-command-fails)
|
||||||
|
|
||||||
|
<!--- END -->
|
||||||
|
|
||||||
Integration tests are useful to ensure that the code works well for any use cases.
|
Integration tests are useful to ensure that the code works well for any use cases.
|
||||||
|
|
||||||
They can also be used as sample on how to use the Matrix SDK.
|
They can also be used as sample on how to use the Matrix SDK.
|
||||||
|
@ -1,20 +1,32 @@
|
|||||||
# Jitsi in Element Android
|
# Jitsi in Element Android
|
||||||
|
|
||||||
|
<!--- TOC -->
|
||||||
|
|
||||||
|
* [Native Jitsi SDK](#native-jitsi-sdk)
|
||||||
|
* [How to build the Jitsi Meet SDK](#how-to-build-the-jitsi-meet-sdk)
|
||||||
|
* [Jitsi version](#jitsi-version)
|
||||||
|
* [Run the build script](#run-the-build-script)
|
||||||
|
* [Link with the new generated library](#link-with-the-new-generated-library)
|
||||||
|
* [Sanity tests](#sanity-tests)
|
||||||
|
* [Export the build library](#export-the-build-library)
|
||||||
|
|
||||||
|
<!--- END -->
|
||||||
|
|
||||||
Native Jitsi support has been added to Element Android by the PR [#1914](https://github.com/vector-im/element-android/pull/1914). The description of the PR contains some documentation about the behaviour in each possible room configuration.
|
Native Jitsi support has been added to Element Android by the PR [#1914](https://github.com/vector-im/element-android/pull/1914). The description of the PR contains some documentation about the behaviour in each possible room configuration.
|
||||||
|
|
||||||
Also, ensure to have a look on [the documentation from Element Web](https://github.com/vector-im/element-web/blob/develop/docs/jitsi.md)
|
Also, ensure to have a look on [the documentation from Element Web](https://github.com/vector-im/element-web/blob/develop/docs/jitsi.md)
|
||||||
|
|
||||||
The official documentation about how to integrate the Jitsi SDK in an Android app is available here: https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-android-sdk.
|
The official documentation about how to integrate the Jitsi SDK in an Android app is available here: https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-android-sdk.
|
||||||
|
|
||||||
# Native Jitsi SDK
|
## Native Jitsi SDK
|
||||||
|
|
||||||
The Jitsi SDK is built by ourselves with the flag LIBRE_BUILD, to be able to be integrated on the F-Droid version of Element Android.
|
The Jitsi SDK is built by ourselves with the flag LIBRE_BUILD, to be able to be integrated on the F-Droid version of Element Android.
|
||||||
|
|
||||||
The generated maven repository is then host in the project https://github.com/vector-im/jitsi_libre_maven
|
The generated maven repository is then host in the project https://github.com/vector-im/jitsi_libre_maven
|
||||||
|
|
||||||
## How to build the Jitsi Meet SDK
|
### How to build the Jitsi Meet SDK
|
||||||
|
|
||||||
### Jitsi version
|
#### Jitsi version
|
||||||
|
|
||||||
Update the script `./tools/jitsi/build_jisti_libs.sh` with the tag of the project `https://github.com/jitsi/jitsi-meet`.
|
Update the script `./tools/jitsi/build_jisti_libs.sh` with the tag of the project `https://github.com/jitsi/jitsi-meet`.
|
||||||
|
|
||||||
@ -22,7 +34,7 @@ Latest tag can be found from this page: https://github.com/jitsi/jitsi-meet-rele
|
|||||||
|
|
||||||
Currently we are building the version with the tag `android-sdk-3.10.0`.
|
Currently we are building the version with the tag `android-sdk-3.10.0`.
|
||||||
|
|
||||||
### Run the build script
|
#### Run the build script
|
||||||
|
|
||||||
At the root of the Element Android, run the following script:
|
At the root of the Element Android, run the following script:
|
||||||
|
|
||||||
@ -32,7 +44,7 @@ At the root of the Element Android, run the following script:
|
|||||||
|
|
||||||
It will build the Jitsi Meet Android library and put every generated files in the folder `/tmp/jitsi`
|
It will build the Jitsi Meet Android library and put every generated files in the folder `/tmp/jitsi`
|
||||||
|
|
||||||
### Link with the new generated library
|
#### Link with the new generated library
|
||||||
|
|
||||||
- Update the file `./build.gradle` to use the previously created local Maven repository. Currently we have this line:
|
- Update the file `./build.gradle` to use the previously created local Maven repository. Currently we have this line:
|
||||||
|
|
||||||
@ -57,7 +69,7 @@ implementation('com.facebook.react:react-native-webrtc:1.92.1-jitsi-9093212@aar'
|
|||||||
- Perform a gradle sync and build the project
|
- Perform a gradle sync and build the project
|
||||||
- Perform test
|
- Perform test
|
||||||
|
|
||||||
### Sanity tests
|
#### Sanity tests
|
||||||
|
|
||||||
In order to validate that the upgrade of the Jitsi and WebRTC dependency does not break anything, the following sanity tests have to be performed, using two devices:
|
In order to validate that the upgrade of the Jitsi and WebRTC dependency does not break anything, the following sanity tests have to be performed, using two devices:
|
||||||
- Make 1-1 audio call (so using WebRTC)
|
- Make 1-1 audio call (so using WebRTC)
|
||||||
@ -65,7 +77,7 @@ In order to validate that the upgrade of the Jitsi and WebRTC dependency does no
|
|||||||
- Create and join a conference call with audio only (so using Jitsi library). Leave the conference. Join it again.
|
- Create and join a conference call with audio only (so using Jitsi library). Leave the conference. Join it again.
|
||||||
- Create and join a conference call with audio and video (so using Jitsi library) Leave the conference. Join it again.
|
- Create and join a conference call with audio and video (so using Jitsi library) Leave the conference. Join it again.
|
||||||
|
|
||||||
### Export the build library
|
#### Export the build library
|
||||||
|
|
||||||
If all the tests are passed, you can export the generated Jitsi library to our Maven repository.
|
If all the tests are passed, you can export the generated Jitsi library to our Maven repository.
|
||||||
|
|
||||||
|
@ -1,28 +1,33 @@
|
|||||||
This document aims to describe how Element android displays notifications to the end user. It also clarifies notifications and background settings in the app.
|
This document aims to describe how Element android displays notifications to the end user. It also clarifies notifications and background settings in the app.
|
||||||
|
|
||||||
# Table of Contents
|
# Table of Contents
|
||||||
1. [Prerequisites Knowledge](#prerequisites-knowledge)
|
|
||||||
* [How does a matrix client get a message from a homeserver?](#how-does-a-matrix-client-get-a-message-from-a-homeserver)
|
<!--- TOC -->
|
||||||
* [How does a mobile app receives push notification?](#how-does-a-mobile-app-receives-push-notification)
|
|
||||||
|
* [Prerequisites Knowledge](#prerequisites-knowledge)
|
||||||
|
* [How does a matrix client get a message from a homeserver?](#how-does-a-matrix-client-get-a-message-from-a-homeserver?)
|
||||||
|
* [How does a mobile app receives push notification](#how-does-a-mobile-app-receives-push-notification)
|
||||||
* [Push VS Notification](#push-vs-notification)
|
* [Push VS Notification](#push-vs-notification)
|
||||||
* [Push in the matrix federated world](#push-in-the-matrix-federated-world)
|
* [Push in the matrix federated world](#push-in-the-matrix-federated-world)
|
||||||
* [How does the homeserver know when to notify a client?](#how-does-the-homeserver-know-when-to-notify-a-client)
|
* [How does the homeserver know when to notify a client?](#how-does-the-homeserver-know-when-to-notify-a-client?)
|
||||||
* [Push vs privacy, and mitigation](#push-vs-privacy-and-mitigation)
|
* [Push vs privacy, and mitigation](#push-vs-privacy-and-mitigation)
|
||||||
* [Background processing limitations](#background-processing-limitations)
|
* [Background processing limitations](#background-processing-limitations)
|
||||||
2. [Element Notification implementations](#element-notification-implementations)
|
* [Element Notification implementations](#element-notification-implementations)
|
||||||
* [Requirements](#requirements)
|
* [Requirements](#requirements)
|
||||||
* [Foreground sync mode (Gplay & F-Droid)](#foreground-sync-mode-gplay-f-droid)
|
* [Foreground sync mode (Gplay and F-Droid)](#foreground-sync-mode-gplay-and-f-droid)
|
||||||
* [Push (FCM) received in background](#push-fcm-received-in-background)
|
* [Push (FCM) received in background](#push-fcm-received-in-background)
|
||||||
* [FCM Fallback mode](#fcm-fallback-mode)
|
* [FCM Fallback mode](#fcm-fallback-mode)
|
||||||
* [F-Droid background Mode](#f-droid-background-mode)
|
* [F-Droid background Mode](#f-droid-background-mode)
|
||||||
3. [Application Settings](#application-settings)
|
* [Application Settings](#application-settings)
|
||||||
|
|
||||||
|
<!--- END -->
|
||||||
|
|
||||||
|
|
||||||
First let's start with some prerequisite knowledge
|
First let's start with some prerequisite knowledge
|
||||||
|
|
||||||
# Prerequisites Knowledge
|
## Prerequisites Knowledge
|
||||||
|
|
||||||
## How does a matrix client get a message from a homeserver?
|
### How does a matrix client get a message from a homeserver?
|
||||||
|
|
||||||
In order to get messages from a homeserver, a matrix client need to perform a ``sync`` operation.
|
In order to get messages from a homeserver, a matrix client need to perform a ``sync`` operation.
|
||||||
|
|
||||||
@ -52,7 +57,7 @@ By default, this is 0, so the server will return immediately even if the respons
|
|||||||
|
|
||||||
When the Element Android app is open (i.e in foreground state), the default timeout is 30 seconds, and delay is 0.
|
When the Element Android app is open (i.e in foreground state), the default timeout is 30 seconds, and delay is 0.
|
||||||
|
|
||||||
## How does a mobile app receives push notification
|
### How does a mobile app receives push notification
|
||||||
|
|
||||||
Push notification is used as a way to wake up a mobile application when some important information is available and should be processed.
|
Push notification is used as a way to wake up a mobile application when some important information is available and should be processed.
|
||||||
|
|
||||||
@ -67,21 +72,21 @@ FCM will only work on android devices that have Google plays services installed
|
|||||||
|
|
||||||
De-Googlified devices need to rely on something else in order to stay up to date with a server.
|
De-Googlified devices need to rely on something else in order to stay up to date with a server.
|
||||||
There some cases when devices with google services cannot use FCM (network infrastructure limitations -firewalls-,
|
There some cases when devices with google services cannot use FCM (network infrastructure limitations -firewalls-,
|
||||||
privacy and or independency requirement, source code licence)
|
privacy and or independence requirement, source code licence)
|
||||||
|
|
||||||
## Push VS Notification
|
### Push VS Notification
|
||||||
|
|
||||||
This need some disambiguation, because it is the source of common confusion:
|
This need some disambiguation, because it is the source of common confusion:
|
||||||
|
|
||||||
|
|
||||||
*The fact that you see a notification on your screen does not mean that you have successfully configured your PUSH plateform.*
|
*The fact that you see a notification on your screen does not mean that you have successfully configured your PUSH platform.*
|
||||||
|
|
||||||
Technically there is a difference between a push and a notification. A notification is what you see on screen and/or in the notification Menu/Drawer (in the top bar of the phone).
|
Technically there is a difference between a push and a notification. A notification is what you see on screen and/or in the notification Menu/Drawer (in the top bar of the phone).
|
||||||
|
|
||||||
Notifications are not always triggered by a push (One can display a notification locally triggered by an alarm)
|
Notifications are not always triggered by a push (One can display a notification locally triggered by an alarm)
|
||||||
|
|
||||||
|
|
||||||
## Push in the matrix federated world
|
### Push in the matrix federated world
|
||||||
|
|
||||||
In order to send a push to a mobile, App developers need to have a server that will use the FCM APIs, and these APIs requires authentication!
|
In order to send a push to a mobile, App developers need to have a server that will use the FCM APIs, and these APIs requires authentication!
|
||||||
This server is called a **Push Gateway** in the matrix world
|
This server is called a **Push Gateway** in the matrix world
|
||||||
@ -122,7 +127,7 @@ Recommended reading:
|
|||||||
* https://matrix.org/docs/spec/client_server/r0.4.0.html#id128
|
* https://matrix.org/docs/spec/client_server/r0.4.0.html#id128
|
||||||
|
|
||||||
|
|
||||||
## How does the homeserver know when to notify a client?
|
### How does the homeserver know when to notify a client?
|
||||||
|
|
||||||
This is defined by [**push rules**](https://matrix.org/docs/spec/client_server/r0.4.0.html#push-rules-).
|
This is defined by [**push rules**](https://matrix.org/docs/spec/client_server/r0.4.0.html#push-rules-).
|
||||||
|
|
||||||
@ -140,14 +145,14 @@ Of course, content patterns matching cannot be used for encrypted messages serve
|
|||||||
|
|
||||||
That is why clients are able to **process the push rules client side** to decide what kind of notification should be presented for a given event.
|
That is why clients are able to **process the push rules client side** to decide what kind of notification should be presented for a given event.
|
||||||
|
|
||||||
## Push vs privacy, and mitigation
|
### Push vs privacy, and mitigation
|
||||||
|
|
||||||
As seen previously, App developers don't directly send a push to the end user's device, they use a Push Provider as intermediary. So technically this intermediary is able to read the content of what is sent.
|
As seen previously, App developers don't directly send a push to the end user's device, they use a Push Provider as intermediary. So technically this intermediary is able to read the content of what is sent.
|
||||||
|
|
||||||
App developers usually mitigate this by sending a `silent notification`, that is a notification with no identifiable data, or with an encrypted payload. When the push is received the app can then synchronise to it's server in order to generate a local notification.
|
App developers usually mitigate this by sending a `silent notification`, that is a notification with no identifiable data, or with an encrypted payload. When the push is received the app can then synchronise to it's server in order to generate a local notification.
|
||||||
|
|
||||||
|
|
||||||
## Background processing limitations
|
### Background processing limitations
|
||||||
|
|
||||||
A mobile applications process live in a managed word, meaning that its process can be limited (e.g no network access), stopped or killed at almost anytime by the Operating System.
|
A mobile applications process live in a managed word, meaning that its process can be limited (e.g no network access), stopped or killed at almost anytime by the Operating System.
|
||||||
|
|
||||||
@ -167,15 +172,15 @@ The documentation on this subject is vague, and as per our experiments not alway
|
|||||||
|
|
||||||
It is getting more and more complex to have reliable notifications when FCM is not used.
|
It is getting more and more complex to have reliable notifications when FCM is not used.
|
||||||
|
|
||||||
# Element Notification implementations
|
## Element Notification implementations
|
||||||
|
|
||||||
## Requirements
|
### Requirements
|
||||||
|
|
||||||
Element Android must work with and without FCM.
|
Element Android must work with and without FCM.
|
||||||
* The Element android app published on F-Droid do not rely on FCM (all related dependencies are not present)
|
* The Element android app published on F-Droid do not rely on FCM (all related dependencies are not present)
|
||||||
* The Element android app published on google play rely on FCM, with a fallback mode when FCM registration has failed (e.g outdated or missing Google Play Services)
|
* The Element android app published on google play rely on FCM, with a fallback mode when FCM registration has failed (e.g outdated or missing Google Play Services)
|
||||||
|
|
||||||
## Foreground sync mode (Gplay & F-Droid)
|
### Foreground sync mode (Gplay and F-Droid)
|
||||||
|
|
||||||
When in foreground, Element performs sync continuously with a timeout value set to 10 seconds (see HttpPooling).
|
When in foreground, Element performs sync continuously with a timeout value set to 10 seconds (see HttpPooling).
|
||||||
|
|
||||||
@ -183,9 +188,9 @@ As this mode does not need to live beyond the scope of the application, and as p
|
|||||||
|
|
||||||
This mode is turned on when the app enters foreground, and off when enters background.
|
This mode is turned on when the app enters foreground, and off when enters background.
|
||||||
|
|
||||||
In background, and depending on wether push is available or not, Element will use different methods to perform the syncs (Workers / Alarms / Service)
|
In background, and depending on whether push is available or not, Element will use different methods to perform the syncs (Workers / Alarms / Service)
|
||||||
|
|
||||||
## Push (FCM) received in background
|
### Push (FCM) received in background
|
||||||
|
|
||||||
In order to enable Push, Element must first get a push token from the firebase SDK, then register a pusher with this token on the homeserver.
|
In order to enable Push, Element must first get a push token from the firebase SDK, then register a pusher with this token on the homeserver.
|
||||||
|
|
||||||
@ -225,10 +230,10 @@ Upon reception of the FCM push, Element will perform a sync call to the homeserv
|
|||||||
|
|
||||||
Element implements several strategies in these cases (TODO document)
|
Element implements several strategies in these cases (TODO document)
|
||||||
|
|
||||||
## FCM Fallback mode
|
### FCM Fallback mode
|
||||||
|
|
||||||
It is possible that Element is not able to get a FCM push token.
|
It is possible that Element is not able to get a FCM push token.
|
||||||
Common errors (amoung several others) that can cause that:
|
Common errors (among several others) that can cause that:
|
||||||
* Google Play Services is outdated
|
* Google Play Services is outdated
|
||||||
* Google Play Service fails in someways with FCM servers (infamous `SERVICE_NOT_AVAILABLE`)
|
* Google Play Service fails in someways with FCM servers (infamous `SERVICE_NOT_AVAILABLE`)
|
||||||
|
|
||||||
@ -246,7 +251,7 @@ Usually in this mode, what happen is when you take back your phone in your hand,
|
|||||||
|
|
||||||
The fallback mode is supposed to be a temporary state waiting for the user to fix issues for FCM, or for App Developers that has done a fork to correctly configure their FCM settings.
|
The fallback mode is supposed to be a temporary state waiting for the user to fix issues for FCM, or for App Developers that has done a fork to correctly configure their FCM settings.
|
||||||
|
|
||||||
## F-Droid background Mode
|
### F-Droid background Mode
|
||||||
|
|
||||||
The F-Droid Element flavor has no dependencies to FCM, therefore cannot relies on Push.
|
The F-Droid Element flavor has no dependencies to FCM, therefore cannot relies on Push.
|
||||||
|
|
||||||
@ -256,7 +261,7 @@ Only solution left is to use `AlarmManager`, that offers new API to allow launch
|
|||||||
|
|
||||||
Notice that these alarms, due to their potential impact on battery life, can still be restricted by the system. Documentation says that they will not be triggered more than every minutes under normal system operation, and when in low power mode about every 15 mn.
|
Notice that these alarms, due to their potential impact on battery life, can still be restricted by the system. Documentation says that they will not be triggered more than every minutes under normal system operation, and when in low power mode about every 15 mn.
|
||||||
|
|
||||||
These restrictions can be relaxed by requirering the app to be white listed from battery optimization.
|
These restrictions can be relaxed by requiring the app to be white listed from battery optimization.
|
||||||
|
|
||||||
F-Droid version will schedule alarms that will then trigger a Broadcast Receiver, that in turn will launch a Service (in the classic android way), and the reschedule an alarm for next time.
|
F-Droid version will schedule alarms that will then trigger a Broadcast Receiver, that in turn will launch a Service (in the classic android way), and the reschedule an alarm for next time.
|
||||||
|
|
||||||
@ -266,9 +271,7 @@ That is why on Element F-Droid, the broadcast receiver will acquire a temporary
|
|||||||
|
|
||||||
Note that foreground services require to put a notification informing the user that the app is doing something even if not launched).
|
Note that foreground services require to put a notification informing the user that the app is doing something even if not launched).
|
||||||
|
|
||||||
|
## Application Settings
|
||||||
|
|
||||||
# Application Settings
|
|
||||||
|
|
||||||
**Notifications > Enable notifications for this account**
|
**Notifications > Enable notifications for this account**
|
||||||
|
|
||||||
|
@ -1,5 +1,43 @@
|
|||||||
# Pull requests
|
# Pull requests
|
||||||
|
|
||||||
|
<!--- TOC -->
|
||||||
|
|
||||||
|
* [Introduction](#introduction)
|
||||||
|
* [Who should read this document?](#who-should-read-this-document?)
|
||||||
|
* [Submitting PR](#submitting-pr)
|
||||||
|
* [Who can submit pull requests?](#who-can-submit-pull-requests?)
|
||||||
|
* [Humans](#humans)
|
||||||
|
* [Draft PR?](#draft-pr?)
|
||||||
|
* [Base branch](#base-branch)
|
||||||
|
* [PR Review Assignment](#pr-review-assignment)
|
||||||
|
* [PR review time](#pr-review-time)
|
||||||
|
* [Re-request PR review](#re-request-pr-review)
|
||||||
|
* [When create split PR?](#when-create-split-pr?)
|
||||||
|
* [Avoid fixing other unrelated issue in a big PR](#avoid-fixing-other-unrelated-issue-in-a-big-pr)
|
||||||
|
* [Bots](#bots)
|
||||||
|
* [Dependabot](#dependabot)
|
||||||
|
* [Gradle wrapper](#gradle-wrapper)
|
||||||
|
* [Sync analytics plan](#sync-analytics-plan)
|
||||||
|
* [Reviewing PR](#reviewing-pr)
|
||||||
|
* [Who can review pull requests?](#who-can-review-pull-requests?)
|
||||||
|
* [What to have in mind when reviewing a PR](#what-to-have-in-mind-when-reviewing-a-pr)
|
||||||
|
* [Rules](#rules)
|
||||||
|
* [Check the form](#check-the-form)
|
||||||
|
* [PR title](#pr-title)
|
||||||
|
* [PR description](#pr-description)
|
||||||
|
* [File change](#file-change)
|
||||||
|
* [Check the commit](#check-the-commit)
|
||||||
|
* [Check the substance](#check-the-substance)
|
||||||
|
* [Make a dedicated meeting to review the PR](#make-a-dedicated-meeting-to-review-the-pr)
|
||||||
|
* [What happen to the issue(s)?](#what-happen-to-the-issues?)
|
||||||
|
* [Merge conflict](#merge-conflict)
|
||||||
|
* [When and who can merge PR](#when-and-who-can-merge-pr)
|
||||||
|
* [Merge type](#merge-type)
|
||||||
|
* [Resolve conversation](#resolve-conversation)
|
||||||
|
* [Responsibility](#responsibility)
|
||||||
|
|
||||||
|
<!--- END -->
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
This document gives some clue about how to efficiently manage Pull Requests (PR). This document is a first draft and may be improved later.
|
This document gives some clue about how to efficiently manage Pull Requests (PR). This document is a first draft and may be improved later.
|
||||||
|
@ -2,6 +2,27 @@
|
|||||||
|
|
||||||
This document describes the flow of signin to a homeserver, and also the flow when user want to reset his password. Examples come from the `matrix.org` homeserver.
|
This document describes the flow of signin to a homeserver, and also the flow when user want to reset his password. Examples come from the `matrix.org` homeserver.
|
||||||
|
|
||||||
|
<!--- TOC -->
|
||||||
|
|
||||||
|
* [Sign in flows](#sign-in-flows)
|
||||||
|
* [Get the flow](#get-the-flow)
|
||||||
|
* [Login with username](#login-with-username)
|
||||||
|
* [Incorrect password](#incorrect-password)
|
||||||
|
* [Correct password:](#correct-password:)
|
||||||
|
* [Login with email](#login-with-email)
|
||||||
|
* [Unknown email](#unknown-email)
|
||||||
|
* [Known email, wrong password](#known-email-wrong-password)
|
||||||
|
* [Known email, correct password](#known-email-correct-password)
|
||||||
|
* [Login with Msisdn](#login-with-msisdn)
|
||||||
|
* [Login with SSO](#login-with-sso)
|
||||||
|
* [Reset password](#reset-password)
|
||||||
|
* [Send email](#send-email)
|
||||||
|
* [When the email is not known](#when-the-email-is-not-known)
|
||||||
|
* [When the email is known](#when-the-email-is-known)
|
||||||
|
* [User clicks on the link](#user-clicks-on-the-link)
|
||||||
|
|
||||||
|
<!--- END -->
|
||||||
|
|
||||||
## Sign in flows
|
## Sign in flows
|
||||||
|
|
||||||
### Get the flow
|
### Get the flow
|
||||||
|
@ -4,6 +4,20 @@ This document describes the flow of registration to a homeserver. Examples come
|
|||||||
|
|
||||||
*Ref*: https://matrix.org/docs/spec/client_server/latest#account-registration-and-management
|
*Ref*: https://matrix.org/docs/spec/client_server/latest#account-registration-and-management
|
||||||
|
|
||||||
|
<!--- TOC -->
|
||||||
|
|
||||||
|
* [Sign up flows](#sign-up-flows)
|
||||||
|
* [First step](#first-step)
|
||||||
|
* [Step 1: entering user name and password](#step-1:-entering-user-name-and-password)
|
||||||
|
* [If username already exists](#if-username-already-exists)
|
||||||
|
* [Step 2: entering email](#step-2:-entering-email)
|
||||||
|
* [Step 2 bis: user enters an email](#step-2-bis:-user-enters-an-email)
|
||||||
|
* [Step 3: Accepting T&C](#step-3:-accepting-t&c)
|
||||||
|
* [Step 4: Captcha](#step-4:-captcha)
|
||||||
|
* [Step 5: MSISDN](#step-5:-msisdn)
|
||||||
|
|
||||||
|
<!--- END -->
|
||||||
|
|
||||||
## Sign up flows
|
## Sign up flows
|
||||||
|
|
||||||
### First step
|
### First step
|
||||||
|
@ -10,6 +10,20 @@ Currently the test are covering a small set of application flows:
|
|||||||
- Self verification via emoji
|
- Self verification via emoji
|
||||||
- Self verification via passphrase
|
- Self verification via passphrase
|
||||||
|
|
||||||
|
<!--- TOC -->
|
||||||
|
|
||||||
|
* [Prerequisites:](#prerequisites:)
|
||||||
|
* [Run the tests](#run-the-tests)
|
||||||
|
* [From the source code](#from-the-source-code)
|
||||||
|
* [From command line](#from-command-line)
|
||||||
|
* [Recipes](#recipes)
|
||||||
|
* [Wait for initial sync](#wait-for-initial-sync)
|
||||||
|
* [Accessing current activity](#accessing-current-activity)
|
||||||
|
* [Interact with other session](#interact-with-other-session)
|
||||||
|
* [Contributing to the UiAllScreensSanityTest](#contributing-to-the-uiallscreenssanitytest)
|
||||||
|
|
||||||
|
<!--- END -->
|
||||||
|
|
||||||
## Prerequisites:
|
## Prerequisites:
|
||||||
|
|
||||||
Out of the box, the tests use one of the homeservers (located at http://localhost:8080) of the "Demo Federation of Homeservers" (https://github.com/matrix-org/synapse#running-a-demo-federation-of-synapses).
|
Out of the box, the tests use one of the homeservers (located at http://localhost:8080) of the "Demo Federation of Homeservers" (https://github.com/matrix-org/synapse#running-a-demo-federation-of-synapses).
|
||||||
|
@ -55,5 +55,6 @@ dependencies {
|
|||||||
implementation libs.androidx.appCompat
|
implementation libs.androidx.appCompat
|
||||||
implementation libs.androidx.recyclerview
|
implementation libs.androidx.recyclerview
|
||||||
|
|
||||||
implementation libs.google.material
|
api libs.androidx.viewpager2
|
||||||
|
implementation libs.androidx.transition
|
||||||
}
|
}
|
@ -50,6 +50,5 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation libs.androidx.appCompat
|
|
||||||
implementation libs.jetbrains.coroutinesAndroid
|
implementation libs.jetbrains.coroutinesAndroid
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,7 @@ dependencies {
|
|||||||
|
|
||||||
implementation libs.androidx.appCompat
|
implementation libs.androidx.appCompat
|
||||||
implementation libs.androidx.core
|
implementation libs.androidx.core
|
||||||
|
implementation libs.androidx.recyclerview
|
||||||
|
|
||||||
implementation libs.airbnb.epoxy
|
implementation libs.airbnb.epoxy
|
||||||
kapt libs.airbnb.epoxyProcessor
|
kapt libs.airbnb.epoxyProcessor
|
||||||
@ -60,7 +61,6 @@ dependencies {
|
|||||||
// Span utils
|
// Span utils
|
||||||
implementation 'me.gujun.android:span:1.7'
|
implementation 'me.gujun.android:span:1.7'
|
||||||
|
|
||||||
implementation libs.google.material
|
|
||||||
|
|
||||||
implementation libs.jetbrains.coroutinesCore
|
implementation libs.jetbrains.coroutinesCore
|
||||||
implementation libs.jetbrains.coroutinesAndroid
|
implementation libs.jetbrains.coroutinesAndroid
|
||||||
|
@ -38,9 +38,9 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation libs.androidx.appCompat
|
api libs.androidx.activity
|
||||||
implementation libs.androidx.fragmentKtx
|
|
||||||
implementation libs.androidx.exifinterface
|
implementation libs.androidx.exifinterface
|
||||||
|
implementation libs.androidx.core
|
||||||
|
|
||||||
// Log
|
// Log
|
||||||
implementation libs.jakewharton.timber
|
implementation libs.jakewharton.timber
|
||||||
|
@ -18,4 +18,26 @@
|
|||||||
<item name="android:gravity">center</item>
|
<item name="android:gravity">center</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="TextAppearance.Vector.Body.BottomSheetDisplayName">
|
||||||
|
<item name="android:textSize">16sp</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="TextAppearance.Vector.Body.BottomSheetRemainingTime">
|
||||||
|
<item name="android:textSize">12sp</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="TextAppearance.Vector.Body.BottomSheetLastUpdatedAt">
|
||||||
|
<item name="android:textSize">12sp</item>
|
||||||
|
<item name="android:textColor">?vctr_content_tertiary</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="Widget.Vector.Button.Text.BottomSheetStopSharing">
|
||||||
|
<item name="android:foreground">?selectableItemBackground</item>
|
||||||
|
<item name="android:background">@android:color/transparent</item>
|
||||||
|
<item name="android:textAppearance">@style/TextAppearance.Vector.Body.Medium</item>
|
||||||
|
<item name="android:textColor">?colorError</item>
|
||||||
|
<item name="android:padding">0dp</item>
|
||||||
|
<item name="android:gravity">center</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -31,9 +31,7 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
implementation project(":matrix-sdk-android")
|
implementation project(":matrix-sdk-android")
|
||||||
implementation libs.androidx.appCompat
|
|
||||||
|
|
||||||
implementation libs.jetbrains.coroutinesCore
|
implementation libs.jetbrains.coroutinesCore
|
||||||
implementation libs.jetbrains.coroutinesAndroid
|
implementation libs.jetbrains.coroutinesAndroid
|
||||||
@ -41,7 +39,4 @@ dependencies {
|
|||||||
|
|
||||||
// Paging
|
// Paging
|
||||||
implementation libs.androidx.pagingRuntimeKtx
|
implementation libs.androidx.pagingRuntimeKtx
|
||||||
|
|
||||||
// Logging
|
|
||||||
implementation libs.jakewharton.timber
|
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,13 @@ import org.matrix.android.sdk.api.util.toOptional
|
|||||||
|
|
||||||
class FlowSession(private val session: Session) {
|
class FlowSession(private val session: Session) {
|
||||||
|
|
||||||
|
fun liveRoomSummary(roomId: String): Flow<Optional<RoomSummary>> {
|
||||||
|
return session.roomService().getRoomSummaryLive(roomId).asFlow()
|
||||||
|
.startWith(session.coroutineDispatchers.io) {
|
||||||
|
session.roomService().getRoomSummary(roomId).toOptional()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun liveRoomSummaries(queryParams: RoomSummaryQueryParams, sortOrder: RoomSortOrder = RoomSortOrder.NONE): Flow<List<RoomSummary>> {
|
fun liveRoomSummaries(queryParams: RoomSummaryQueryParams, sortOrder: RoomSortOrder = RoomSortOrder.NONE): Flow<List<RoomSummary>> {
|
||||||
return session.roomService().getRoomSummariesLive(queryParams, sortOrder).asFlow()
|
return session.roomService().getRoomSummariesLive(queryParams, sortOrder).asFlow()
|
||||||
.startWith(session.coroutineDispatchers.io) {
|
.startWith(session.coroutineDispatchers.io) {
|
||||||
|
@ -136,7 +136,6 @@ dependencies {
|
|||||||
implementation libs.jetbrains.coroutinesCore
|
implementation libs.jetbrains.coroutinesCore
|
||||||
implementation libs.jetbrains.coroutinesAndroid
|
implementation libs.jetbrains.coroutinesAndroid
|
||||||
|
|
||||||
implementation libs.androidx.appCompat
|
|
||||||
implementation libs.androidx.core
|
implementation libs.androidx.core
|
||||||
|
|
||||||
// Lifecycle
|
// Lifecycle
|
||||||
@ -155,12 +154,11 @@ dependencies {
|
|||||||
implementation(platform("com.squareup.okhttp3:okhttp-bom:4.9.3"))
|
implementation(platform("com.squareup.okhttp3:okhttp-bom:4.9.3"))
|
||||||
implementation 'com.squareup.okhttp3:okhttp'
|
implementation 'com.squareup.okhttp3:okhttp'
|
||||||
implementation 'com.squareup.okhttp3:logging-interceptor'
|
implementation 'com.squareup.okhttp3:logging-interceptor'
|
||||||
implementation 'com.squareup.okhttp3:okhttp-urlconnection'
|
|
||||||
|
|
||||||
implementation libs.squareup.moshi
|
implementation libs.squareup.moshi
|
||||||
kapt libs.squareup.moshiKotlin
|
kapt libs.squareup.moshiKotlin
|
||||||
|
|
||||||
implementation libs.markwon.core
|
api "com.atlassian.commonmark:commonmark:0.13.0"
|
||||||
|
|
||||||
// Image
|
// Image
|
||||||
implementation libs.androidx.exifinterface
|
implementation libs.androidx.exifinterface
|
||||||
@ -176,10 +174,6 @@ dependencies {
|
|||||||
// Work
|
// Work
|
||||||
implementation libs.androidx.work
|
implementation libs.androidx.work
|
||||||
|
|
||||||
// FP
|
|
||||||
implementation libs.arrow.core
|
|
||||||
implementation libs.arrow.instances
|
|
||||||
|
|
||||||
// olm lib is now hosted in MavenCentral
|
// olm lib is now hosted in MavenCentral
|
||||||
implementation 'org.matrix.android:olm-sdk:3.2.11'
|
implementation 'org.matrix.android:olm-sdk:3.2.11'
|
||||||
|
|
||||||
@ -198,11 +192,9 @@ dependencies {
|
|||||||
implementation libs.apache.commonsImaging
|
implementation libs.apache.commonsImaging
|
||||||
|
|
||||||
// Phone number https://github.com/google/libphonenumber
|
// Phone number https://github.com/google/libphonenumber
|
||||||
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.48'
|
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.49'
|
||||||
|
|
||||||
testImplementation libs.tests.junit
|
testImplementation libs.tests.junit
|
||||||
testImplementation 'org.robolectric:robolectric:4.7.3'
|
|
||||||
//testImplementation 'org.robolectric:shadows-support-v4:3.0'
|
|
||||||
// Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281
|
// Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281
|
||||||
testImplementation libs.mockk.mockk
|
testImplementation libs.mockk.mockk
|
||||||
testImplementation libs.tests.kluent
|
testImplementation libs.tests.kluent
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
# Package org.matrix.android.sdk.userstories
|
||||||
|
|
||||||
|
This package contains some user stories (**Us** prefix) of the SDK usage. You will find example of what it is possible to do with the SDK and the API which can be used to do it.
|
||||||
|
|
||||||
# Package org.matrix.android.sdk.api
|
# Package org.matrix.android.sdk.api
|
||||||
|
|
||||||
This is the root package of the API exposed by this SDK.
|
This is the root package of the API exposed by this SDK.
|
||||||
|
@ -24,8 +24,8 @@ import org.junit.runner.RunWith
|
|||||||
import org.junit.runners.JUnit4
|
import org.junit.runners.JUnit4
|
||||||
import org.junit.runners.MethodSorters
|
import org.junit.runners.MethodSorters
|
||||||
import org.matrix.android.sdk.InstrumentedTest
|
import org.matrix.android.sdk.InstrumentedTest
|
||||||
import org.matrix.android.sdk.common.CommonTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
|
||||||
import org.matrix.android.sdk.common.CryptoTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest
|
||||||
import org.matrix.android.sdk.common.SessionTestParams
|
import org.matrix.android.sdk.common.SessionTestParams
|
||||||
import org.matrix.android.sdk.common.TestConstants
|
import org.matrix.android.sdk.common.TestConstants
|
||||||
|
|
||||||
@ -34,32 +34,22 @@ import org.matrix.android.sdk.common.TestConstants
|
|||||||
@LargeTest
|
@LargeTest
|
||||||
class AccountCreationTest : InstrumentedTest {
|
class AccountCreationTest : InstrumentedTest {
|
||||||
|
|
||||||
private val commonTestHelper = CommonTestHelper(context())
|
|
||||||
private val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun createAccountTest() {
|
fun createAccountTest() = runSessionTest(context()) { commonTestHelper ->
|
||||||
val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = true))
|
commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = true))
|
||||||
|
|
||||||
commonTestHelper.signOutAndClose(session)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Ignore("This test will be ignored until it is fixed")
|
@Ignore("This test will be ignored until it is fixed")
|
||||||
fun createAccountAndLoginAgainTest() {
|
fun createAccountAndLoginAgainTest() = runSessionTest(context()) { commonTestHelper ->
|
||||||
val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = true))
|
val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = true))
|
||||||
|
|
||||||
// Log again to the same account
|
// Log again to the same account
|
||||||
val session2 = commonTestHelper.logIntoAccount(session.myUserId, SessionTestParams(withInitialSync = true))
|
commonTestHelper.logIntoAccount(session.myUserId, SessionTestParams(withInitialSync = true))
|
||||||
|
|
||||||
commonTestHelper.signOutAndClose(session)
|
|
||||||
commonTestHelper.signOutAndClose(session2)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun simpleE2eTest() {
|
fun simpleE2eTest() = runCryptoTest(context()) { cryptoTestHelper, _ ->
|
||||||
val res = cryptoTestHelper.doE2ETestWithAliceInARoom()
|
cryptoTestHelper.doE2ETestWithAliceInARoom()
|
||||||
|
|
||||||
res.cleanUp(commonTestHelper)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ import org.junit.runners.JUnit4
|
|||||||
import org.junit.runners.MethodSorters
|
import org.junit.runners.MethodSorters
|
||||||
import org.matrix.android.sdk.InstrumentedTest
|
import org.matrix.android.sdk.InstrumentedTest
|
||||||
import org.matrix.android.sdk.api.failure.isInvalidPassword
|
import org.matrix.android.sdk.api.failure.isInvalidPassword
|
||||||
import org.matrix.android.sdk.common.CommonTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest
|
||||||
import org.matrix.android.sdk.common.SessionTestParams
|
import org.matrix.android.sdk.common.SessionTestParams
|
||||||
import org.matrix.android.sdk.common.TestConstants
|
import org.matrix.android.sdk.common.TestConstants
|
||||||
|
|
||||||
@ -34,14 +34,12 @@ import org.matrix.android.sdk.common.TestConstants
|
|||||||
@Ignore("This test will be ignored until it is fixed")
|
@Ignore("This test will be ignored until it is fixed")
|
||||||
class ChangePasswordTest : InstrumentedTest {
|
class ChangePasswordTest : InstrumentedTest {
|
||||||
|
|
||||||
private val commonTestHelper = CommonTestHelper(context())
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val NEW_PASSWORD = "this is a new password"
|
private const val NEW_PASSWORD = "this is a new password"
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun changePasswordTest() {
|
fun changePasswordTest() = runSessionTest(context()) { commonTestHelper ->
|
||||||
val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = false))
|
val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = false))
|
||||||
|
|
||||||
// Change password
|
// Change password
|
||||||
@ -54,9 +52,6 @@ class ChangePasswordTest : InstrumentedTest {
|
|||||||
throwable.isInvalidPassword().shouldBeTrue()
|
throwable.isInvalidPassword().shouldBeTrue()
|
||||||
|
|
||||||
// Try to login with the new password, should work
|
// Try to login with the new password, should work
|
||||||
val session2 = commonTestHelper.logIntoAccount(session.myUserId, NEW_PASSWORD, SessionTestParams(withInitialSync = false))
|
commonTestHelper.logIntoAccount(session.myUserId, NEW_PASSWORD, SessionTestParams(withInitialSync = false))
|
||||||
|
|
||||||
commonTestHelper.signOutAndClose(session)
|
|
||||||
commonTestHelper.signOutAndClose(session2)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ import org.matrix.android.sdk.api.auth.UserPasswordAuth
|
|||||||
import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
|
import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
|
||||||
import org.matrix.android.sdk.api.failure.Failure
|
import org.matrix.android.sdk.api.failure.Failure
|
||||||
import org.matrix.android.sdk.api.failure.MatrixError
|
import org.matrix.android.sdk.api.failure.MatrixError
|
||||||
import org.matrix.android.sdk.common.CommonTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest
|
||||||
import org.matrix.android.sdk.common.SessionTestParams
|
import org.matrix.android.sdk.common.SessionTestParams
|
||||||
import org.matrix.android.sdk.common.TestConstants
|
import org.matrix.android.sdk.common.TestConstants
|
||||||
import kotlin.coroutines.Continuation
|
import kotlin.coroutines.Continuation
|
||||||
@ -39,10 +39,8 @@ import kotlin.coroutines.resume
|
|||||||
@FixMethodOrder(MethodSorters.JVM)
|
@FixMethodOrder(MethodSorters.JVM)
|
||||||
class DeactivateAccountTest : InstrumentedTest {
|
class DeactivateAccountTest : InstrumentedTest {
|
||||||
|
|
||||||
private val commonTestHelper = CommonTestHelper(context())
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun deactivateAccountTest() {
|
fun deactivateAccountTest() = runSessionTest(context(), false /* session will be deactivated */) { commonTestHelper ->
|
||||||
val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = true))
|
val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = true))
|
||||||
|
|
||||||
// Deactivate the account
|
// Deactivate the account
|
||||||
|
@ -23,7 +23,7 @@ import org.junit.runner.RunWith
|
|||||||
import org.junit.runners.JUnit4
|
import org.junit.runners.JUnit4
|
||||||
import org.junit.runners.MethodSorters
|
import org.junit.runners.MethodSorters
|
||||||
import org.matrix.android.sdk.InstrumentedTest
|
import org.matrix.android.sdk.InstrumentedTest
|
||||||
import org.matrix.android.sdk.common.CommonTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest
|
||||||
import org.matrix.android.sdk.common.SessionTestParams
|
import org.matrix.android.sdk.common.SessionTestParams
|
||||||
import org.matrix.android.sdk.common.TestConstants
|
import org.matrix.android.sdk.common.TestConstants
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
@ -32,10 +32,8 @@ import timber.log.Timber
|
|||||||
@FixMethodOrder(MethodSorters.JVM)
|
@FixMethodOrder(MethodSorters.JVM)
|
||||||
class ApiInterceptorTest : InstrumentedTest {
|
class ApiInterceptorTest : InstrumentedTest {
|
||||||
|
|
||||||
private val commonTestHelper = CommonTestHelper(context())
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun apiInterceptorTest() {
|
fun apiInterceptorTest() = runSessionTest(context()) { commonTestHelper ->
|
||||||
val responses = mutableListOf<String>()
|
val responses = mutableListOf<String>()
|
||||||
|
|
||||||
val listener = object : ApiInterceptorListener {
|
val listener = object : ApiInterceptorListener {
|
||||||
|
@ -54,12 +54,39 @@ import java.util.concurrent.TimeUnit
|
|||||||
* This class exposes methods to be used in common cases
|
* This class exposes methods to be used in common cases
|
||||||
* Registration, login, Sync, Sending messages...
|
* Registration, login, Sync, Sending messages...
|
||||||
*/
|
*/
|
||||||
class CommonTestHelper(context: Context) {
|
class CommonTestHelper private constructor(context: Context) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
internal fun runSessionTest(context: Context, autoSignoutOnClose: Boolean = true, block: (CommonTestHelper) -> Unit) {
|
||||||
|
val testHelper = CommonTestHelper(context)
|
||||||
|
return try {
|
||||||
|
block(testHelper)
|
||||||
|
} finally {
|
||||||
|
if (autoSignoutOnClose) {
|
||||||
|
testHelper.cleanUpOpenedSessions()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun runCryptoTest(context: Context, autoSignoutOnClose: Boolean = true, block: (CryptoTestHelper, CommonTestHelper) -> Unit) {
|
||||||
|
val testHelper = CommonTestHelper(context)
|
||||||
|
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
||||||
|
return try {
|
||||||
|
block(cryptoTestHelper, testHelper)
|
||||||
|
} finally {
|
||||||
|
if (autoSignoutOnClose) {
|
||||||
|
testHelper.cleanUpOpenedSessions()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal val matrix: TestMatrix
|
internal val matrix: TestMatrix
|
||||||
private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
|
private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
|
||||||
private var accountNumber = 0
|
private var accountNumber = 0
|
||||||
|
|
||||||
|
private val trackedSessions = mutableListOf<Session>()
|
||||||
|
|
||||||
fun getTestInterceptor(session: Session): MockOkHttpInterceptor? = TestModule.interceptorForSession(session.sessionId) as? MockOkHttpInterceptor
|
fun getTestInterceptor(session: Session): MockOkHttpInterceptor? = TestModule.interceptorForSession(session.sessionId) as? MockOkHttpInterceptor
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -84,6 +111,15 @@ class CommonTestHelper(context: Context) {
|
|||||||
return logIntoAccount(userId, TestConstants.PASSWORD, testParams)
|
return logIntoAccount(userId, TestConstants.PASSWORD, testParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun cleanUpOpenedSessions() {
|
||||||
|
trackedSessions.forEach {
|
||||||
|
runBlockingTest {
|
||||||
|
it.signOutService().signOut(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trackedSessions.clear()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a homeserver configuration, with Http connection allowed for test
|
* Create a homeserver configuration, with Http connection allowed for test
|
||||||
*/
|
*/
|
||||||
@ -245,7 +281,9 @@ class CommonTestHelper(context: Context) {
|
|||||||
testParams
|
testParams
|
||||||
)
|
)
|
||||||
assertNotNull(session)
|
assertNotNull(session)
|
||||||
return session
|
return session.also {
|
||||||
|
trackedSessions.add(session)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -261,7 +299,9 @@ class CommonTestHelper(context: Context) {
|
|||||||
testParams: SessionTestParams): Session {
|
testParams: SessionTestParams): Session {
|
||||||
val session = logAccountAndSync(userId, password, testParams)
|
val session = logAccountAndSync(userId, password, testParams)
|
||||||
assertNotNull(session)
|
assertNotNull(session)
|
||||||
return session
|
return session.also {
|
||||||
|
trackedSessions.add(session)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -436,6 +476,7 @@ class CommonTestHelper(context: Context) {
|
|||||||
fun Iterable<Session>.signOutAndClose() = forEach { signOutAndClose(it) }
|
fun Iterable<Session>.signOutAndClose() = forEach { signOutAndClose(it) }
|
||||||
|
|
||||||
fun signOutAndClose(session: Session) {
|
fun signOutAndClose(session: Session) {
|
||||||
|
trackedSessions.remove(session)
|
||||||
runBlockingTest(timeout = 60_000) {
|
runBlockingTest(timeout = 60_000) {
|
||||||
session.signOutService().signOut(true)
|
session.signOutService().signOut(true)
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
|||||||
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
|
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
|
||||||
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
||||||
import org.matrix.android.sdk.api.session.securestorage.EmptyKeySigner
|
import org.matrix.android.sdk.api.session.securestorage.EmptyKeySigner
|
||||||
import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageService
|
import org.matrix.android.sdk.api.session.securestorage.KeyRef
|
||||||
import org.matrix.android.sdk.api.util.Optional
|
import org.matrix.android.sdk.api.util.Optional
|
||||||
import org.matrix.android.sdk.api.util.awaitCallback
|
import org.matrix.android.sdk.api.util.awaitCallback
|
||||||
import org.matrix.android.sdk.api.util.toBase64NoPadding
|
import org.matrix.android.sdk.api.util.toBase64NoPadding
|
||||||
@ -66,7 +66,7 @@ import java.util.UUID
|
|||||||
import kotlin.coroutines.Continuation
|
import kotlin.coroutines.Continuation
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
|
|
||||||
class CryptoTestHelper(private val testHelper: CommonTestHelper) {
|
class CryptoTestHelper(val testHelper: CommonTestHelper) {
|
||||||
|
|
||||||
private val messagesFromAlice: List<String> = listOf("0 - Hello I'm Alice!", "4 - Go!")
|
private val messagesFromAlice: List<String> = listOf("0 - Hello I'm Alice!", "4 - Go!")
|
||||||
private val messagesFromBob: List<String> = listOf("1 - Hello I'm Bob!", "2 - Isn't life grand?", "3 - Let's go to the opera.")
|
private val messagesFromBob: List<String> = listOf("1 - Hello I'm Bob!", "2 - Isn't life grand?", "3 - Let's go to the opera.")
|
||||||
@ -361,19 +361,19 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) {
|
|||||||
ssssService.storeSecret(
|
ssssService.storeSecret(
|
||||||
MASTER_KEY_SSSS_NAME,
|
MASTER_KEY_SSSS_NAME,
|
||||||
session.cryptoService().crossSigningService().getCrossSigningPrivateKeys()!!.master!!,
|
session.cryptoService().crossSigningService().getCrossSigningPrivateKeys()!!.master!!,
|
||||||
listOf(SharedSecretStorageService.KeyRef(keyInfo.keyId, keyInfo.keySpec))
|
listOf(KeyRef(keyInfo.keyId, keyInfo.keySpec))
|
||||||
)
|
)
|
||||||
|
|
||||||
ssssService.storeSecret(
|
ssssService.storeSecret(
|
||||||
SELF_SIGNING_KEY_SSSS_NAME,
|
SELF_SIGNING_KEY_SSSS_NAME,
|
||||||
session.cryptoService().crossSigningService().getCrossSigningPrivateKeys()!!.selfSigned!!,
|
session.cryptoService().crossSigningService().getCrossSigningPrivateKeys()!!.selfSigned!!,
|
||||||
listOf(SharedSecretStorageService.KeyRef(keyInfo.keyId, keyInfo.keySpec))
|
listOf(KeyRef(keyInfo.keyId, keyInfo.keySpec))
|
||||||
)
|
)
|
||||||
|
|
||||||
ssssService.storeSecret(
|
ssssService.storeSecret(
|
||||||
USER_SIGNING_KEY_SSSS_NAME,
|
USER_SIGNING_KEY_SSSS_NAME,
|
||||||
session.cryptoService().crossSigningService().getCrossSigningPrivateKeys()!!.user!!,
|
session.cryptoService().crossSigningService().getCrossSigningPrivateKeys()!!.user!!,
|
||||||
listOf(SharedSecretStorageService.KeyRef(keyInfo.keyId, keyInfo.keySpec))
|
listOf(KeyRef(keyInfo.keyId, keyInfo.keySpec))
|
||||||
)
|
)
|
||||||
|
|
||||||
// set up megolm backup
|
// set up megolm backup
|
||||||
@ -390,7 +390,7 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) {
|
|||||||
ssssService.storeSecret(
|
ssssService.storeSecret(
|
||||||
KEYBACKUP_SECRET_SSSS_NAME,
|
KEYBACKUP_SECRET_SSSS_NAME,
|
||||||
secret,
|
secret,
|
||||||
listOf(SharedSecretStorageService.KeyRef(keyInfo.keyId, keyInfo.keySpec))
|
listOf(KeyRef(keyInfo.keyId, keyInfo.keySpec))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,9 @@ class RetryTestRule(val retryCount: Int = 3) : TestRule {
|
|||||||
for (i in 0 until retryCount) {
|
for (i in 0 until retryCount) {
|
||||||
try {
|
try {
|
||||||
base.evaluate()
|
base.evaluate()
|
||||||
|
if (i > 0) {
|
||||||
|
println("Retried test $i times")
|
||||||
|
}
|
||||||
return
|
return
|
||||||
} catch (t: Throwable) {
|
} catch (t: Throwable) {
|
||||||
caughtThrowable = t
|
caughtThrowable = t
|
||||||
|
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.matrix.android.sdk.internal.crypto
|
||||||
|
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import org.junit.Assert
|
||||||
|
import org.junit.FixMethodOrder
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.junit.runners.MethodSorters
|
||||||
|
import org.matrix.android.sdk.InstrumentedTest
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
|
import org.matrix.android.sdk.api.session.getRoom
|
||||||
|
import org.matrix.android.sdk.api.session.room.getTimelineEvent
|
||||||
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
@FixMethodOrder(MethodSorters.JVM)
|
||||||
|
class DecryptRedactedEventTest : InstrumentedTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun doNotFailToDecryptRedactedEvent() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
|
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
|
||||||
|
val e2eRoomID = testData.roomId
|
||||||
|
val aliceSession = testData.firstSession
|
||||||
|
val bobSession = testData.secondSession!!
|
||||||
|
|
||||||
|
val roomALicePOV = aliceSession.getRoom(e2eRoomID)!!
|
||||||
|
val timelineEvent = testHelper.sendTextMessage(roomALicePOV, "Hello", 1).first()
|
||||||
|
val redactionReason = "Wrong Room"
|
||||||
|
roomALicePOV.sendService().redactEvent(timelineEvent.root, redactionReason)
|
||||||
|
|
||||||
|
// get the event from bob
|
||||||
|
testHelper.waitWithLatch {
|
||||||
|
testHelper.retryPeriodicallyWithLatch(it) {
|
||||||
|
bobSession.getRoom(e2eRoomID)?.getTimelineEvent(timelineEvent.eventId)?.root?.isRedacted() == true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val eventBobPov = bobSession.getRoom(e2eRoomID)?.getTimelineEvent(timelineEvent.eventId)!!
|
||||||
|
|
||||||
|
testHelper.runBlockingTest {
|
||||||
|
try {
|
||||||
|
val result = bobSession.cryptoService().decryptEvent(eventBobPov.root, "")
|
||||||
|
Assert.assertEquals(
|
||||||
|
"Unexpected redacted reason",
|
||||||
|
redactionReason,
|
||||||
|
result.clearEvent.toModel<Event>()?.unsignedData?.redactedEvent?.content?.get("reason")
|
||||||
|
)
|
||||||
|
Assert.assertEquals(
|
||||||
|
"Unexpected Redacted event id",
|
||||||
|
timelineEvent.eventId,
|
||||||
|
result.clearEvent.toModel<Event>()?.unsignedData?.redactedEvent?.redacts
|
||||||
|
)
|
||||||
|
} catch (failure: Throwable) {
|
||||||
|
Assert.fail("Should not throw when decrypting a redacted event")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,6 +23,7 @@ import org.amshove.kluent.fail
|
|||||||
import org.amshove.kluent.internal.assertEquals
|
import org.amshove.kluent.internal.assertEquals
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.FixMethodOrder
|
import org.junit.FixMethodOrder
|
||||||
|
import org.junit.Ignore
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
@ -57,7 +58,8 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageContent
|
|||||||
import org.matrix.android.sdk.api.session.room.send.SendState
|
import org.matrix.android.sdk.api.session.room.send.SendState
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
|
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
|
||||||
import org.matrix.android.sdk.common.CommonTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper
|
||||||
import org.matrix.android.sdk.common.CryptoTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
|
||||||
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest
|
||||||
import org.matrix.android.sdk.common.RetryTestRule
|
import org.matrix.android.sdk.common.RetryTestRule
|
||||||
import org.matrix.android.sdk.common.SessionTestParams
|
import org.matrix.android.sdk.common.SessionTestParams
|
||||||
import org.matrix.android.sdk.common.TestConstants
|
import org.matrix.android.sdk.common.TestConstants
|
||||||
@ -68,6 +70,7 @@ import java.util.concurrent.CountDownLatch
|
|||||||
@RunWith(JUnit4::class)
|
@RunWith(JUnit4::class)
|
||||||
@FixMethodOrder(MethodSorters.JVM)
|
@FixMethodOrder(MethodSorters.JVM)
|
||||||
@LargeTest
|
@LargeTest
|
||||||
|
@Ignore("This test fails with an unhandled exception thrown from a coroutine which terminates the entire test run.")
|
||||||
class E2eeSanityTests : InstrumentedTest {
|
class E2eeSanityTests : InstrumentedTest {
|
||||||
|
|
||||||
@get:Rule val rule = RetryTestRule(3)
|
@get:Rule val rule = RetryTestRule(3)
|
||||||
@ -82,9 +85,7 @@ class E2eeSanityTests : InstrumentedTest {
|
|||||||
* Alice sends a new message, then check that the new one can be decrypted
|
* Alice sends a new message, then check that the new one can be decrypted
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun testSendingE2EEMessages() {
|
fun testSendingE2EEMessages() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
|
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
|
||||||
val aliceSession = cryptoTestData.firstSession
|
val aliceSession = cryptoTestData.firstSession
|
||||||
@ -198,21 +199,12 @@ class E2eeSanityTests : InstrumentedTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
otherAccounts.forEach {
|
|
||||||
testHelper.signOutAndClose(it)
|
|
||||||
}
|
|
||||||
newAccount.forEach { testHelper.signOutAndClose(it) }
|
|
||||||
|
|
||||||
cryptoTestData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testKeyGossipingIsEnabledByDefault() {
|
fun testKeyGossipingIsEnabledByDefault() = runSessionTest(context()) { testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val session = testHelper.createAccount("alice", SessionTestParams(true))
|
val session = testHelper.createAccount("alice", SessionTestParams(true))
|
||||||
Assert.assertTrue("Key gossiping should be enabled by default", session.cryptoService().isKeyGossipingEnabled())
|
Assert.assertTrue("Key gossiping should be enabled by default", session.cryptoService().isKeyGossipingEnabled())
|
||||||
testHelper.signOutAndClose(session)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -230,9 +222,7 @@ class E2eeSanityTests : InstrumentedTest {
|
|||||||
* 9. Check that new session can decrypt
|
* 9. Check that new session can decrypt
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun testBasicBackupImport() {
|
fun testBasicBackupImport() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
|
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
|
||||||
val aliceSession = cryptoTestData.firstSession
|
val aliceSession = cryptoTestData.firstSession
|
||||||
@ -344,8 +334,6 @@ class E2eeSanityTests : InstrumentedTest {
|
|||||||
|
|
||||||
// ensure bob can now decrypt
|
// ensure bob can now decrypt
|
||||||
cryptoTestHelper.ensureCanDecrypt(sentEventIds, newBobSession, e2eRoomID, messagesText)
|
cryptoTestHelper.ensureCanDecrypt(sentEventIds, newBobSession, e2eRoomID, messagesText)
|
||||||
|
|
||||||
testHelper.signOutAndClose(newBobSession)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -353,9 +341,7 @@ class E2eeSanityTests : InstrumentedTest {
|
|||||||
* get them from an older one.
|
* get them from an older one.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun testSimpleGossip() {
|
fun testSimpleGossip() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
|
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
|
||||||
val aliceSession = cryptoTestData.firstSession
|
val aliceSession = cryptoTestData.firstSession
|
||||||
@ -449,18 +435,13 @@ class E2eeSanityTests : InstrumentedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cryptoTestHelper.ensureCanDecrypt(sentEventIds, newBobSession, e2eRoomID, messagesText)
|
cryptoTestHelper.ensureCanDecrypt(sentEventIds, newBobSession, e2eRoomID, messagesText)
|
||||||
|
|
||||||
cryptoTestData.cleanUp(testHelper)
|
|
||||||
testHelper.signOutAndClose(newBobSession)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that if a better key is forwarded (lower index, it is then used)
|
* Test that if a better key is forwarded (lower index, it is then used)
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun testForwardBetterKey() {
|
fun testForwardBetterKey() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
|
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
|
||||||
val aliceSession = cryptoTestData.firstSession
|
val aliceSession = cryptoTestData.firstSession
|
||||||
@ -576,10 +557,6 @@ class E2eeSanityTests : InstrumentedTest {
|
|||||||
canDecryptFirst && canDecryptSecond
|
canDecryptFirst && canDecryptSecond
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
testHelper.signOutAndClose(aliceSession)
|
|
||||||
testHelper.signOutAndClose(bobSessionWithBetterKey)
|
|
||||||
testHelper.signOutAndClose(newBobSession)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sendMessageInRoom(testHelper: CommonTestHelper, aliceRoomPOV: Room, text: String): String? {
|
private fun sendMessageInRoom(testHelper: CommonTestHelper, aliceRoomPOV: Room, text: String): String? {
|
||||||
@ -610,9 +587,7 @@ class E2eeSanityTests : InstrumentedTest {
|
|||||||
* Test that if a better key is forwared (lower index, it is then used)
|
* Test that if a better key is forwared (lower index, it is then used)
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun testSelfInteractiveVerificationAndGossip() {
|
fun testASelfInteractiveVerificationAndGossip() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
|
|
||||||
val aliceSession = testHelper.createAccount("alice", SessionTestParams(true))
|
val aliceSession = testHelper.createAccount("alice", SessionTestParams(true))
|
||||||
cryptoTestHelper.bootstrapSecurity(aliceSession)
|
cryptoTestHelper.bootstrapSecurity(aliceSession)
|
||||||
@ -751,9 +726,6 @@ class E2eeSanityTests : InstrumentedTest {
|
|||||||
aliceSession.cryptoService().keysBackupService().getKeyBackupRecoveryKeyInfo()!!.version,
|
aliceSession.cryptoService().keysBackupService().getKeyBackupRecoveryKeyInfo()!!.version,
|
||||||
aliceNewSession.cryptoService().keysBackupService().getKeyBackupRecoveryKeyInfo()!!.version
|
aliceNewSession.cryptoService().keysBackupService().getKeyBackupRecoveryKeyInfo()!!.version
|
||||||
)
|
)
|
||||||
|
|
||||||
testHelper.signOutAndClose(aliceSession)
|
|
||||||
testHelper.signOutAndClose(aliceNewSession)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ensureMembersHaveJoined(testHelper: CommonTestHelper, aliceSession: Session, otherAccounts: List<Session>, e2eRoomID: String) {
|
private fun ensureMembersHaveJoined(testHelper: CommonTestHelper, aliceSession: Session, otherAccounts: List<Session>, e2eRoomID: String) {
|
||||||
|
@ -30,18 +30,14 @@ import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventCon
|
|||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
import org.matrix.android.sdk.api.session.getRoom
|
import org.matrix.android.sdk.api.session.getRoom
|
||||||
import org.matrix.android.sdk.api.session.room.getTimelineEvent
|
import org.matrix.android.sdk.api.session.room.getTimelineEvent
|
||||||
import org.matrix.android.sdk.common.CommonTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
|
||||||
import org.matrix.android.sdk.common.CryptoTestHelper
|
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@FixMethodOrder(MethodSorters.JVM)
|
@FixMethodOrder(MethodSorters.JVM)
|
||||||
class PreShareKeysTest : InstrumentedTest {
|
class PreShareKeysTest : InstrumentedTest {
|
||||||
|
|
||||||
private val testHelper = CommonTestHelper(context())
|
|
||||||
private val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun ensure_outbound_session_happy_path() {
|
fun ensure_outbound_session_happy_path() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
|
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
|
||||||
val e2eRoomID = testData.roomId
|
val e2eRoomID = testData.roomId
|
||||||
val aliceSession = testData.firstSession
|
val aliceSession = testData.firstSession
|
||||||
@ -94,7 +90,5 @@ class PreShareKeysTest : InstrumentedTest {
|
|||||||
bobSession.getRoom(e2eRoomID)?.getTimelineEvent(sentEvent.eventId)?.root?.getClearType() == EventType.MESSAGE
|
bobSession.getRoom(e2eRoomID)?.getTimelineEvent(sentEvent.eventId)?.root?.getClearType() == EventType.MESSAGE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
testData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,8 +38,7 @@ import org.matrix.android.sdk.api.session.getRoom
|
|||||||
import org.matrix.android.sdk.api.session.room.timeline.Timeline
|
import org.matrix.android.sdk.api.session.room.timeline.Timeline
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
|
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
|
||||||
import org.matrix.android.sdk.common.CommonTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
|
||||||
import org.matrix.android.sdk.common.CryptoTestHelper
|
|
||||||
import org.matrix.android.sdk.common.TestConstants
|
import org.matrix.android.sdk.common.TestConstants
|
||||||
import org.matrix.android.sdk.internal.crypto.model.OlmSessionWrapper
|
import org.matrix.android.sdk.internal.crypto.model.OlmSessionWrapper
|
||||||
import org.matrix.android.sdk.internal.crypto.store.db.deserializeFromRealm
|
import org.matrix.android.sdk.internal.crypto.store.db.deserializeFromRealm
|
||||||
@ -63,8 +62,6 @@ import kotlin.coroutines.resume
|
|||||||
class UnwedgingTest : InstrumentedTest {
|
class UnwedgingTest : InstrumentedTest {
|
||||||
|
|
||||||
private lateinit var messagesReceivedByBob: List<TimelineEvent>
|
private lateinit var messagesReceivedByBob: List<TimelineEvent>
|
||||||
private val testHelper = CommonTestHelper(context())
|
|
||||||
private val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun init() {
|
fun init() {
|
||||||
@ -85,7 +82,7 @@ class UnwedgingTest : InstrumentedTest {
|
|||||||
* -> This is automatically fixed after SDKs restarted the olm session
|
* -> This is automatically fixed after SDKs restarted the olm session
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun testUnwedging() {
|
fun testUnwedging() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
||||||
|
|
||||||
val aliceSession = cryptoTestData.firstSession
|
val aliceSession = cryptoTestData.firstSession
|
||||||
@ -240,8 +237,6 @@ class UnwedgingTest : InstrumentedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bobTimeline.dispose()
|
bobTimeline.dispose()
|
||||||
|
|
||||||
cryptoTestData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createEventListener(latch: CountDownLatch, expectedNumberOfMessages: Int): Timeline.Listener {
|
private fun createEventListener(latch: CountDownLatch, expectedNumberOfMessages: Int): Timeline.Listener {
|
||||||
|
@ -37,8 +37,8 @@ import org.matrix.android.sdk.api.session.crypto.crosssigning.isCrossSignedVerif
|
|||||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.isVerified
|
import org.matrix.android.sdk.api.session.crypto.crosssigning.isVerified
|
||||||
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
|
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
|
||||||
import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap
|
import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap
|
||||||
import org.matrix.android.sdk.common.CommonTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
|
||||||
import org.matrix.android.sdk.common.CryptoTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest
|
||||||
import org.matrix.android.sdk.common.SessionTestParams
|
import org.matrix.android.sdk.common.SessionTestParams
|
||||||
import org.matrix.android.sdk.common.TestConstants
|
import org.matrix.android.sdk.common.TestConstants
|
||||||
import kotlin.coroutines.Continuation
|
import kotlin.coroutines.Continuation
|
||||||
@ -49,11 +49,8 @@ import kotlin.coroutines.resume
|
|||||||
@LargeTest
|
@LargeTest
|
||||||
class XSigningTest : InstrumentedTest {
|
class XSigningTest : InstrumentedTest {
|
||||||
|
|
||||||
private val testHelper = CommonTestHelper(context())
|
|
||||||
private val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_InitializeAndStoreKeys() {
|
fun test_InitializeAndStoreKeys() = runSessionTest(context()) { testHelper ->
|
||||||
val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
|
val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
|
||||||
|
|
||||||
testHelper.doSync<Unit> {
|
testHelper.doSync<Unit> {
|
||||||
@ -87,7 +84,7 @@ class XSigningTest : InstrumentedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_CrossSigningCheckBobSeesTheKeys() {
|
fun test_CrossSigningCheckBobSeesTheKeys() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
||||||
|
|
||||||
val aliceSession = cryptoTestData.firstSession
|
val aliceSession = cryptoTestData.firstSession
|
||||||
@ -137,12 +134,10 @@ class XSigningTest : InstrumentedTest {
|
|||||||
)
|
)
|
||||||
|
|
||||||
assertFalse("Bob keys from alice pov should not be trusted", bobKeysFromAlicePOV.isTrusted())
|
assertFalse("Bob keys from alice pov should not be trusted", bobKeysFromAlicePOV.isTrusted())
|
||||||
|
|
||||||
cryptoTestData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_CrossSigningTestAliceTrustBobNewDevice() {
|
fun test_CrossSigningTestAliceTrustBobNewDevice() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
||||||
|
|
||||||
val aliceSession = cryptoTestData.firstSession
|
val aliceSession = cryptoTestData.firstSession
|
||||||
@ -216,9 +211,5 @@ class XSigningTest : InstrumentedTest {
|
|||||||
|
|
||||||
val result = aliceSession.cryptoService().crossSigningService().checkDeviceTrust(bobUserId, bobSecondDeviceId, null)
|
val result = aliceSession.cryptoService().crossSigningService().checkDeviceTrust(bobUserId, bobSecondDeviceId, null)
|
||||||
assertTrue("Bob second device should be trusted from alice POV", result.isCrossSignedVerified())
|
assertTrue("Bob second device should be trusted from alice POV", result.isCrossSignedVerified())
|
||||||
|
|
||||||
testHelper.signOutAndClose(aliceSession)
|
|
||||||
testHelper.signOutAndClose(bobSession)
|
|
||||||
testHelper.signOutAndClose(bobSession2)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ import org.matrix.android.sdk.api.session.room.timeline.Timeline
|
|||||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
|
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
|
||||||
import org.matrix.android.sdk.common.CommonTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper
|
||||||
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
|
||||||
import org.matrix.android.sdk.common.CryptoTestHelper
|
import org.matrix.android.sdk.common.CryptoTestHelper
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.concurrent.CountDownLatch
|
||||||
|
|
||||||
@ -42,12 +43,10 @@ import java.util.concurrent.CountDownLatch
|
|||||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||||
class EncryptionTest : InstrumentedTest {
|
class EncryptionTest : InstrumentedTest {
|
||||||
|
|
||||||
private val testHelper = CommonTestHelper(context())
|
|
||||||
private val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_EncryptionEvent() {
|
fun test_EncryptionEvent() {
|
||||||
performTest(roomShouldBeEncrypted = false) { room ->
|
runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
|
performTest(cryptoTestHelper, testHelper, roomShouldBeEncrypted = false) { room ->
|
||||||
// Send an encryption Event as an Event (and not as a state event)
|
// Send an encryption Event as an Event (and not as a state event)
|
||||||
room.sendService().sendEvent(
|
room.sendService().sendEvent(
|
||||||
eventType = EventType.STATE_ROOM_ENCRYPTION,
|
eventType = EventType.STATE_ROOM_ENCRYPTION,
|
||||||
@ -55,10 +54,12 @@ class EncryptionTest : InstrumentedTest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_EncryptionStateEvent() {
|
fun test_EncryptionStateEvent() {
|
||||||
performTest(roomShouldBeEncrypted = true) { room ->
|
runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
|
performTest(cryptoTestHelper, testHelper, roomShouldBeEncrypted = true) { room ->
|
||||||
runBlocking {
|
runBlocking {
|
||||||
// Send an encryption Event as a State Event
|
// Send an encryption Event as a State Event
|
||||||
room.stateService().sendStateEvent(
|
room.stateService().sendStateEvent(
|
||||||
@ -69,8 +70,9 @@ class EncryptionTest : InstrumentedTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun performTest(roomShouldBeEncrypted: Boolean, action: (Room) -> Unit) {
|
private fun performTest(cryptoTestHelper: CryptoTestHelper, testHelper: CommonTestHelper, roomShouldBeEncrypted: Boolean, action: (Room) -> Unit) {
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceInARoom(encryptedRoom = false)
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceInARoom(encryptedRoom = false)
|
||||||
|
|
||||||
val aliceSession = cryptoTestData.firstSession
|
val aliceSession = cryptoTestData.firstSession
|
||||||
@ -109,6 +111,5 @@ class EncryptionTest : InstrumentedTest {
|
|||||||
room.roomCryptoService().isEncrypted() shouldBe roomShouldBeEncrypted
|
room.roomCryptoService().isEncrypted() shouldBe roomShouldBeEncrypted
|
||||||
it.countDown()
|
it.countDown()
|
||||||
}
|
}
|
||||||
cryptoTestData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,8 +41,7 @@ import org.matrix.android.sdk.api.session.room.getTimelineEvent
|
|||||||
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
|
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent
|
import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent
|
||||||
import org.matrix.android.sdk.common.CommonTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
|
||||||
import org.matrix.android.sdk.common.CryptoTestHelper
|
|
||||||
import org.matrix.android.sdk.common.RetryTestRule
|
import org.matrix.android.sdk.common.RetryTestRule
|
||||||
import org.matrix.android.sdk.common.SessionTestParams
|
import org.matrix.android.sdk.common.SessionTestParams
|
||||||
import org.matrix.android.sdk.common.TestConstants
|
import org.matrix.android.sdk.common.TestConstants
|
||||||
@ -56,9 +55,7 @@ class KeyShareTests : InstrumentedTest {
|
|||||||
@get:Rule val rule = RetryTestRule(3)
|
@get:Rule val rule = RetryTestRule(3)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_DoNotSelfShareIfNotTrusted() {
|
fun test_DoNotSelfShareIfNotTrusted() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
|
||||||
val commonTestHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
|
|
||||||
|
|
||||||
val aliceSession = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
|
val aliceSession = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
|
||||||
Log.v("TEST", "=======> AliceSession 1 is ${aliceSession.sessionParams.deviceId}")
|
Log.v("TEST", "=======> AliceSession 1 is ${aliceSession.sessionParams.deviceId}")
|
||||||
@ -194,9 +191,7 @@ class KeyShareTests : InstrumentedTest {
|
|||||||
* if the key was originally shared with him
|
* if the key was originally shared with him
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun test_reShareIfWasIntendedToBeShared() {
|
fun test_reShareIfWasIntendedToBeShared() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
|
||||||
val commonTestHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
|
|
||||||
|
|
||||||
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
|
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
|
||||||
val aliceSession = testData.firstSession
|
val aliceSession = testData.firstSession
|
||||||
@ -227,9 +222,7 @@ class KeyShareTests : InstrumentedTest {
|
|||||||
* if the key was originally shared with him
|
* if the key was originally shared with him
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun test_reShareToUnverifiedIfWasIntendedToBeShared() {
|
fun test_reShareToUnverifiedIfWasIntendedToBeShared() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
|
||||||
val commonTestHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
|
|
||||||
|
|
||||||
val testData = cryptoTestHelper.doE2ETestWithAliceInARoom(true)
|
val testData = cryptoTestHelper.doE2ETestWithAliceInARoom(true)
|
||||||
val aliceSession = testData.firstSession
|
val aliceSession = testData.firstSession
|
||||||
@ -266,9 +259,7 @@ class KeyShareTests : InstrumentedTest {
|
|||||||
* Tests that keys reshared with own verified session are done from the earliest known index
|
* Tests that keys reshared with own verified session are done from the earliest known index
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun test_reShareFromTheEarliestKnownIndexWithOwnVerifiedSession() {
|
fun test_reShareFromTheEarliestKnownIndexWithOwnVerifiedSession() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
|
||||||
val commonTestHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
|
|
||||||
|
|
||||||
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
|
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
|
||||||
val aliceSession = testData.firstSession
|
val aliceSession = testData.firstSession
|
||||||
@ -388,10 +379,7 @@ class KeyShareTests : InstrumentedTest {
|
|||||||
* Tests that we don't cancel a request to early on first forward if the index is not good enough
|
* Tests that we don't cancel a request to early on first forward if the index is not good enough
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun test_dontCancelToEarly() {
|
fun test_dontCancelToEarly() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
|
||||||
val commonTestHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
|
|
||||||
|
|
||||||
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
|
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
|
||||||
val aliceSession = testData.firstSession
|
val aliceSession = testData.firstSession
|
||||||
val bobSession = testData.secondSession!!
|
val bobSession = testData.secondSession!!
|
||||||
|
@ -36,8 +36,7 @@ import org.matrix.android.sdk.api.session.events.model.content.WithHeldCode
|
|||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
import org.matrix.android.sdk.api.session.getRoom
|
import org.matrix.android.sdk.api.session.getRoom
|
||||||
import org.matrix.android.sdk.api.session.room.getTimelineEvent
|
import org.matrix.android.sdk.api.session.room.getTimelineEvent
|
||||||
import org.matrix.android.sdk.common.CommonTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
|
||||||
import org.matrix.android.sdk.common.CryptoTestHelper
|
|
||||||
import org.matrix.android.sdk.common.MockOkHttpInterceptor
|
import org.matrix.android.sdk.common.MockOkHttpInterceptor
|
||||||
import org.matrix.android.sdk.common.RetryTestRule
|
import org.matrix.android.sdk.common.RetryTestRule
|
||||||
import org.matrix.android.sdk.common.SessionTestParams
|
import org.matrix.android.sdk.common.SessionTestParams
|
||||||
@ -52,9 +51,7 @@ class WithHeldTests : InstrumentedTest {
|
|||||||
@get:Rule val rule = RetryTestRule(3)
|
@get:Rule val rule = RetryTestRule(3)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_WithHeldUnverifiedReason() {
|
fun test_WithHeldUnverifiedReason() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
|
|
||||||
// =============================
|
// =============================
|
||||||
// ARRANGE
|
// ARRANGE
|
||||||
@ -153,16 +150,10 @@ class WithHeldTests : InstrumentedTest {
|
|||||||
bobUnverifiedSession.cryptoService().decryptEvent(eventBobPOV.root, "")
|
bobUnverifiedSession.cryptoService().decryptEvent(eventBobPOV.root, "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
testHelper.signOutAndClose(aliceSession)
|
|
||||||
testHelper.signOutAndClose(bobSession)
|
|
||||||
testHelper.signOutAndClose(bobUnverifiedSession)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_WithHeldNoOlm() {
|
fun test_WithHeldNoOlm() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
|
|
||||||
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
||||||
val aliceSession = testData.firstSession
|
val aliceSession = testData.firstSession
|
||||||
@ -239,14 +230,10 @@ class WithHeldTests : InstrumentedTest {
|
|||||||
Assert.assertEquals("Alice should have marked bob's device for this session", 1, chainIndex2)
|
Assert.assertEquals("Alice should have marked bob's device for this session", 1, chainIndex2)
|
||||||
|
|
||||||
aliceInterceptor.clearRules()
|
aliceInterceptor.clearRules()
|
||||||
testData.cleanUp(testHelper)
|
|
||||||
testHelper.signOutAndClose(bobSecondSession)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_WithHeldKeyRequest() {
|
fun test_WithHeldKeyRequest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
|
|
||||||
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
||||||
val aliceSession = testData.firstSession
|
val aliceSession = testData.firstSession
|
||||||
@ -293,8 +280,5 @@ class WithHeldTests : InstrumentedTest {
|
|||||||
wc?.code == WithHeldCode.UNAUTHORISED
|
wc?.code == WithHeldCode.UNAUTHORISED
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
testHelper.signOutAndClose(aliceSession)
|
|
||||||
testHelper.signOutAndClose(bobSecondSession)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import org.junit.Assert.assertNotNull
|
|||||||
import org.junit.Assert.assertNull
|
import org.junit.Assert.assertNull
|
||||||
import org.junit.Assert.assertTrue
|
import org.junit.Assert.assertTrue
|
||||||
import org.junit.FixMethodOrder
|
import org.junit.FixMethodOrder
|
||||||
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.junit.runners.MethodSorters
|
import org.junit.runners.MethodSorters
|
||||||
@ -43,8 +44,9 @@ import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreation
|
|||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.toKeysVersionResult
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.toKeysVersionResult
|
||||||
import org.matrix.android.sdk.api.session.crypto.model.ImportRoomKeysResult
|
import org.matrix.android.sdk.api.session.crypto.model.ImportRoomKeysResult
|
||||||
import org.matrix.android.sdk.api.session.getRoom
|
import org.matrix.android.sdk.api.session.getRoom
|
||||||
import org.matrix.android.sdk.common.CommonTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
|
||||||
import org.matrix.android.sdk.common.CryptoTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest
|
||||||
|
import org.matrix.android.sdk.common.RetryTestRule
|
||||||
import org.matrix.android.sdk.common.TestConstants
|
import org.matrix.android.sdk.common.TestConstants
|
||||||
import org.matrix.android.sdk.common.TestMatrixCallback
|
import org.matrix.android.sdk.common.TestMatrixCallback
|
||||||
import java.util.Collections
|
import java.util.Collections
|
||||||
@ -55,15 +57,15 @@ import java.util.concurrent.CountDownLatch
|
|||||||
@LargeTest
|
@LargeTest
|
||||||
class KeysBackupTest : InstrumentedTest {
|
class KeysBackupTest : InstrumentedTest {
|
||||||
|
|
||||||
|
@get:Rule val rule = RetryTestRule(3)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* - From doE2ETestWithAliceAndBobInARoomWithEncryptedMessages, we should have no backed up keys
|
* - From doE2ETestWithAliceAndBobInARoomWithEncryptedMessages, we should have no backed up keys
|
||||||
* - Check backup keys after having marked one as backed up
|
* - Check backup keys after having marked one as backed up
|
||||||
* - Reset keys backup markers
|
* - Reset keys backup markers
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun roomKeysTest_testBackupStore_ok() {
|
fun roomKeysTest_testBackupStore_ok() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
|
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages()
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages()
|
||||||
|
|
||||||
@ -102,8 +104,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
* Check that prepareKeysBackupVersionWithPassword returns valid data
|
* Check that prepareKeysBackupVersionWithPassword returns valid data
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun prepareKeysBackupVersionTest() {
|
fun prepareKeysBackupVersionTest() = runSessionTest(context()) { testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
|
|
||||||
val bobSession = testHelper.createAccount(TestConstants.USER_BOB, KeysBackupTestConstants.defaultSessionParams)
|
val bobSession = testHelper.createAccount(TestConstants.USER_BOB, KeysBackupTestConstants.defaultSessionParams)
|
||||||
|
|
||||||
@ -113,7 +114,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
|
|
||||||
val stateObserver = StateObserver(keysBackup)
|
val stateObserver = StateObserver(keysBackup)
|
||||||
|
|
||||||
assertFalse(keysBackup.isEnabled)
|
assertFalse(keysBackup.isEnabled())
|
||||||
|
|
||||||
val megolmBackupCreationInfo = testHelper.doSync<MegolmBackupCreationInfo> {
|
val megolmBackupCreationInfo = testHelper.doSync<MegolmBackupCreationInfo> {
|
||||||
keysBackup.prepareKeysBackupVersion(null, null, it)
|
keysBackup.prepareKeysBackupVersion(null, null, it)
|
||||||
@ -125,16 +126,13 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
assertNotNull(megolmBackupCreationInfo.recoveryKey)
|
assertNotNull(megolmBackupCreationInfo.recoveryKey)
|
||||||
|
|
||||||
stateObserver.stopAndCheckStates(null)
|
stateObserver.stopAndCheckStates(null)
|
||||||
testHelper.signOutAndClose(bobSession)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test creating a keys backup version and check that createKeysBackupVersion() returns valid data
|
* Test creating a keys backup version and check that createKeysBackupVersion() returns valid data
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun createKeysBackupVersionTest() {
|
fun createKeysBackupVersionTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
|
|
||||||
val bobSession = testHelper.createAccount(TestConstants.USER_BOB, KeysBackupTestConstants.defaultSessionParams)
|
val bobSession = testHelper.createAccount(TestConstants.USER_BOB, KeysBackupTestConstants.defaultSessionParams)
|
||||||
cryptoTestHelper.initializeCrossSigning(bobSession)
|
cryptoTestHelper.initializeCrossSigning(bobSession)
|
||||||
@ -143,13 +141,13 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
|
|
||||||
val stateObserver = StateObserver(keysBackup)
|
val stateObserver = StateObserver(keysBackup)
|
||||||
|
|
||||||
assertFalse(keysBackup.isEnabled)
|
assertFalse(keysBackup.isEnabled())
|
||||||
|
|
||||||
val megolmBackupCreationInfo = testHelper.doSync<MegolmBackupCreationInfo> {
|
val megolmBackupCreationInfo = testHelper.doSync<MegolmBackupCreationInfo> {
|
||||||
keysBackup.prepareKeysBackupVersion(null, null, it)
|
keysBackup.prepareKeysBackupVersion(null, null, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
assertFalse(keysBackup.isEnabled)
|
assertFalse(keysBackup.isEnabled())
|
||||||
|
|
||||||
// Create the version
|
// Create the version
|
||||||
val version = testHelper.doSync<KeysVersion> {
|
val version = testHelper.doSync<KeysVersion> {
|
||||||
@ -157,7 +155,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Backup must be enable now
|
// Backup must be enable now
|
||||||
assertTrue(keysBackup.isEnabled)
|
assertTrue(keysBackup.isEnabled())
|
||||||
|
|
||||||
// Check that it's signed with MSK
|
// Check that it's signed with MSK
|
||||||
val versionResult = testHelper.doSync<KeysVersionResult?> {
|
val versionResult = testHelper.doSync<KeysVersionResult?> {
|
||||||
@ -193,7 +191,6 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
stateObserver.stopAndCheckStates(null)
|
stateObserver.stopAndCheckStates(null)
|
||||||
testHelper.signOutAndClose(bobSession)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -201,9 +198,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
* - Check the backup completes
|
* - Check the backup completes
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun backupAfterCreateKeysBackupVersionTest() {
|
fun backupAfterCreateKeysBackupVersionTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
||||||
|
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages()
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages()
|
||||||
@ -238,16 +233,13 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
KeysBackupState.ReadyToBackUp
|
KeysBackupState.ReadyToBackUp
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
cryptoTestData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check that backupAllGroupSessions() returns valid data
|
* Check that backupAllGroupSessions() returns valid data
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun backupAllGroupSessionsTest() {
|
fun backupAllGroupSessionsTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
||||||
|
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages()
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages()
|
||||||
@ -281,7 +273,6 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
assertEquals("All keys must have been marked as backed up", nbOfKeys, backedUpKeys)
|
assertEquals("All keys must have been marked as backed up", nbOfKeys, backedUpKeys)
|
||||||
|
|
||||||
stateObserver.stopAndCheckStates(null)
|
stateObserver.stopAndCheckStates(null)
|
||||||
cryptoTestData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -293,9 +284,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
* - Compare the decrypted megolm key with the original one
|
* - Compare the decrypted megolm key with the original one
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun testEncryptAndDecryptKeysBackupData() {
|
fun testEncryptAndDecryptKeysBackupData() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
||||||
|
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages()
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages()
|
||||||
@ -330,7 +319,6 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
keysBackupTestHelper.assertKeysEquals(session.exportKeys(), sessionData)
|
keysBackupTestHelper.assertKeysEquals(session.exportKeys(), sessionData)
|
||||||
|
|
||||||
stateObserver.stopAndCheckStates(null)
|
stateObserver.stopAndCheckStates(null)
|
||||||
cryptoTestData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -340,9 +328,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
* - Restore must be successful
|
* - Restore must be successful
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun restoreKeysBackupTest() {
|
fun restoreKeysBackupTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
||||||
|
|
||||||
val testData = keysBackupTestHelper.createKeysBackupScenarioWithPassword(null)
|
val testData = keysBackupTestHelper.createKeysBackupScenarioWithPassword(null)
|
||||||
@ -428,9 +414,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
* - It must be trusted and must have with 2 signatures now
|
* - It must be trusted and must have with 2 signatures now
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun trustKeyBackupVersionTest() {
|
fun trustKeyBackupVersionTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
||||||
|
|
||||||
// - Do an e2e backup to the homeserver with a recovery key
|
// - Do an e2e backup to the homeserver with a recovery key
|
||||||
@ -441,8 +425,8 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
|
|
||||||
// - The new device must see the previous backup as not trusted
|
// - The new device must see the previous backup as not trusted
|
||||||
assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion)
|
assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion)
|
||||||
assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled)
|
assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled())
|
||||||
assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state)
|
assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().getState())
|
||||||
|
|
||||||
// - Trust the backup from the new device
|
// - Trust the backup from the new device
|
||||||
testHelper.doSync<Unit> {
|
testHelper.doSync<Unit> {
|
||||||
@ -458,7 +442,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
|
|
||||||
// - Backup must be enabled on the new device, on the same version
|
// - Backup must be enabled on the new device, on the same version
|
||||||
assertEquals(testData.prepareKeysBackupDataResult.version, testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion?.version)
|
assertEquals(testData.prepareKeysBackupDataResult.version, testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion?.version)
|
||||||
assertTrue(testData.aliceSession2.cryptoService().keysBackupService().isEnabled)
|
assertTrue(testData.aliceSession2.cryptoService().keysBackupService().isEnabled())
|
||||||
|
|
||||||
// - Retrieve the last version from the server
|
// - Retrieve the last version from the server
|
||||||
val keysVersionResult = testHelper.doSync<KeysBackupLastVersionResult> {
|
val keysVersionResult = testHelper.doSync<KeysBackupLastVersionResult> {
|
||||||
@ -477,7 +461,6 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
assertEquals(2, keysBackupVersionTrust.signatures.size)
|
assertEquals(2, keysBackupVersionTrust.signatures.size)
|
||||||
|
|
||||||
stateObserver.stopAndCheckStates(null)
|
stateObserver.stopAndCheckStates(null)
|
||||||
testData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -491,9 +474,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
* - It must be trusted and must have with 2 signatures now
|
* - It must be trusted and must have with 2 signatures now
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun trustKeyBackupVersionWithRecoveryKeyTest() {
|
fun trustKeyBackupVersionWithRecoveryKeyTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
||||||
|
|
||||||
// - Do an e2e backup to the homeserver with a recovery key
|
// - Do an e2e backup to the homeserver with a recovery key
|
||||||
@ -504,8 +485,8 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
|
|
||||||
// - The new device must see the previous backup as not trusted
|
// - The new device must see the previous backup as not trusted
|
||||||
assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion)
|
assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion)
|
||||||
assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled)
|
assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled())
|
||||||
assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state)
|
assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().getState())
|
||||||
|
|
||||||
// - Trust the backup from the new device with the recovery key
|
// - Trust the backup from the new device with the recovery key
|
||||||
testHelper.doSync<Unit> {
|
testHelper.doSync<Unit> {
|
||||||
@ -521,7 +502,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
|
|
||||||
// - Backup must be enabled on the new device, on the same version
|
// - Backup must be enabled on the new device, on the same version
|
||||||
assertEquals(testData.prepareKeysBackupDataResult.version, testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion?.version)
|
assertEquals(testData.prepareKeysBackupDataResult.version, testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion?.version)
|
||||||
assertTrue(testData.aliceSession2.cryptoService().keysBackupService().isEnabled)
|
assertTrue(testData.aliceSession2.cryptoService().keysBackupService().isEnabled())
|
||||||
|
|
||||||
// - Retrieve the last version from the server
|
// - Retrieve the last version from the server
|
||||||
val keysVersionResult = testHelper.doSync<KeysBackupLastVersionResult> {
|
val keysVersionResult = testHelper.doSync<KeysBackupLastVersionResult> {
|
||||||
@ -540,7 +521,6 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
assertEquals(2, keysBackupVersionTrust.signatures.size)
|
assertEquals(2, keysBackupVersionTrust.signatures.size)
|
||||||
|
|
||||||
stateObserver.stopAndCheckStates(null)
|
stateObserver.stopAndCheckStates(null)
|
||||||
testData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -552,9 +532,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
* - The backup must still be untrusted and disabled
|
* - The backup must still be untrusted and disabled
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun trustKeyBackupVersionWithWrongRecoveryKeyTest() {
|
fun trustKeyBackupVersionWithWrongRecoveryKeyTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
||||||
|
|
||||||
// - Do an e2e backup to the homeserver with a recovery key
|
// - Do an e2e backup to the homeserver with a recovery key
|
||||||
@ -565,8 +543,8 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
|
|
||||||
// - The new device must see the previous backup as not trusted
|
// - The new device must see the previous backup as not trusted
|
||||||
assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion)
|
assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion)
|
||||||
assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled)
|
assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled())
|
||||||
assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state)
|
assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().getState())
|
||||||
|
|
||||||
// - Try to trust the backup from the new device with a wrong recovery key
|
// - Try to trust the backup from the new device with a wrong recovery key
|
||||||
val latch = CountDownLatch(1)
|
val latch = CountDownLatch(1)
|
||||||
@ -579,11 +557,10 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
|
|
||||||
// - The new device must still see the previous backup as not trusted
|
// - The new device must still see the previous backup as not trusted
|
||||||
assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion)
|
assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion)
|
||||||
assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled)
|
assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled())
|
||||||
assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state)
|
assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().getState())
|
||||||
|
|
||||||
stateObserver.stopAndCheckStates(null)
|
stateObserver.stopAndCheckStates(null)
|
||||||
testData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -597,9 +574,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
* - It must be trusted and must have with 2 signatures now
|
* - It must be trusted and must have with 2 signatures now
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun trustKeyBackupVersionWithPasswordTest() {
|
fun trustKeyBackupVersionWithPasswordTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
||||||
|
|
||||||
val password = "Password"
|
val password = "Password"
|
||||||
@ -612,8 +587,8 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
|
|
||||||
// - The new device must see the previous backup as not trusted
|
// - The new device must see the previous backup as not trusted
|
||||||
assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion)
|
assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion)
|
||||||
assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled)
|
assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled())
|
||||||
assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state)
|
assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().getState())
|
||||||
|
|
||||||
// - Trust the backup from the new device with the password
|
// - Trust the backup from the new device with the password
|
||||||
testHelper.doSync<Unit> {
|
testHelper.doSync<Unit> {
|
||||||
@ -629,7 +604,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
|
|
||||||
// - Backup must be enabled on the new device, on the same version
|
// - Backup must be enabled on the new device, on the same version
|
||||||
assertEquals(testData.prepareKeysBackupDataResult.version, testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion?.version)
|
assertEquals(testData.prepareKeysBackupDataResult.version, testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion?.version)
|
||||||
assertTrue(testData.aliceSession2.cryptoService().keysBackupService().isEnabled)
|
assertTrue(testData.aliceSession2.cryptoService().keysBackupService().isEnabled())
|
||||||
|
|
||||||
// - Retrieve the last version from the server
|
// - Retrieve the last version from the server
|
||||||
val keysVersionResult = testHelper.doSync<KeysBackupLastVersionResult> {
|
val keysVersionResult = testHelper.doSync<KeysBackupLastVersionResult> {
|
||||||
@ -648,7 +623,6 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
assertEquals(2, keysBackupVersionTrust.signatures.size)
|
assertEquals(2, keysBackupVersionTrust.signatures.size)
|
||||||
|
|
||||||
stateObserver.stopAndCheckStates(null)
|
stateObserver.stopAndCheckStates(null)
|
||||||
testData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -660,9 +634,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
* - The backup must still be untrusted and disabled
|
* - The backup must still be untrusted and disabled
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun trustKeyBackupVersionWithWrongPasswordTest() {
|
fun trustKeyBackupVersionWithWrongPasswordTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
||||||
|
|
||||||
val password = "Password"
|
val password = "Password"
|
||||||
@ -676,8 +648,8 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
|
|
||||||
// - The new device must see the previous backup as not trusted
|
// - The new device must see the previous backup as not trusted
|
||||||
assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion)
|
assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion)
|
||||||
assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled)
|
assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled())
|
||||||
assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state)
|
assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().getState())
|
||||||
|
|
||||||
// - Try to trust the backup from the new device with a wrong password
|
// - Try to trust the backup from the new device with a wrong password
|
||||||
val latch = CountDownLatch(1)
|
val latch = CountDownLatch(1)
|
||||||
@ -690,11 +662,10 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
|
|
||||||
// - The new device must still see the previous backup as not trusted
|
// - The new device must still see the previous backup as not trusted
|
||||||
assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion)
|
assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion)
|
||||||
assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled)
|
assertFalse(testData.aliceSession2.cryptoService().keysBackupService().isEnabled())
|
||||||
assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state)
|
assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().getState())
|
||||||
|
|
||||||
stateObserver.stopAndCheckStates(null)
|
stateObserver.stopAndCheckStates(null)
|
||||||
testData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -704,9 +675,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
* - It must fail
|
* - It must fail
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun restoreKeysBackupWithAWrongRecoveryKeyTest() {
|
fun restoreKeysBackupWithAWrongRecoveryKeyTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
||||||
|
|
||||||
val testData = keysBackupTestHelper.createKeysBackupScenarioWithPassword(null)
|
val testData = keysBackupTestHelper.createKeysBackupScenarioWithPassword(null)
|
||||||
@ -730,8 +699,6 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
|
|
||||||
// onSuccess may not have been called
|
// onSuccess may not have been called
|
||||||
assertNull(importRoomKeysResult)
|
assertNull(importRoomKeysResult)
|
||||||
|
|
||||||
testData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -741,9 +708,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
* - Restore must be successful
|
* - Restore must be successful
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun testBackupWithPassword() {
|
fun testBackupWithPassword() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
||||||
|
|
||||||
val password = "password"
|
val password = "password"
|
||||||
@ -790,8 +755,6 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
assertEquals(100, (steps[104] as StepProgressListener.Step.ImportingKey).progress)
|
assertEquals(100, (steps[104] as StepProgressListener.Step.ImportingKey).progress)
|
||||||
|
|
||||||
keysBackupTestHelper.checkRestoreSuccess(testData, importRoomKeysResult.totalNumberOfKeys, importRoomKeysResult.successfullyNumberOfImportedKeys)
|
keysBackupTestHelper.checkRestoreSuccess(testData, importRoomKeysResult.totalNumberOfKeys, importRoomKeysResult.successfullyNumberOfImportedKeys)
|
||||||
|
|
||||||
testData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -801,9 +764,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
* - It must fail
|
* - It must fail
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun restoreKeysBackupWithAWrongPasswordTest() {
|
fun restoreKeysBackupWithAWrongPasswordTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
||||||
|
|
||||||
val password = "password"
|
val password = "password"
|
||||||
@ -830,8 +791,6 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
|
|
||||||
// onSuccess may not have been called
|
// onSuccess may not have been called
|
||||||
assertNull(importRoomKeysResult)
|
assertNull(importRoomKeysResult)
|
||||||
|
|
||||||
testData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -841,9 +800,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
* - Restore must be successful
|
* - Restore must be successful
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun testUseRecoveryKeyToRestoreAPasswordBasedKeysBackup() {
|
fun testUseRecoveryKeyToRestoreAPasswordBasedKeysBackup() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
||||||
|
|
||||||
val password = "password"
|
val password = "password"
|
||||||
@ -863,8 +820,6 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
keysBackupTestHelper.checkRestoreSuccess(testData, importRoomKeysResult.totalNumberOfKeys, importRoomKeysResult.successfullyNumberOfImportedKeys)
|
keysBackupTestHelper.checkRestoreSuccess(testData, importRoomKeysResult.totalNumberOfKeys, importRoomKeysResult.successfullyNumberOfImportedKeys)
|
||||||
|
|
||||||
testData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -874,9 +829,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
* - It must fail
|
* - It must fail
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun testUsePasswordToRestoreARecoveryKeyBasedKeysBackup() {
|
fun testUsePasswordToRestoreARecoveryKeyBasedKeysBackup() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
||||||
|
|
||||||
val testData = keysBackupTestHelper.createKeysBackupScenarioWithPassword(null)
|
val testData = keysBackupTestHelper.createKeysBackupScenarioWithPassword(null)
|
||||||
@ -900,8 +853,6 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
|
|
||||||
// onSuccess may not have been called
|
// onSuccess may not have been called
|
||||||
assertNull(importRoomKeysResult)
|
assertNull(importRoomKeysResult)
|
||||||
|
|
||||||
testData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -909,9 +860,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
* - Check the returned KeysVersionResult is trusted
|
* - Check the returned KeysVersionResult is trusted
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun testIsKeysBackupTrusted() {
|
fun testIsKeysBackupTrusted() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
||||||
|
|
||||||
// - Create a backup version
|
// - Create a backup version
|
||||||
@ -945,7 +894,6 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
assertEquals(signature.device!!.deviceId, cryptoTestData.firstSession.sessionParams.deviceId)
|
assertEquals(signature.device!!.deviceId, cryptoTestData.firstSession.sessionParams.deviceId)
|
||||||
|
|
||||||
stateObserver.stopAndCheckStates(null)
|
stateObserver.stopAndCheckStates(null)
|
||||||
cryptoTestData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -957,9 +905,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
* -> That must fail and her backup state must be WrongBackUpVersion
|
* -> That must fail and her backup state must be WrongBackUpVersion
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun testBackupWhenAnotherBackupWasCreated() {
|
fun testBackupWhenAnotherBackupWasCreated() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
||||||
|
|
||||||
// - Create a backup version
|
// - Create a backup version
|
||||||
@ -969,7 +915,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
|
|
||||||
val stateObserver = StateObserver(keysBackup)
|
val stateObserver = StateObserver(keysBackup)
|
||||||
|
|
||||||
assertFalse(keysBackup.isEnabled)
|
assertFalse(keysBackup.isEnabled())
|
||||||
|
|
||||||
// Wait for keys backup to be finished
|
// Wait for keys backup to be finished
|
||||||
val latch0 = CountDownLatch(1)
|
val latch0 = CountDownLatch(1)
|
||||||
@ -993,7 +939,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
// - Make alice back up her keys to her homeserver
|
// - Make alice back up her keys to her homeserver
|
||||||
keysBackupTestHelper.prepareAndCreateKeysBackupData(keysBackup)
|
keysBackupTestHelper.prepareAndCreateKeysBackupData(keysBackup)
|
||||||
|
|
||||||
assertTrue(keysBackup.isEnabled)
|
assertTrue(keysBackup.isEnabled())
|
||||||
|
|
||||||
testHelper.await(latch0)
|
testHelper.await(latch0)
|
||||||
|
|
||||||
@ -1012,11 +958,10 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
testHelper.await(latch2)
|
testHelper.await(latch2)
|
||||||
|
|
||||||
// -> That must fail and her backup state must be WrongBackUpVersion
|
// -> That must fail and her backup state must be WrongBackUpVersion
|
||||||
assertEquals(KeysBackupState.WrongBackUpVersion, keysBackup.state)
|
assertEquals(KeysBackupState.WrongBackUpVersion, keysBackup.getState())
|
||||||
assertFalse(keysBackup.isEnabled)
|
assertFalse(keysBackup.isEnabled())
|
||||||
|
|
||||||
stateObserver.stopAndCheckStates(null)
|
stateObserver.stopAndCheckStates(null)
|
||||||
cryptoTestData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1032,9 +977,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
* -> It must success
|
* -> It must success
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun testBackupAfterVerifyingADevice() {
|
fun testBackupAfterVerifyingADevice() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
||||||
|
|
||||||
// - Create a backup version
|
// - Create a backup version
|
||||||
@ -1069,7 +1012,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
// - Try to backup all in aliceSession2, it must fail
|
// - Try to backup all in aliceSession2, it must fail
|
||||||
val keysBackup2 = aliceSession2.cryptoService().keysBackupService()
|
val keysBackup2 = aliceSession2.cryptoService().keysBackupService()
|
||||||
|
|
||||||
assertFalse("Backup should not be enabled", keysBackup2.isEnabled)
|
assertFalse("Backup should not be enabled", keysBackup2.isEnabled())
|
||||||
|
|
||||||
val stateObserver2 = StateObserver(keysBackup2)
|
val stateObserver2 = StateObserver(keysBackup2)
|
||||||
|
|
||||||
@ -1088,8 +1031,8 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
assertFalse(isSuccessful)
|
assertFalse(isSuccessful)
|
||||||
|
|
||||||
// Backup state must be NotTrusted
|
// Backup state must be NotTrusted
|
||||||
assertEquals("Backup state must be NotTrusted", KeysBackupState.NotTrusted, keysBackup2.state)
|
assertEquals("Backup state must be NotTrusted", KeysBackupState.NotTrusted, keysBackup2.getState())
|
||||||
assertFalse("Backup should not be enabled", keysBackup2.isEnabled)
|
assertFalse("Backup should not be enabled", keysBackup2.isEnabled())
|
||||||
|
|
||||||
// - Validate the old device from the new one
|
// - Validate the old device from the new one
|
||||||
aliceSession2.cryptoService().setDeviceVerification(
|
aliceSession2.cryptoService().setDeviceVerification(
|
||||||
@ -1103,7 +1046,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
keysBackup2.addListener(object : KeysBackupStateListener {
|
keysBackup2.addListener(object : KeysBackupStateListener {
|
||||||
override fun onStateChange(newState: KeysBackupState) {
|
override fun onStateChange(newState: KeysBackupState) {
|
||||||
// Check the backup completes
|
// Check the backup completes
|
||||||
if (keysBackup2.state == KeysBackupState.ReadyToBackUp) {
|
if (keysBackup2.getState() == KeysBackupState.ReadyToBackUp) {
|
||||||
// Remove itself from the list of listeners
|
// Remove itself from the list of listeners
|
||||||
keysBackup2.removeListener(this)
|
keysBackup2.removeListener(this)
|
||||||
|
|
||||||
@ -1121,12 +1064,10 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// -> It must success
|
// -> It must success
|
||||||
assertTrue(aliceSession2.cryptoService().keysBackupService().isEnabled)
|
assertTrue(aliceSession2.cryptoService().keysBackupService().isEnabled())
|
||||||
|
|
||||||
stateObserver.stopAndCheckStates(null)
|
stateObserver.stopAndCheckStates(null)
|
||||||
stateObserver2.stopAndCheckStates(null)
|
stateObserver2.stopAndCheckStates(null)
|
||||||
testHelper.signOutAndClose(aliceSession2)
|
|
||||||
cryptoTestData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1134,9 +1075,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
* - Delete the backup
|
* - Delete the backup
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun deleteKeysBackupTest() {
|
fun deleteKeysBackupTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
val keysBackupTestHelper = KeysBackupTestHelper(testHelper, cryptoTestHelper)
|
||||||
|
|
||||||
// - Create a backup version
|
// - Create a backup version
|
||||||
@ -1146,19 +1085,18 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
|
|
||||||
val stateObserver = StateObserver(keysBackup)
|
val stateObserver = StateObserver(keysBackup)
|
||||||
|
|
||||||
assertFalse(keysBackup.isEnabled)
|
assertFalse(keysBackup.isEnabled())
|
||||||
|
|
||||||
val keyBackupCreationInfo = keysBackupTestHelper.prepareAndCreateKeysBackupData(keysBackup)
|
val keyBackupCreationInfo = keysBackupTestHelper.prepareAndCreateKeysBackupData(keysBackup)
|
||||||
|
|
||||||
assertTrue(keysBackup.isEnabled)
|
assertTrue(keysBackup.isEnabled())
|
||||||
|
|
||||||
// Delete the backup
|
// Delete the backup
|
||||||
testHelper.doSync<Unit> { keysBackup.deleteBackup(keyBackupCreationInfo.version, it) }
|
testHelper.doSync<Unit> { keysBackup.deleteBackup(keyBackupCreationInfo.version, it) }
|
||||||
|
|
||||||
// Backup is now disabled
|
// Backup is now disabled
|
||||||
assertFalse(keysBackup.isEnabled)
|
assertFalse(keysBackup.isEnabled())
|
||||||
|
|
||||||
stateObserver.stopAndCheckStates(null)
|
stateObserver.stopAndCheckStates(null)
|
||||||
cryptoTestData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ internal class KeysBackupTestHelper(
|
|||||||
|
|
||||||
Assert.assertNotNull(megolmBackupCreationInfo)
|
Assert.assertNotNull(megolmBackupCreationInfo)
|
||||||
|
|
||||||
Assert.assertFalse("Key backup should not be enabled before creation", keysBackup.isEnabled)
|
Assert.assertFalse("Key backup should not be enabled before creation", keysBackup.isEnabled())
|
||||||
|
|
||||||
// Create the version
|
// Create the version
|
||||||
val keysVersion = testHelper.doSync<KeysVersion> {
|
val keysVersion = testHelper.doSync<KeysVersion> {
|
||||||
@ -116,7 +116,7 @@ internal class KeysBackupTestHelper(
|
|||||||
Assert.assertNotNull("Key backup version should not be null", keysVersion.version)
|
Assert.assertNotNull("Key backup version should not be null", keysVersion.version)
|
||||||
|
|
||||||
// Backup must be enable now
|
// Backup must be enable now
|
||||||
Assert.assertTrue(keysBackup.isEnabled)
|
Assert.assertTrue(keysBackup.isEnabled())
|
||||||
|
|
||||||
stateObserver.stopAndCheckStates(null)
|
stateObserver.stopAndCheckStates(null)
|
||||||
return PrepareKeysBackupDataResult(megolmBackupCreationInfo, keysVersion.version)
|
return PrepareKeysBackupDataResult(megolmBackupCreationInfo, keysVersion.version)
|
||||||
@ -128,7 +128,7 @@ internal class KeysBackupTestHelper(
|
|||||||
*/
|
*/
|
||||||
fun waitForKeysBackupToBeInState(session: Session, state: KeysBackupState) {
|
fun waitForKeysBackupToBeInState(session: Session, state: KeysBackupState) {
|
||||||
// If already in the wanted state, return
|
// If already in the wanted state, return
|
||||||
if (session.cryptoService().keysBackupService().state == state) {
|
if (session.cryptoService().keysBackupService().getState() == state) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.matrix.android.sdk.internal.crypto.replayattack
|
||||||
|
|
||||||
|
import androidx.test.filters.LargeTest
|
||||||
|
import org.amshove.kluent.internal.assertFailsWith
|
||||||
|
import org.junit.Assert
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Assert.fail
|
||||||
|
import org.junit.FixMethodOrder
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.junit.runners.JUnit4
|
||||||
|
import org.junit.runners.MethodSorters
|
||||||
|
import org.matrix.android.sdk.InstrumentedTest
|
||||||
|
import org.matrix.android.sdk.api.session.crypto.MXCryptoError
|
||||||
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
|
||||||
|
|
||||||
|
@RunWith(JUnit4::class)
|
||||||
|
@FixMethodOrder(MethodSorters.JVM)
|
||||||
|
@LargeTest
|
||||||
|
class ReplayAttackTest : InstrumentedTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun replayAttackAlreadyDecryptedEventTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
|
||||||
|
|
||||||
|
val e2eRoomID = cryptoTestData.roomId
|
||||||
|
|
||||||
|
// Alice
|
||||||
|
val aliceSession = cryptoTestData.firstSession
|
||||||
|
val aliceRoomPOV = aliceSession.roomService().getRoom(e2eRoomID)!!
|
||||||
|
|
||||||
|
// Bob
|
||||||
|
val bobSession = cryptoTestData.secondSession
|
||||||
|
val bobRoomPOV = bobSession!!.roomService().getRoom(e2eRoomID)!!
|
||||||
|
assertEquals(bobRoomPOV.roomSummary()?.joinedMembersCount, 2)
|
||||||
|
|
||||||
|
// Alice will send a message
|
||||||
|
val sentEvents = testHelper.sendTextMessage(aliceRoomPOV, "Hello I will be decrypted twice", 1)
|
||||||
|
assertEquals(1, sentEvents.size)
|
||||||
|
|
||||||
|
val fakeEventId = sentEvents[0].eventId + "_fake"
|
||||||
|
val fakeEventWithTheSameIndex =
|
||||||
|
sentEvents[0].copy(eventId = fakeEventId, root = sentEvents[0].root.copy(eventId = fakeEventId))
|
||||||
|
|
||||||
|
testHelper.runBlockingTest {
|
||||||
|
// Lets assume we are from the main timelineId
|
||||||
|
val timelineId = "timelineId"
|
||||||
|
// Lets decrypt the original event
|
||||||
|
aliceSession.cryptoService().decryptEvent(sentEvents[0].root, timelineId)
|
||||||
|
// Lets decrypt the fake event that will have the same message index
|
||||||
|
val exception = assertFailsWith<MXCryptoError.Base> {
|
||||||
|
// An exception should be thrown while the same index would have been used for the previous decryption
|
||||||
|
aliceSession.cryptoService().decryptEvent(fakeEventWithTheSameIndex.root, timelineId)
|
||||||
|
}
|
||||||
|
assertEquals(MXCryptoError.ErrorType.DUPLICATED_MESSAGE_INDEX, exception.errorType)
|
||||||
|
}
|
||||||
|
cryptoTestData.cleanUp(testHelper)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun replayAttackSameEventTest() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
|
||||||
|
|
||||||
|
val e2eRoomID = cryptoTestData.roomId
|
||||||
|
|
||||||
|
// Alice
|
||||||
|
val aliceSession = cryptoTestData.firstSession
|
||||||
|
val aliceRoomPOV = aliceSession.roomService().getRoom(e2eRoomID)!!
|
||||||
|
|
||||||
|
// Bob
|
||||||
|
val bobSession = cryptoTestData.secondSession
|
||||||
|
val bobRoomPOV = bobSession!!.roomService().getRoom(e2eRoomID)!!
|
||||||
|
assertEquals(bobRoomPOV.roomSummary()?.joinedMembersCount, 2)
|
||||||
|
|
||||||
|
// Alice will send a message
|
||||||
|
val sentEvents = testHelper.sendTextMessage(aliceRoomPOV, "Hello I will be decrypted twice", 1)
|
||||||
|
Assert.assertTrue("Message should be sent", sentEvents.size == 1)
|
||||||
|
assertEquals(sentEvents.size, 1)
|
||||||
|
|
||||||
|
testHelper.runBlockingTest {
|
||||||
|
// Lets assume we are from the main timelineId
|
||||||
|
val timelineId = "timelineId"
|
||||||
|
// Lets decrypt the original event
|
||||||
|
aliceSession.cryptoService().decryptEvent(sentEvents[0].root, timelineId)
|
||||||
|
try {
|
||||||
|
// Lets try to decrypt the same event
|
||||||
|
aliceSession.cryptoService().decryptEvent(sentEvents[0].root, timelineId)
|
||||||
|
} catch (ex: Throwable) {
|
||||||
|
fail("Shouldn't throw a decryption error for same event")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -31,15 +31,16 @@ import org.matrix.android.sdk.api.crypto.SSSS_ALGORITHM_AES_HMAC_SHA2
|
|||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
|
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
|
||||||
import org.matrix.android.sdk.api.session.securestorage.EncryptedSecretContent
|
import org.matrix.android.sdk.api.session.securestorage.EncryptedSecretContent
|
||||||
|
import org.matrix.android.sdk.api.session.securestorage.KeyRef
|
||||||
import org.matrix.android.sdk.api.session.securestorage.KeySigner
|
import org.matrix.android.sdk.api.session.securestorage.KeySigner
|
||||||
import org.matrix.android.sdk.api.session.securestorage.RawBytesKeySpec
|
import org.matrix.android.sdk.api.session.securestorage.RawBytesKeySpec
|
||||||
import org.matrix.android.sdk.api.session.securestorage.SecretStorageKeyContent
|
import org.matrix.android.sdk.api.session.securestorage.SecretStorageKeyContent
|
||||||
import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageError
|
import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageError
|
||||||
import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageService
|
|
||||||
import org.matrix.android.sdk.api.session.securestorage.SsssKeyCreationInfo
|
import org.matrix.android.sdk.api.session.securestorage.SsssKeyCreationInfo
|
||||||
import org.matrix.android.sdk.api.util.Optional
|
import org.matrix.android.sdk.api.util.Optional
|
||||||
import org.matrix.android.sdk.api.util.toBase64NoPadding
|
import org.matrix.android.sdk.api.util.toBase64NoPadding
|
||||||
import org.matrix.android.sdk.common.CommonTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper
|
||||||
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest
|
||||||
import org.matrix.android.sdk.common.SessionTestParams
|
import org.matrix.android.sdk.common.SessionTestParams
|
||||||
import org.matrix.android.sdk.common.TestConstants
|
import org.matrix.android.sdk.common.TestConstants
|
||||||
import org.matrix.android.sdk.internal.crypto.secrets.DefaultSharedSecretStorageService
|
import org.matrix.android.sdk.internal.crypto.secrets.DefaultSharedSecretStorageService
|
||||||
@ -55,8 +56,7 @@ class QuadSTests : InstrumentedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_Generate4SKey() {
|
fun test_Generate4SKey() = runSessionTest(context()) { testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
|
|
||||||
val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
|
val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
|
||||||
|
|
||||||
@ -108,12 +108,11 @@ class QuadSTests : InstrumentedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_StoreSecret() {
|
fun test_StoreSecret() = runSessionTest(context()) { testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
|
|
||||||
val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
|
val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
|
||||||
val keyId = "My.Key"
|
val keyId = "My.Key"
|
||||||
val info = generatedSecret(aliceSession, keyId, true)
|
val info = generatedSecret(testHelper, aliceSession, keyId, true)
|
||||||
|
|
||||||
val keySpec = RawBytesKeySpec.fromRecoveryKey(info.recoveryKey)
|
val keySpec = RawBytesKeySpec.fromRecoveryKey(info.recoveryKey)
|
||||||
|
|
||||||
@ -123,11 +122,11 @@ class QuadSTests : InstrumentedTest {
|
|||||||
aliceSession.sharedSecretStorageService().storeSecret(
|
aliceSession.sharedSecretStorageService().storeSecret(
|
||||||
"secret.of.life",
|
"secret.of.life",
|
||||||
clearSecret,
|
clearSecret,
|
||||||
listOf(SharedSecretStorageService.KeyRef(null, keySpec)) // default key
|
listOf(KeyRef(null, keySpec)) // default key
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val secretAccountData = assertAccountData(aliceSession, "secret.of.life")
|
val secretAccountData = assertAccountData(testHelper, aliceSession, "secret.of.life")
|
||||||
|
|
||||||
val encryptedContent = secretAccountData.content["encrypted"] as? Map<*, *>
|
val encryptedContent = secretAccountData.content["encrypted"] as? Map<*, *>
|
||||||
assertNotNull("Element should be encrypted", encryptedContent)
|
assertNotNull("Element should be encrypted", encryptedContent)
|
||||||
@ -149,12 +148,10 @@ class QuadSTests : InstrumentedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assertEquals("Secret mismatch", clearSecret, decryptedSecret)
|
assertEquals("Secret mismatch", clearSecret, decryptedSecret)
|
||||||
testHelper.signOutAndClose(aliceSession)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_SetDefaultLocalEcho() {
|
fun test_SetDefaultLocalEcho() = runSessionTest(context()) { testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
|
|
||||||
val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
|
val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
|
||||||
|
|
||||||
@ -170,19 +167,16 @@ class QuadSTests : InstrumentedTest {
|
|||||||
testHelper.runBlockingTest {
|
testHelper.runBlockingTest {
|
||||||
quadS.setDefaultKey(TEST_KEY_ID)
|
quadS.setDefaultKey(TEST_KEY_ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
testHelper.signOutAndClose(aliceSession)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_StoreSecretWithMultipleKey() {
|
fun test_StoreSecretWithMultipleKey() = runSessionTest(context()) { testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
|
|
||||||
val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
|
val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
|
||||||
val keyId1 = "Key.1"
|
val keyId1 = "Key.1"
|
||||||
val key1Info = generatedSecret(aliceSession, keyId1, true)
|
val key1Info = generatedSecret(testHelper, aliceSession, keyId1, true)
|
||||||
val keyId2 = "Key2"
|
val keyId2 = "Key2"
|
||||||
val key2Info = generatedSecret(aliceSession, keyId2, true)
|
val key2Info = generatedSecret(testHelper, aliceSession, keyId2, true)
|
||||||
|
|
||||||
val mySecretText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
|
val mySecretText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
|
||||||
|
|
||||||
@ -191,8 +185,8 @@ class QuadSTests : InstrumentedTest {
|
|||||||
"my.secret",
|
"my.secret",
|
||||||
mySecretText.toByteArray().toBase64NoPadding(),
|
mySecretText.toByteArray().toBase64NoPadding(),
|
||||||
listOf(
|
listOf(
|
||||||
SharedSecretStorageService.KeyRef(keyId1, RawBytesKeySpec.fromRecoveryKey(key1Info.recoveryKey)),
|
KeyRef(keyId1, RawBytesKeySpec.fromRecoveryKey(key1Info.recoveryKey)),
|
||||||
SharedSecretStorageService.KeyRef(keyId2, RawBytesKeySpec.fromRecoveryKey(key2Info.recoveryKey))
|
KeyRef(keyId2, RawBytesKeySpec.fromRecoveryKey(key2Info.recoveryKey))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -221,19 +215,16 @@ class QuadSTests : InstrumentedTest {
|
|||||||
RawBytesKeySpec.fromRecoveryKey(key2Info.recoveryKey)!!
|
RawBytesKeySpec.fromRecoveryKey(key2Info.recoveryKey)!!
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
testHelper.signOutAndClose(aliceSession)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Ignore("Test is working locally, not in GitHub actions")
|
@Ignore("Test is working locally, not in GitHub actions")
|
||||||
fun test_GetSecretWithBadPassphrase() {
|
fun test_GetSecretWithBadPassphrase() = runSessionTest(context()) { testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
|
|
||||||
val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
|
val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
|
||||||
val keyId1 = "Key.1"
|
val keyId1 = "Key.1"
|
||||||
val passphrase = "The good pass phrase"
|
val passphrase = "The good pass phrase"
|
||||||
val key1Info = generatedSecretFromPassphrase(aliceSession, passphrase, keyId1, true)
|
val key1Info = generatedSecretFromPassphrase(testHelper, aliceSession, passphrase, keyId1, true)
|
||||||
|
|
||||||
val mySecretText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
|
val mySecretText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
|
||||||
|
|
||||||
@ -241,7 +232,7 @@ class QuadSTests : InstrumentedTest {
|
|||||||
aliceSession.sharedSecretStorageService().storeSecret(
|
aliceSession.sharedSecretStorageService().storeSecret(
|
||||||
"my.secret",
|
"my.secret",
|
||||||
mySecretText.toByteArray().toBase64NoPadding(),
|
mySecretText.toByteArray().toBase64NoPadding(),
|
||||||
listOf(SharedSecretStorageService.KeyRef(keyId1, RawBytesKeySpec.fromRecoveryKey(key1Info.recoveryKey)))
|
listOf(KeyRef(keyId1, RawBytesKeySpec.fromRecoveryKey(key1Info.recoveryKey)))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,13 +266,9 @@ class QuadSTests : InstrumentedTest {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
testHelper.signOutAndClose(aliceSession)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun assertAccountData(session: Session, type: String): UserAccountDataEvent {
|
private fun assertAccountData(testHelper: CommonTestHelper, session: Session, type: String): UserAccountDataEvent {
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
|
|
||||||
var accountData: UserAccountDataEvent? = null
|
var accountData: UserAccountDataEvent? = null
|
||||||
testHelper.waitWithLatch {
|
testHelper.waitWithLatch {
|
||||||
val liveAccountData = session.accountDataService().getLiveUserAccountDataEvent(type)
|
val liveAccountData = session.accountDataService().getLiveUserAccountDataEvent(type)
|
||||||
@ -297,29 +284,27 @@ class QuadSTests : InstrumentedTest {
|
|||||||
return accountData!!
|
return accountData!!
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generatedSecret(session: Session, keyId: String, asDefault: Boolean = true): SsssKeyCreationInfo {
|
private fun generatedSecret(testHelper: CommonTestHelper, session: Session, keyId: String, asDefault: Boolean = true): SsssKeyCreationInfo {
|
||||||
val quadS = session.sharedSecretStorageService()
|
val quadS = session.sharedSecretStorageService()
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
|
|
||||||
val creationInfo = testHelper.runBlockingTest {
|
val creationInfo = testHelper.runBlockingTest {
|
||||||
quadS.generateKey(keyId, null, keyId, emptyKeySigner)
|
quadS.generateKey(keyId, null, keyId, emptyKeySigner)
|
||||||
}
|
}
|
||||||
|
|
||||||
assertAccountData(session, "${DefaultSharedSecretStorageService.KEY_ID_BASE}.$keyId")
|
assertAccountData(testHelper, session, "${DefaultSharedSecretStorageService.KEY_ID_BASE}.$keyId")
|
||||||
|
|
||||||
if (asDefault) {
|
if (asDefault) {
|
||||||
testHelper.runBlockingTest {
|
testHelper.runBlockingTest {
|
||||||
quadS.setDefaultKey(keyId)
|
quadS.setDefaultKey(keyId)
|
||||||
}
|
}
|
||||||
assertAccountData(session, DefaultSharedSecretStorageService.DEFAULT_KEY_ID)
|
assertAccountData(testHelper, session, DefaultSharedSecretStorageService.DEFAULT_KEY_ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
return creationInfo
|
return creationInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generatedSecretFromPassphrase(session: Session, passphrase: String, keyId: String, asDefault: Boolean = true): SsssKeyCreationInfo {
|
private fun generatedSecretFromPassphrase(testHelper: CommonTestHelper, session: Session, passphrase: String, keyId: String, asDefault: Boolean = true): SsssKeyCreationInfo {
|
||||||
val quadS = session.sharedSecretStorageService()
|
val quadS = session.sharedSecretStorageService()
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
|
|
||||||
val creationInfo = testHelper.runBlockingTest {
|
val creationInfo = testHelper.runBlockingTest {
|
||||||
quadS.generateKeyWithPassphrase(
|
quadS.generateKeyWithPassphrase(
|
||||||
@ -331,12 +316,12 @@ class QuadSTests : InstrumentedTest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
assertAccountData(session, "${DefaultSharedSecretStorageService.KEY_ID_BASE}.$keyId")
|
assertAccountData(testHelper, session, "${DefaultSharedSecretStorageService.KEY_ID_BASE}.$keyId")
|
||||||
if (asDefault) {
|
if (asDefault) {
|
||||||
testHelper.runBlockingTest {
|
testHelper.runBlockingTest {
|
||||||
quadS.setDefaultKey(keyId)
|
quadS.setDefaultKey(keyId)
|
||||||
}
|
}
|
||||||
assertAccountData(session, DefaultSharedSecretStorageService.DEFAULT_KEY_ID)
|
assertAccountData(testHelper, session, DefaultSharedSecretStorageService.DEFAULT_KEY_ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
return creationInfo
|
return creationInfo
|
||||||
|
@ -44,8 +44,7 @@ import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransa
|
|||||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState
|
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState
|
||||||
import org.matrix.android.sdk.api.session.events.model.Event
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
import org.matrix.android.sdk.common.CommonTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
|
||||||
import org.matrix.android.sdk.common.CryptoTestHelper
|
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationCancel
|
import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationCancel
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationStart
|
import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationStart
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.toValue
|
import org.matrix.android.sdk.internal.crypto.model.rest.toValue
|
||||||
@ -56,9 +55,7 @@ import java.util.concurrent.CountDownLatch
|
|||||||
class SASTest : InstrumentedTest {
|
class SASTest : InstrumentedTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_aliceStartThenAliceCancel() {
|
fun test_aliceStartThenAliceCancel() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
||||||
|
|
||||||
val aliceSession = cryptoTestData.firstSession
|
val aliceSession = cryptoTestData.firstSession
|
||||||
@ -135,15 +132,11 @@ class SASTest : InstrumentedTest {
|
|||||||
|
|
||||||
assertNull(bobVerificationService.getExistingTransaction(aliceSession.myUserId, txID))
|
assertNull(bobVerificationService.getExistingTransaction(aliceSession.myUserId, txID))
|
||||||
assertNull(aliceVerificationService.getExistingTransaction(bobSession.myUserId, txID))
|
assertNull(aliceVerificationService.getExistingTransaction(bobSession.myUserId, txID))
|
||||||
|
|
||||||
cryptoTestData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Ignore("This test will be ignored until it is fixed")
|
@Ignore("This test will be ignored until it is fixed")
|
||||||
fun test_key_agreement_protocols_must_include_curve25519() {
|
fun test_key_agreement_protocols_must_include_curve25519() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
fail("Not passing for the moment")
|
fail("Not passing for the moment")
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
||||||
|
|
||||||
@ -195,15 +188,11 @@ class SASTest : InstrumentedTest {
|
|||||||
testHelper.await(cancelLatch)
|
testHelper.await(cancelLatch)
|
||||||
|
|
||||||
assertEquals("Request should be cancelled with m.unknown_method", CancelCode.UnknownMethod, cancelReason)
|
assertEquals("Request should be cancelled with m.unknown_method", CancelCode.UnknownMethod, cancelReason)
|
||||||
|
|
||||||
cryptoTestData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Ignore("This test will be ignored until it is fixed")
|
@Ignore("This test will be ignored until it is fixed")
|
||||||
fun test_key_agreement_macs_Must_include_hmac_sha256() {
|
fun test_key_agreement_macs_Must_include_hmac_sha256() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
fail("Not passing for the moment")
|
fail("Not passing for the moment")
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
||||||
|
|
||||||
@ -236,15 +225,11 @@ class SASTest : InstrumentedTest {
|
|||||||
|
|
||||||
val cancelReq = canceledToDeviceEvent!!.content.toModel<KeyVerificationCancel>()!!
|
val cancelReq = canceledToDeviceEvent!!.content.toModel<KeyVerificationCancel>()!!
|
||||||
assertEquals("Request should be cancelled with m.unknown_method", CancelCode.UnknownMethod.value, cancelReq.code)
|
assertEquals("Request should be cancelled with m.unknown_method", CancelCode.UnknownMethod.value, cancelReq.code)
|
||||||
|
|
||||||
cryptoTestData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Ignore("This test will be ignored until it is fixed")
|
@Ignore("This test will be ignored until it is fixed")
|
||||||
fun test_key_agreement_short_code_include_decimal() {
|
fun test_key_agreement_short_code_include_decimal() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
fail("Not passing for the moment")
|
fail("Not passing for the moment")
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
||||||
|
|
||||||
@ -277,8 +262,6 @@ class SASTest : InstrumentedTest {
|
|||||||
|
|
||||||
val cancelReq = canceledToDeviceEvent!!.content.toModel<KeyVerificationCancel>()!!
|
val cancelReq = canceledToDeviceEvent!!.content.toModel<KeyVerificationCancel>()!!
|
||||||
assertEquals("Request should be cancelled with m.unknown_method", CancelCode.UnknownMethod.value, cancelReq.code)
|
assertEquals("Request should be cancelled with m.unknown_method", CancelCode.UnknownMethod.value, cancelReq.code)
|
||||||
|
|
||||||
cryptoTestData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fakeBobStart(bobSession: Session,
|
private fun fakeBobStart(bobSession: Session,
|
||||||
@ -314,9 +297,7 @@ class SASTest : InstrumentedTest {
|
|||||||
// any two devices may only have at most one key verification in flight at a time.
|
// any two devices may only have at most one key verification in flight at a time.
|
||||||
// If a device has two verifications in progress with the same device, then it should cancel both verifications.
|
// If a device has two verifications in progress with the same device, then it should cancel both verifications.
|
||||||
@Test
|
@Test
|
||||||
fun test_aliceStartTwoRequests() {
|
fun test_aliceStartTwoRequests() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
||||||
|
|
||||||
val aliceSession = cryptoTestData.firstSession
|
val aliceSession = cryptoTestData.firstSession
|
||||||
@ -357,9 +338,7 @@ class SASTest : InstrumentedTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
@Ignore("This test will be ignored until it is fixed")
|
@Ignore("This test will be ignored until it is fixed")
|
||||||
fun test_aliceAndBobAgreement() {
|
fun test_aliceAndBobAgreement() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
||||||
|
|
||||||
val aliceSession = cryptoTestData.firstSession
|
val aliceSession = cryptoTestData.firstSession
|
||||||
@ -413,14 +392,10 @@ class SASTest : InstrumentedTest {
|
|||||||
accepted!!.shortAuthenticationStrings.forEach {
|
accepted!!.shortAuthenticationStrings.forEach {
|
||||||
assertTrue("all agreed Short Code should be known by alice", startReq!!.shortAuthenticationStrings.contains(it))
|
assertTrue("all agreed Short Code should be known by alice", startReq!!.shortAuthenticationStrings.contains(it))
|
||||||
}
|
}
|
||||||
|
|
||||||
cryptoTestData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_aliceAndBobSASCode() {
|
fun test_aliceAndBobSASCode() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
||||||
|
|
||||||
val aliceSession = cryptoTestData.firstSession
|
val aliceSession = cryptoTestData.firstSession
|
||||||
@ -473,14 +448,10 @@ class SASTest : InstrumentedTest {
|
|||||||
"Should have same SAS", aliceTx.getShortCodeRepresentation(SasMode.DECIMAL),
|
"Should have same SAS", aliceTx.getShortCodeRepresentation(SasMode.DECIMAL),
|
||||||
bobTx.getShortCodeRepresentation(SasMode.DECIMAL)
|
bobTx.getShortCodeRepresentation(SasMode.DECIMAL)
|
||||||
)
|
)
|
||||||
|
|
||||||
cryptoTestData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_happyPath() {
|
fun test_happyPath() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
||||||
|
|
||||||
val aliceSession = cryptoTestData.firstSession
|
val aliceSession = cryptoTestData.firstSession
|
||||||
@ -553,13 +524,10 @@ class SASTest : InstrumentedTest {
|
|||||||
|
|
||||||
assertTrue("alice device should be verified from bob point of view", aliceDeviceInfoFromBobPOV!!.isVerified)
|
assertTrue("alice device should be verified from bob point of view", aliceDeviceInfoFromBobPOV!!.isVerified)
|
||||||
assertTrue("bob device should be verified from alice point of view", bobDeviceInfoFromAlicePOV!!.isVerified)
|
assertTrue("bob device should be verified from alice point of view", bobDeviceInfoFromAlicePOV!!.isVerified)
|
||||||
cryptoTestData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_ConcurrentStart() {
|
fun test_ConcurrentStart() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
||||||
|
|
||||||
val aliceSession = cryptoTestData.firstSession
|
val aliceSession = cryptoTestData.firstSession
|
||||||
@ -646,7 +614,5 @@ class SASTest : InstrumentedTest {
|
|||||||
bobPovTx?.state == VerificationTxState.ShortCodeReady
|
bobPovTx?.state == VerificationTxState.ShortCodeReady
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cryptoTestData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,8 +31,8 @@ import org.matrix.android.sdk.api.session.crypto.verification.CancelCode
|
|||||||
import org.matrix.android.sdk.api.session.crypto.verification.PendingVerificationRequest
|
import org.matrix.android.sdk.api.session.crypto.verification.PendingVerificationRequest
|
||||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod
|
import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod
|
||||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
|
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
|
||||||
import org.matrix.android.sdk.common.CommonTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
|
||||||
import org.matrix.android.sdk.common.CryptoTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest
|
||||||
import org.matrix.android.sdk.common.SessionTestParams
|
import org.matrix.android.sdk.common.SessionTestParams
|
||||||
import org.matrix.android.sdk.common.TestConstants
|
import org.matrix.android.sdk.common.TestConstants
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.concurrent.CountDownLatch
|
||||||
@ -154,9 +154,7 @@ class VerificationTest : InstrumentedTest {
|
|||||||
private fun doTest(aliceSupportedMethods: List<VerificationMethod>,
|
private fun doTest(aliceSupportedMethods: List<VerificationMethod>,
|
||||||
bobSupportedMethods: List<VerificationMethod>,
|
bobSupportedMethods: List<VerificationMethod>,
|
||||||
expectedResultForAlice: ExpectedResult,
|
expectedResultForAlice: ExpectedResult,
|
||||||
expectedResultForBob: ExpectedResult) {
|
expectedResultForBob: ExpectedResult) = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
||||||
|
|
||||||
val aliceSession = cryptoTestData.firstSession
|
val aliceSession = cryptoTestData.firstSession
|
||||||
@ -251,14 +249,11 @@ class VerificationTest : InstrumentedTest {
|
|||||||
pr.otherCanShowQrCode() shouldBe expectedResultForBob.otherCanShowQrCode
|
pr.otherCanShowQrCode() shouldBe expectedResultForBob.otherCanShowQrCode
|
||||||
pr.otherCanScanQrCode() shouldBe expectedResultForBob.otherCanScanQrCode
|
pr.otherCanScanQrCode() shouldBe expectedResultForBob.otherCanScanQrCode
|
||||||
}
|
}
|
||||||
|
|
||||||
cryptoTestData.cleanUp(testHelper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_selfVerificationAcceptedCancelsItForOtherSessions() {
|
fun test_selfVerificationAcceptedCancelsItForOtherSessions() = runSessionTest(context()) { testHelper ->
|
||||||
val defaultSessionParams = SessionTestParams(true)
|
val defaultSessionParams = SessionTestParams(true)
|
||||||
val testHelper = CommonTestHelper(context())
|
|
||||||
|
|
||||||
val aliceSessionToVerify = testHelper.createAccount(TestConstants.USER_ALICE, defaultSessionParams)
|
val aliceSessionToVerify = testHelper.createAccount(TestConstants.USER_ALICE, defaultSessionParams)
|
||||||
val aliceSessionThatVerifies = testHelper.logIntoAccount(aliceSessionToVerify.myUserId, TestConstants.PASSWORD, defaultSessionParams)
|
val aliceSessionThatVerifies = testHelper.logIntoAccount(aliceSessionToVerify.myUserId, TestConstants.PASSWORD, defaultSessionParams)
|
||||||
|
@ -34,8 +34,7 @@ import org.matrix.android.sdk.api.session.events.model.isThread
|
|||||||
import org.matrix.android.sdk.api.session.getRoom
|
import org.matrix.android.sdk.api.session.getRoom
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.Timeline
|
import org.matrix.android.sdk.api.session.room.timeline.Timeline
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
|
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
|
||||||
import org.matrix.android.sdk.common.CommonTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
|
||||||
import org.matrix.android.sdk.common.CryptoTestHelper
|
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.concurrent.CountDownLatch
|
||||||
|
|
||||||
@RunWith(JUnit4::class)
|
@RunWith(JUnit4::class)
|
||||||
@ -44,9 +43,7 @@ import java.util.concurrent.CountDownLatch
|
|||||||
class ThreadMessagingTest : InstrumentedTest {
|
class ThreadMessagingTest : InstrumentedTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun reply_in_thread_should_create_a_thread() {
|
fun reply_in_thread_should_create_a_thread() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
|
||||||
val commonTestHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
|
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceInARoom(false)
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceInARoom(false)
|
||||||
|
|
||||||
val aliceSession = cryptoTestData.firstSession
|
val aliceSession = cryptoTestData.firstSession
|
||||||
@ -104,9 +101,7 @@ class ThreadMessagingTest : InstrumentedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun reply_in_thread_should_create_a_thread_from_other_user() {
|
fun reply_in_thread_should_create_a_thread_from_other_user() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
|
||||||
val commonTestHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
|
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(false)
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(false)
|
||||||
|
|
||||||
val aliceSession = cryptoTestData.firstSession
|
val aliceSession = cryptoTestData.firstSession
|
||||||
@ -179,9 +174,7 @@ class ThreadMessagingTest : InstrumentedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun reply_in_thread_to_timeline_message_multiple_times() {
|
fun reply_in_thread_to_timeline_message_multiple_times() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
|
||||||
val commonTestHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
|
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceInARoom(false)
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceInARoom(false)
|
||||||
|
|
||||||
val aliceSession = cryptoTestData.firstSession
|
val aliceSession = cryptoTestData.firstSession
|
||||||
@ -244,9 +237,7 @@ class ThreadMessagingTest : InstrumentedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun thread_summary_advanced_validation_after_multiple_messages_in_multiple_threads() {
|
fun thread_summary_advanced_validation_after_multiple_messages_in_multiple_threads() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
|
||||||
val commonTestHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
|
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(false)
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(false)
|
||||||
|
|
||||||
val aliceSession = cryptoTestData.firstSession
|
val aliceSession = cryptoTestData.firstSession
|
||||||
|
@ -38,8 +38,7 @@ import org.matrix.android.sdk.api.session.room.model.message.PollType
|
|||||||
import org.matrix.android.sdk.api.session.room.timeline.Timeline
|
import org.matrix.android.sdk.api.session.room.timeline.Timeline
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
|
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
|
||||||
import org.matrix.android.sdk.common.CommonTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
|
||||||
import org.matrix.android.sdk.common.CryptoTestHelper
|
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.concurrent.CountDownLatch
|
||||||
|
|
||||||
@RunWith(JUnit4::class)
|
@RunWith(JUnit4::class)
|
||||||
@ -47,9 +46,7 @@ import java.util.concurrent.CountDownLatch
|
|||||||
class PollAggregationTest : InstrumentedTest {
|
class PollAggregationTest : InstrumentedTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testAllPollUseCases() {
|
fun testAllPollUseCases() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
|
||||||
val commonTestHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
|
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(false)
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(false)
|
||||||
|
|
||||||
val aliceSession = cryptoTestData.firstSession
|
val aliceSession = cryptoTestData.firstSession
|
||||||
@ -138,7 +135,6 @@ class PollAggregationTest : InstrumentedTest {
|
|||||||
|
|
||||||
aliceSession.stopSync()
|
aliceSession.stopSync()
|
||||||
aliceTimeline.dispose()
|
aliceTimeline.dispose()
|
||||||
cryptoTestData.cleanUp(commonTestHelper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun testInitialPollConditions(pollContent: MessagePollContent, pollSummary: PollResponseAggregatedSummary?) {
|
private fun testInitialPollConditions(pollContent: MessagePollContent, pollSummary: PollResponseAggregatedSummary?) {
|
||||||
|
@ -34,8 +34,7 @@ import org.matrix.android.sdk.api.session.getRoom
|
|||||||
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
|
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.Timeline
|
import org.matrix.android.sdk.api.session.room.timeline.Timeline
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
|
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
|
||||||
import org.matrix.android.sdk.common.CommonTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
|
||||||
import org.matrix.android.sdk.common.CryptoTestHelper
|
|
||||||
import org.matrix.android.sdk.common.checkSendOrder
|
import org.matrix.android.sdk.common.checkSendOrder
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.concurrent.CountDownLatch
|
||||||
@ -53,9 +52,7 @@ class TimelineForwardPaginationTest : InstrumentedTest {
|
|||||||
* This test ensure that if we click to permalink, we will be able to go back to the live
|
* This test ensure that if we click to permalink, we will be able to go back to the live
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun forwardPaginationTest() {
|
fun forwardPaginationTest() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
|
||||||
val commonTestHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
|
|
||||||
val numberOfMessagesToSend = 90
|
val numberOfMessagesToSend = 90
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceInARoom(false)
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceInARoom(false)
|
||||||
|
|
||||||
@ -177,7 +174,5 @@ class TimelineForwardPaginationTest : InstrumentedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
aliceTimeline.dispose()
|
aliceTimeline.dispose()
|
||||||
|
|
||||||
cryptoTestData.cleanUp(commonTestHelper)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,6 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageContent
|
|||||||
import org.matrix.android.sdk.api.session.room.timeline.Timeline
|
import org.matrix.android.sdk.api.session.room.timeline.Timeline
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
|
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
|
||||||
import org.matrix.android.sdk.common.CommonTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper
|
||||||
import org.matrix.android.sdk.common.CryptoTestHelper
|
|
||||||
import org.matrix.android.sdk.common.checkSendOrder
|
import org.matrix.android.sdk.common.checkSendOrder
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.concurrent.CountDownLatch
|
||||||
@ -48,9 +47,7 @@ class TimelinePreviousLastForwardTest : InstrumentedTest {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun previousLastForwardTest() {
|
fun previousLastForwardTest() = CommonTestHelper.runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
|
||||||
val commonTestHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
|
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(false)
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(false)
|
||||||
|
|
||||||
val aliceSession = cryptoTestData.firstSession
|
val aliceSession = cryptoTestData.firstSession
|
||||||
@ -242,7 +239,5 @@ class TimelinePreviousLastForwardTest : InstrumentedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bobTimeline.dispose()
|
bobTimeline.dispose()
|
||||||
|
|
||||||
cryptoTestData.cleanUp(commonTestHelper)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,8 +32,7 @@ import org.matrix.android.sdk.api.session.getRoom
|
|||||||
import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent
|
import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.Timeline
|
import org.matrix.android.sdk.api.session.room.timeline.Timeline
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
|
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
|
||||||
import org.matrix.android.sdk.common.CommonTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
|
||||||
import org.matrix.android.sdk.common.CryptoTestHelper
|
|
||||||
import org.matrix.android.sdk.common.TestConstants
|
import org.matrix.android.sdk.common.TestConstants
|
||||||
|
|
||||||
@RunWith(JUnit4::class)
|
@RunWith(JUnit4::class)
|
||||||
@ -42,9 +41,7 @@ import org.matrix.android.sdk.common.TestConstants
|
|||||||
class TimelineSimpleBackPaginationTest : InstrumentedTest {
|
class TimelineSimpleBackPaginationTest : InstrumentedTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun timeline_backPaginate_shouldReachEndOfTimeline() {
|
fun timeline_backPaginate_shouldReachEndOfTimeline() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
|
||||||
val commonTestHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
|
|
||||||
val numberOfMessagesToSent = 200
|
val numberOfMessagesToSent = 200
|
||||||
|
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(false)
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(false)
|
||||||
@ -102,6 +99,5 @@ class TimelineSimpleBackPaginationTest : InstrumentedTest {
|
|||||||
assertEquals(numberOfMessagesToSent, onlySentEvents.size)
|
assertEquals(numberOfMessagesToSent, onlySentEvents.size)
|
||||||
|
|
||||||
bobTimeline.dispose()
|
bobTimeline.dispose()
|
||||||
cryptoTestData.cleanUp(commonTestHelper)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,8 +30,7 @@ import org.matrix.android.sdk.api.session.events.model.toModel
|
|||||||
import org.matrix.android.sdk.api.session.getRoom
|
import org.matrix.android.sdk.api.session.getRoom
|
||||||
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
|
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
|
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
|
||||||
import org.matrix.android.sdk.common.CommonTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
|
||||||
import org.matrix.android.sdk.common.CryptoTestHelper
|
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.concurrent.CountDownLatch
|
||||||
|
|
||||||
/** !! Not working with the new timeline
|
/** !! Not working with the new timeline
|
||||||
@ -47,15 +46,12 @@ class TimelineWithManyMembersTest : InstrumentedTest {
|
|||||||
private const val NUMBER_OF_MEMBERS = 6
|
private const val NUMBER_OF_MEMBERS = 6
|
||||||
}
|
}
|
||||||
|
|
||||||
private val commonTestHelper = CommonTestHelper(context())
|
|
||||||
private val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensures when someone sends a message to a crowded room, everyone can decrypt the message.
|
* Ensures when someone sends a message to a crowded room, everyone can decrypt the message.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun everyone_should_decrypt_message_in_a_crowded_room() {
|
fun everyone_should_decrypt_message_in_a_crowded_room() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithManyMembers(NUMBER_OF_MEMBERS)
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithManyMembers(NUMBER_OF_MEMBERS)
|
||||||
|
|
||||||
val sessionForFirstMember = cryptoTestData.firstSession
|
val sessionForFirstMember = cryptoTestData.firstSession
|
||||||
|
@ -26,9 +26,8 @@ import org.matrix.android.sdk.InstrumentedTest
|
|||||||
import org.matrix.android.sdk.api.extensions.orFalse
|
import org.matrix.android.sdk.api.extensions.orFalse
|
||||||
import org.matrix.android.sdk.api.session.getRoom
|
import org.matrix.android.sdk.api.session.getRoom
|
||||||
import org.matrix.android.sdk.api.session.search.SearchResult
|
import org.matrix.android.sdk.api.session.search.SearchResult
|
||||||
import org.matrix.android.sdk.common.CommonTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
|
||||||
import org.matrix.android.sdk.common.CryptoTestData
|
import org.matrix.android.sdk.common.CryptoTestData
|
||||||
import org.matrix.android.sdk.common.CryptoTestHelper
|
|
||||||
|
|
||||||
@RunWith(JUnit4::class)
|
@RunWith(JUnit4::class)
|
||||||
@FixMethodOrder(MethodSorters.JVM)
|
@FixMethodOrder(MethodSorters.JVM)
|
||||||
@ -74,9 +73,7 @@ class SearchMessagesTest : InstrumentedTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun doTest(block: suspend (CryptoTestData) -> SearchResult) {
|
private fun doTest(block: suspend (CryptoTestData) -> SearchResult) = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
|
||||||
val commonTestHelper = CommonTestHelper(context())
|
|
||||||
val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
|
|
||||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceInARoom(false)
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceInARoom(false)
|
||||||
val aliceSession = cryptoTestData.firstSession
|
val aliceSession = cryptoTestData.firstSession
|
||||||
val aliceRoomId = cryptoTestData.roomId
|
val aliceRoomId = cryptoTestData.roomId
|
||||||
@ -99,7 +96,5 @@ class SearchMessagesTest : InstrumentedTest {
|
|||||||
(it.event.content?.get("body") as? String)?.startsWith(MESSAGE).orFalse()
|
(it.event.content?.get("body") as? String)?.startsWith(MESSAGE).orFalse()
|
||||||
}.orFalse()
|
}.orFalse()
|
||||||
)
|
)
|
||||||
|
|
||||||
cryptoTestData.cleanUp(commonTestHelper)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
|||||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset
|
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
|
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
|
||||||
import org.matrix.android.sdk.api.session.space.JoinSpaceResult
|
import org.matrix.android.sdk.api.session.space.JoinSpaceResult
|
||||||
import org.matrix.android.sdk.common.CommonTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest
|
||||||
import org.matrix.android.sdk.common.SessionTestParams
|
import org.matrix.android.sdk.common.SessionTestParams
|
||||||
|
|
||||||
@RunWith(JUnit4::class)
|
@RunWith(JUnit4::class)
|
||||||
@ -49,8 +49,7 @@ import org.matrix.android.sdk.common.SessionTestParams
|
|||||||
class SpaceCreationTest : InstrumentedTest {
|
class SpaceCreationTest : InstrumentedTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun createSimplePublicSpace() {
|
fun createSimplePublicSpace() = runSessionTest(context()) { commonTestHelper ->
|
||||||
val commonTestHelper = CommonTestHelper(context())
|
|
||||||
val session = commonTestHelper.createAccount("Hubble", SessionTestParams(true))
|
val session = commonTestHelper.createAccount("Hubble", SessionTestParams(true))
|
||||||
val roomName = "My Space"
|
val roomName = "My Space"
|
||||||
val topic = "A public space for test"
|
val topic = "A public space for test"
|
||||||
@ -96,13 +95,10 @@ class SpaceCreationTest : InstrumentedTest {
|
|||||||
?.toModel<RoomHistoryVisibilityContent>()?.historyVisibility
|
?.toModel<RoomHistoryVisibilityContent>()?.historyVisibility
|
||||||
|
|
||||||
assertEquals("Public space room should be world readable", RoomHistoryVisibility.WORLD_READABLE, historyVisibility)
|
assertEquals("Public space room should be world readable", RoomHistoryVisibility.WORLD_READABLE, historyVisibility)
|
||||||
|
|
||||||
commonTestHelper.signOutAndClose(session)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testJoinSimplePublicSpace() {
|
fun testJoinSimplePublicSpace() = runSessionTest(context()) { commonTestHelper ->
|
||||||
val commonTestHelper = CommonTestHelper(context())
|
|
||||||
|
|
||||||
val aliceSession = commonTestHelper.createAccount("alice", SessionTestParams(true))
|
val aliceSession = commonTestHelper.createAccount("alice", SessionTestParams(true))
|
||||||
val bobSession = commonTestHelper.createAccount("bob", SessionTestParams(true))
|
val bobSession = commonTestHelper.createAccount("bob", SessionTestParams(true))
|
||||||
@ -134,8 +130,7 @@ class SpaceCreationTest : InstrumentedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSimplePublicSpaceWithChildren() {
|
fun testSimplePublicSpaceWithChildren() = runSessionTest(context()) { commonTestHelper ->
|
||||||
val commonTestHelper = CommonTestHelper(context())
|
|
||||||
val aliceSession = commonTestHelper.createAccount("alice", SessionTestParams(true))
|
val aliceSession = commonTestHelper.createAccount("alice", SessionTestParams(true))
|
||||||
val bobSession = commonTestHelper.createAccount("bob", SessionTestParams(true))
|
val bobSession = commonTestHelper.createAccount("bob", SessionTestParams(true))
|
||||||
|
|
||||||
@ -204,8 +199,5 @@ class SpaceCreationTest : InstrumentedTest {
|
|||||||
// ).size
|
// ).size
|
||||||
//
|
//
|
||||||
// assertEquals("Unexpected number of joined children", 1, childCount)
|
// assertEquals("Unexpected number of joined children", 1, childCount)
|
||||||
|
|
||||||
commonTestHelper.signOutAndClose(aliceSession)
|
|
||||||
commonTestHelper.signOutAndClose(bobSession)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,8 +29,8 @@ import org.junit.runner.RunWith
|
|||||||
import org.junit.runners.JUnit4
|
import org.junit.runners.JUnit4
|
||||||
import org.junit.runners.MethodSorters
|
import org.junit.runners.MethodSorters
|
||||||
import org.matrix.android.sdk.InstrumentedTest
|
import org.matrix.android.sdk.InstrumentedTest
|
||||||
import org.matrix.android.sdk.api.query.ActiveSpaceFilter
|
|
||||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||||
|
import org.matrix.android.sdk.api.query.SpaceFilter
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||||
import org.matrix.android.sdk.api.session.events.model.toContent
|
import org.matrix.android.sdk.api.session.events.model.toContent
|
||||||
@ -48,6 +48,7 @@ import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
|||||||
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
||||||
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
||||||
import org.matrix.android.sdk.common.CommonTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper
|
||||||
|
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest
|
||||||
import org.matrix.android.sdk.common.SessionTestParams
|
import org.matrix.android.sdk.common.SessionTestParams
|
||||||
|
|
||||||
@RunWith(JUnit4::class)
|
@RunWith(JUnit4::class)
|
||||||
@ -55,8 +56,7 @@ import org.matrix.android.sdk.common.SessionTestParams
|
|||||||
class SpaceHierarchyTest : InstrumentedTest {
|
class SpaceHierarchyTest : InstrumentedTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun createCanonicalChildRelation() {
|
fun createCanonicalChildRelation() = runSessionTest(context()) { commonTestHelper ->
|
||||||
val commonTestHelper = CommonTestHelper(context())
|
|
||||||
|
|
||||||
val session = commonTestHelper.createAccount("John", SessionTestParams(true))
|
val session = commonTestHelper.createAccount("John", SessionTestParams(true))
|
||||||
val spaceName = "My Space"
|
val spaceName = "My Space"
|
||||||
@ -173,8 +173,7 @@ class SpaceHierarchyTest : InstrumentedTest {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testFilteringBySpace() {
|
fun testFilteringBySpace() = CommonTestHelper.runSessionTest(context()) { commonTestHelper ->
|
||||||
val commonTestHelper = CommonTestHelper(context())
|
|
||||||
val session = commonTestHelper.createAccount("John", SessionTestParams(true))
|
val session = commonTestHelper.createAccount("John", SessionTestParams(true))
|
||||||
|
|
||||||
val spaceAInfo = createPublicSpace(
|
val spaceAInfo = createPublicSpace(
|
||||||
@ -249,15 +248,14 @@ class SpaceHierarchyTest : InstrumentedTest {
|
|||||||
|
|
||||||
Thread.sleep(6_000)
|
Thread.sleep(6_000)
|
||||||
val orphansUpdate = session.roomService().getRoomSummaries(roomSummaryQueryParams {
|
val orphansUpdate = session.roomService().getRoomSummaries(roomSummaryQueryParams {
|
||||||
activeSpaceFilter = ActiveSpaceFilter.ActiveSpace(null)
|
spaceFilter = SpaceFilter.OrphanRooms
|
||||||
})
|
})
|
||||||
assertEquals("Unexpected number of orphan rooms ${orphansUpdate.map { it.name }}", 2, orphansUpdate.size)
|
assertEquals("Unexpected number of orphan rooms ${orphansUpdate.map { it.name }}", 2, orphansUpdate.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Ignore("This test will be ignored until it is fixed")
|
@Ignore("This test will be ignored until it is fixed")
|
||||||
fun testBreakCycle() {
|
fun testBreakCycle() = CommonTestHelper.runSessionTest(context()) { commonTestHelper ->
|
||||||
val commonTestHelper = CommonTestHelper(context())
|
|
||||||
val session = commonTestHelper.createAccount("John", SessionTestParams(true))
|
val session = commonTestHelper.createAccount("John", SessionTestParams(true))
|
||||||
|
|
||||||
val spaceAInfo = createPublicSpace(
|
val spaceAInfo = createPublicSpace(
|
||||||
@ -302,8 +300,7 @@ class SpaceHierarchyTest : InstrumentedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testLiveFlatChildren() {
|
fun testLiveFlatChildren() = CommonTestHelper.runSessionTest(context()) { commonTestHelper ->
|
||||||
val commonTestHelper = CommonTestHelper(context())
|
|
||||||
val session = commonTestHelper.createAccount("John", SessionTestParams(true))
|
val session = commonTestHelper.createAccount("John", SessionTestParams(true))
|
||||||
|
|
||||||
val spaceAInfo = createPublicSpace(
|
val spaceAInfo = createPublicSpace(
|
||||||
@ -395,9 +392,9 @@ class SpaceHierarchyTest : InstrumentedTest {
|
|||||||
childInfo: List<Triple<String, Boolean, Boolean?>>
|
childInfo: List<Triple<String, Boolean, Boolean?>>
|
||||||
/** Name, auto-join, canonical*/
|
/** Name, auto-join, canonical*/
|
||||||
): TestSpaceCreationResult {
|
): TestSpaceCreationResult {
|
||||||
val commonTestHelper = CommonTestHelper(context())
|
|
||||||
var spaceId = ""
|
var spaceId = ""
|
||||||
var roomIds: List<String> = emptyList()
|
var roomIds: List<String> = emptyList()
|
||||||
|
runSessionTest(context()) { commonTestHelper ->
|
||||||
commonTestHelper.waitWithLatch { latch ->
|
commonTestHelper.waitWithLatch { latch ->
|
||||||
spaceId = session.spaceService().createSpace(spaceName, "Test Topic", null, true)
|
spaceId = session.spaceService().createSpace(spaceName, "Test Topic", null, true)
|
||||||
val syncedSpace = session.spaceService().getSpace(spaceId)
|
val syncedSpace = session.spaceService().getSpace(spaceId)
|
||||||
@ -415,6 +412,7 @@ class SpaceHierarchyTest : InstrumentedTest {
|
|||||||
}
|
}
|
||||||
latch.countDown()
|
latch.countDown()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return TestSpaceCreationResult(spaceId, roomIds)
|
return TestSpaceCreationResult(spaceId, roomIds)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -423,9 +421,9 @@ class SpaceHierarchyTest : InstrumentedTest {
|
|||||||
childInfo: List<Triple<String, Boolean, Boolean?>>
|
childInfo: List<Triple<String, Boolean, Boolean?>>
|
||||||
/** Name, auto-join, canonical*/
|
/** Name, auto-join, canonical*/
|
||||||
): TestSpaceCreationResult {
|
): TestSpaceCreationResult {
|
||||||
val commonTestHelper = CommonTestHelper(context())
|
|
||||||
var spaceId = ""
|
var spaceId = ""
|
||||||
var roomIds: List<String> = emptyList()
|
var roomIds: List<String> = emptyList()
|
||||||
|
runSessionTest(context()) { commonTestHelper ->
|
||||||
commonTestHelper.waitWithLatch { latch ->
|
commonTestHelper.waitWithLatch { latch ->
|
||||||
spaceId = session.spaceService().createSpace(spaceName, "My Private Space", null, false)
|
spaceId = session.spaceService().createSpace(spaceName, "My Private Space", null, false)
|
||||||
val syncedSpace = session.spaceService().getSpace(spaceId)
|
val syncedSpace = session.spaceService().getSpace(spaceId)
|
||||||
@ -454,12 +452,12 @@ class SpaceHierarchyTest : InstrumentedTest {
|
|||||||
}
|
}
|
||||||
latch.countDown()
|
latch.countDown()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return TestSpaceCreationResult(spaceId, roomIds)
|
return TestSpaceCreationResult(spaceId, roomIds)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testRootSpaces() {
|
fun testRootSpaces() = runSessionTest(context()) { commonTestHelper ->
|
||||||
val commonTestHelper = CommonTestHelper(context())
|
|
||||||
val session = commonTestHelper.createAccount("John", SessionTestParams(true))
|
val session = commonTestHelper.createAccount("John", SessionTestParams(true))
|
||||||
|
|
||||||
/* val spaceAInfo = */ createPublicSpace(
|
/* val spaceAInfo = */ createPublicSpace(
|
||||||
@ -506,13 +504,10 @@ class SpaceHierarchyTest : InstrumentedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assertEquals("Unexpected number of root spaces ${rootSpaces.map { it.name }}", 2, rootSpaces.size)
|
assertEquals("Unexpected number of root spaces ${rootSpaces.map { it.name }}", 2, rootSpaces.size)
|
||||||
|
|
||||||
commonTestHelper.signOutAndClose(session)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testParentRelation() {
|
fun testParentRelation() = runSessionTest(context()) { commonTestHelper ->
|
||||||
val commonTestHelper = CommonTestHelper(context())
|
|
||||||
val aliceSession = commonTestHelper.createAccount("Alice", SessionTestParams(true))
|
val aliceSession = commonTestHelper.createAccount("Alice", SessionTestParams(true))
|
||||||
val bobSession = commonTestHelper.createAccount("Bib", SessionTestParams(true))
|
val bobSession = commonTestHelper.createAccount("Bib", SessionTestParams(true))
|
||||||
|
|
||||||
@ -604,8 +599,5 @@ class SpaceHierarchyTest : InstrumentedTest {
|
|||||||
bobSession.getRoomSummary(bobRoomId)?.flattenParentIds?.contains(spaceAInfo.spaceId) == true
|
bobSession.getRoomSummary(bobRoomId)?.flattenParentIds?.contains(spaceAInfo.spaceId) == true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
commonTestHelper.signOutAndClose(aliceSession)
|
|
||||||
commonTestHelper.signOutAndClose(bobSession)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,14 @@
|
|||||||
|
|
||||||
package org.matrix.android.sdk.api
|
package org.matrix.android.sdk.api
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface exists to let the implementation provide localized room display name fallback.
|
||||||
|
* The methods can be called when the room has no name, i.e. its `m.room.name` state event does not exist or
|
||||||
|
* the name in it is an empty String.
|
||||||
|
* It allows the SDK to store the room name fallback into the local storage and so let the client do
|
||||||
|
* queries on the room name.
|
||||||
|
* *Limitation*: if the locale of the device changes, the methods will not be called again.
|
||||||
|
*/
|
||||||
interface RoomDisplayNameFallbackProvider {
|
interface RoomDisplayNameFallbackProvider {
|
||||||
fun getNameForRoomInvite(): String
|
fun getNameForRoomInvite(): String
|
||||||
fun getNameForEmptyRoom(isDirect: Boolean, leftMemberNames: List<String>): String
|
fun getNameForEmptyRoom(isDirect: Boolean, leftMemberNames: List<String>): String
|
||||||
|
@ -66,7 +66,7 @@ interface AuthenticationService {
|
|||||||
/**
|
/**
|
||||||
* True when login and password has been sent with success to the homeserver.
|
* True when login and password has been sent with success to the homeserver.
|
||||||
*/
|
*/
|
||||||
val isRegistrationStarted: Boolean
|
fun isRegistrationStarted(): Boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cancel pending login or pending registration.
|
* Cancel pending login or pending registration.
|
||||||
|
@ -18,13 +18,31 @@ package org.matrix.android.sdk.api.auth.registration
|
|||||||
|
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
|
|
||||||
// Either a session or an object containing data about registration stages
|
/**
|
||||||
|
* Either a session or an object containing data about registration stages.
|
||||||
|
*/
|
||||||
sealed class RegistrationResult {
|
sealed class RegistrationResult {
|
||||||
|
/**
|
||||||
|
* The registration is successful, the [Session] is provided.
|
||||||
|
*/
|
||||||
data class Success(val session: Session) : RegistrationResult()
|
data class Success(val session: Session) : RegistrationResult()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The registration still miss some steps. See [FlowResult] to know the details.
|
||||||
|
*/
|
||||||
data class FlowResponse(val flowResult: FlowResult) : RegistrationResult()
|
data class FlowResponse(val flowResult: FlowResult) : RegistrationResult()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information about the missing and completed [Stage].
|
||||||
|
*/
|
||||||
data class FlowResult(
|
data class FlowResult(
|
||||||
|
/**
|
||||||
|
* List of missing stages.
|
||||||
|
*/
|
||||||
val missingStages: List<Stage>,
|
val missingStages: List<Stage>,
|
||||||
|
/**
|
||||||
|
* List of completed stages.
|
||||||
|
*/
|
||||||
val completedStages: List<Stage>
|
val completedStages: List<Stage>
|
||||||
)
|
)
|
||||||
|
@ -109,14 +109,14 @@ interface RegistrationWizard {
|
|||||||
suspend fun checkIfEmailHasBeenValidated(delayMillis: Long): RegistrationResult
|
suspend fun checkIfEmailHasBeenValidated(delayMillis: Long): RegistrationResult
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the current ThreePid, waiting for validation. The SDK will store it in database, so it can be
|
* Returns the current ThreePid, waiting for validation. The SDK will store it in database, so it can be
|
||||||
* restored even if the app has been killed during the registration
|
* restored even if the app has been killed during the registration
|
||||||
*/
|
*/
|
||||||
val currentThreePid: String?
|
fun getCurrentThreePid(): String?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True when login and password have been sent with success to the homeserver, i.e. [createAccount] has been
|
* Return true when login and password have been sent with success to the homeserver, i.e. [createAccount] has been
|
||||||
* called successfully.
|
* called successfully.
|
||||||
*/
|
*/
|
||||||
val isRegistrationStarted: Boolean
|
fun isRegistrationStarted(): Boolean
|
||||||
}
|
}
|
||||||
|
@ -16,25 +16,40 @@
|
|||||||
|
|
||||||
package org.matrix.android.sdk.api.auth.registration
|
package org.matrix.android.sdk.api.auth.registration
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registration stages.
|
||||||
|
*/
|
||||||
sealed class Stage(open val mandatory: Boolean) {
|
sealed class Stage(open val mandatory: Boolean) {
|
||||||
|
|
||||||
// m.login.recaptcha
|
/**
|
||||||
|
* m.login.recaptcha stage.
|
||||||
|
*/
|
||||||
data class ReCaptcha(override val mandatory: Boolean, val publicKey: String) : Stage(mandatory)
|
data class ReCaptcha(override val mandatory: Boolean, val publicKey: String) : Stage(mandatory)
|
||||||
|
|
||||||
// m.login.email.identity
|
/**
|
||||||
|
* m.login.email.identity stage.
|
||||||
|
*/
|
||||||
data class Email(override val mandatory: Boolean) : Stage(mandatory)
|
data class Email(override val mandatory: Boolean) : Stage(mandatory)
|
||||||
|
|
||||||
// m.login.msisdn
|
/**
|
||||||
|
* m.login.msisdn stage.
|
||||||
|
*/
|
||||||
data class Msisdn(override val mandatory: Boolean) : Stage(mandatory)
|
data class Msisdn(override val mandatory: Boolean) : Stage(mandatory)
|
||||||
|
|
||||||
// m.login.dummy, can be mandatory if there is no other stages. In this case the account cannot be created by just sending a username
|
/**
|
||||||
// and a password, the dummy stage has to be done
|
* m.login.dummy, can be mandatory if there is no other stages. In this case the account cannot be created by just sending a username
|
||||||
|
* and a password, the dummy stage has to be done.
|
||||||
|
*/
|
||||||
data class Dummy(override val mandatory: Boolean) : Stage(mandatory)
|
data class Dummy(override val mandatory: Boolean) : Stage(mandatory)
|
||||||
|
|
||||||
// Undocumented yet: m.login.terms
|
/**
|
||||||
|
* Undocumented yet: m.login.terms stage.
|
||||||
|
*/
|
||||||
data class Terms(override val mandatory: Boolean, val policies: TermPolicies) : Stage(mandatory)
|
data class Terms(override val mandatory: Boolean, val policies: TermPolicies) : Stage(mandatory)
|
||||||
|
|
||||||
// For unknown stages
|
/**
|
||||||
|
* For unknown stages.
|
||||||
|
*/
|
||||||
data class Other(override val mandatory: Boolean, val type: String, val params: Map<*, *>?) : Stage(mandatory)
|
data class Other(override val mandatory: Boolean, val type: String, val params: Map<*, *>?) : Stage(mandatory)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,13 +17,19 @@
|
|||||||
package org.matrix.android.sdk.api.cache
|
package org.matrix.android.sdk.api.cache
|
||||||
|
|
||||||
sealed class CacheStrategy {
|
sealed class CacheStrategy {
|
||||||
// Data is always fetched from the server
|
/**
|
||||||
|
* Data is always fetched from the server.
|
||||||
|
*/
|
||||||
object NoCache : CacheStrategy()
|
object NoCache : CacheStrategy()
|
||||||
|
|
||||||
// Once data is retrieved, it is stored for the provided amount of time.
|
/**
|
||||||
// In case of error, and if strict is set to false, the cache can be returned if available
|
* Once data is retrieved, it is stored for the provided amount of time.
|
||||||
|
* In case of error, and if strict is set to false, the cache can be returned if available
|
||||||
|
*/
|
||||||
data class TtlCache(val validityDurationInMillis: Long, val strict: Boolean) : CacheStrategy()
|
data class TtlCache(val validityDurationInMillis: Long, val strict: Boolean) : CacheStrategy()
|
||||||
|
|
||||||
// Once retrieved, the data is stored in cache and will be always get from the cache
|
/**
|
||||||
|
* Once retrieved, the data is stored in cache and will be always get from the cache.
|
||||||
|
*/
|
||||||
object InfiniteCache : CacheStrategy()
|
object InfiniteCache : CacheStrategy()
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,9 @@ sealed class Failure(cause: Throwable? = null) : Throwable(cause = cause) {
|
|||||||
data class ServerError(val error: MatrixError, val httpCode: Int) : Failure(RuntimeException(error.toString()))
|
data class ServerError(val error: MatrixError, val httpCode: Int) : Failure(RuntimeException(error.toString()))
|
||||||
object SuccessError : Failure(RuntimeException(RuntimeException("SuccessResult is false")))
|
object SuccessError : Failure(RuntimeException(RuntimeException("SuccessResult is false")))
|
||||||
|
|
||||||
// When server send an error, but it cannot be interpreted as a MatrixError
|
/**
|
||||||
|
* When server send an error, but it cannot be interpreted as a MatrixError.
|
||||||
|
*/
|
||||||
data class OtherServerError(val errorBody: String, val httpCode: Int) : Failure(RuntimeException("HTTP $httpCode: $errorBody"))
|
data class OtherServerError(val errorBody: String, val httpCode: Int) : Failure(RuntimeException("HTTP $httpCode: $errorBody"))
|
||||||
|
|
||||||
data class RegistrationFlowError(val registrationFlowResponse: RegistrationFlowResponse) : Failure(RuntimeException(registrationFlowResponse.toString()))
|
data class RegistrationFlowError(val registrationFlowResponse: RegistrationFlowResponse) : Failure(RuntimeException(registrationFlowResponse.toString()))
|
||||||
|
@ -20,20 +20,52 @@ package org.matrix.android.sdk.api.query
|
|||||||
* Basic query language. All these cases are mutually exclusive.
|
* Basic query language. All these cases are mutually exclusive.
|
||||||
*/
|
*/
|
||||||
sealed interface QueryStringValue {
|
sealed interface QueryStringValue {
|
||||||
|
/**
|
||||||
|
* No condition, i.e. there will be no test on the tested field.
|
||||||
|
*/
|
||||||
|
object NoCondition : QueryStringValue
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tested field has to be null.
|
||||||
|
*/
|
||||||
|
object IsNull : QueryStringValue
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tested field has to be not null.
|
||||||
|
*/
|
||||||
|
object IsNotNull : QueryStringValue
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tested field has to be empty.
|
||||||
|
*/
|
||||||
|
object IsEmpty : QueryStringValue
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tested field has to not empty.
|
||||||
|
*/
|
||||||
|
object IsNotEmpty : QueryStringValue
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to check String content.
|
||||||
|
*/
|
||||||
sealed interface ContentQueryStringValue : QueryStringValue {
|
sealed interface ContentQueryStringValue : QueryStringValue {
|
||||||
val string: String
|
val string: String
|
||||||
val case: Case
|
val case: Case
|
||||||
}
|
}
|
||||||
|
|
||||||
object NoCondition : QueryStringValue
|
/**
|
||||||
object IsNull : QueryStringValue
|
* The tested field must match the [string].
|
||||||
object IsNotNull : QueryStringValue
|
*/
|
||||||
object IsEmpty : QueryStringValue
|
|
||||||
object IsNotEmpty : QueryStringValue
|
|
||||||
|
|
||||||
data class Equals(override val string: String, override val case: Case = Case.SENSITIVE) : ContentQueryStringValue
|
data class Equals(override val string: String, override val case: Case = Case.SENSITIVE) : ContentQueryStringValue
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tested field must contain the [string].
|
||||||
|
*/
|
||||||
data class Contains(override val string: String, override val case: Case = Case.SENSITIVE) : ContentQueryStringValue
|
data class Contains(override val string: String, override val case: Case = Case.SENSITIVE) : ContentQueryStringValue
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Case enum for [ContentQueryStringValue].
|
||||||
|
*/
|
||||||
enum class Case {
|
enum class Case {
|
||||||
/**
|
/**
|
||||||
* Match query sensitive to case.
|
* Match query sensitive to case.
|
||||||
|
@ -16,9 +16,23 @@
|
|||||||
|
|
||||||
package org.matrix.android.sdk.api.query
|
package org.matrix.android.sdk.api.query
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To filter by Room category.
|
||||||
|
* @see [org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams]
|
||||||
|
*/
|
||||||
enum class RoomCategoryFilter {
|
enum class RoomCategoryFilter {
|
||||||
|
/**
|
||||||
|
* Get only the DM, i.e. the rooms referenced in `m.direct` account data.
|
||||||
|
*/
|
||||||
ONLY_DM,
|
ONLY_DM,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get only the Room, not the DM, i.e. the rooms not referenced in `m.direct` account data.
|
||||||
|
*/
|
||||||
ONLY_ROOMS,
|
ONLY_ROOMS,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the room with non-0 notifications.
|
||||||
|
*/
|
||||||
ONLY_WITH_NOTIFICATIONS,
|
ONLY_WITH_NOTIFICATIONS,
|
||||||
ALL
|
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,22 @@
|
|||||||
|
|
||||||
package org.matrix.android.sdk.api.query
|
package org.matrix.android.sdk.api.query
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter room by their tag.
|
||||||
|
* @see [org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams]
|
||||||
|
* @see [org.matrix.android.sdk.api.session.room.model.tag.RoomTag]
|
||||||
|
*/
|
||||||
data class RoomTagQueryFilter(
|
data class RoomTagQueryFilter(
|
||||||
|
/**
|
||||||
|
* Set to true to get the rooms which have the tag "m.favourite".
|
||||||
|
*/
|
||||||
val isFavorite: Boolean?,
|
val isFavorite: Boolean?,
|
||||||
|
/**
|
||||||
|
* Set to true to get the rooms which have the tag "m.lowpriority".
|
||||||
|
*/
|
||||||
val isLowPriority: Boolean?,
|
val isLowPriority: Boolean?,
|
||||||
val isServerNotice: Boolean?
|
/**
|
||||||
|
* Set to true to get the rooms which have the tag "m.server_notice".
|
||||||
|
*/
|
||||||
|
val isServerNotice: Boolean?,
|
||||||
)
|
)
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.matrix.android.sdk.api.query
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter to be used to do room queries regarding the space hierarchy.
|
||||||
|
* @see [org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams]
|
||||||
|
*/
|
||||||
|
sealed interface SpaceFilter {
|
||||||
|
/**
|
||||||
|
* Used to get all the rooms that are not in any space.
|
||||||
|
*/
|
||||||
|
object OrphanRooms : SpaceFilter
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to get all the rooms that have the provided space in their parent hierarchy.
|
||||||
|
*/
|
||||||
|
data class ActiveSpace(val spaceId: String) : SpaceFilter
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to get all the rooms that do not have the provided space in their parent hierarchy.
|
||||||
|
*/
|
||||||
|
data class ExcludeSpace(val spaceId: String) : SpaceFilter
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a [SpaceFilter.ActiveSpace] if the String is not null, or [SpaceFilter.OrphanRooms].
|
||||||
|
*/
|
||||||
|
fun String?.toActiveSpaceOrOrphanRooms(): SpaceFilter = this?.let { SpaceFilter.ActiveSpace(it) } ?: SpaceFilter.OrphanRooms
|
@ -168,8 +168,6 @@ interface KeysBackupService {
|
|||||||
password: String,
|
password: String,
|
||||||
callback: MatrixCallback<Unit>)
|
callback: MatrixCallback<Unit>)
|
||||||
|
|
||||||
fun onSecretKeyGossip(secret: String)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restore a backup with a recovery key from a given backup version stored on the homeserver.
|
* Restore a backup with a recovery key from a given backup version stored on the homeserver.
|
||||||
*
|
*
|
||||||
@ -204,10 +202,13 @@ interface KeysBackupService {
|
|||||||
callback: MatrixCallback<ImportRoomKeysResult>)
|
callback: MatrixCallback<ImportRoomKeysResult>)
|
||||||
|
|
||||||
val keysBackupVersion: KeysVersionResult?
|
val keysBackupVersion: KeysVersionResult?
|
||||||
|
|
||||||
val currentBackupVersion: String?
|
val currentBackupVersion: String?
|
||||||
val isEnabled: Boolean
|
get() = keysBackupVersion?.version
|
||||||
val isStucked: Boolean
|
|
||||||
val state: KeysBackupState
|
fun isEnabled(): Boolean
|
||||||
|
fun isStuck(): Boolean
|
||||||
|
fun getState(): KeysBackupState
|
||||||
|
|
||||||
// For gossiping
|
// For gossiping
|
||||||
fun saveBackupRecoveryKey(recoveryKey: String?, version: String?)
|
fun saveBackupRecoveryKey(recoveryKey: String?, version: String?)
|
||||||
|
@ -51,33 +51,51 @@ package org.matrix.android.sdk.api.session.crypto.keysbackup
|
|||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
enum class KeysBackupState {
|
enum class KeysBackupState {
|
||||||
// Need to check the current backup version on the homeserver
|
/**
|
||||||
|
* Need to check the current backup version on the homeserver.
|
||||||
|
*/
|
||||||
Unknown,
|
Unknown,
|
||||||
|
|
||||||
// Checking if backup is enabled on homeserver
|
/**
|
||||||
|
* Checking if backup is enabled on homeserver.
|
||||||
|
*/
|
||||||
CheckingBackUpOnHomeserver,
|
CheckingBackUpOnHomeserver,
|
||||||
|
|
||||||
// Backup has been stopped because a new backup version has been detected on the homeserver
|
/**
|
||||||
|
* Backup has been stopped because a new backup version has been detected on the homeserver.
|
||||||
|
*/
|
||||||
WrongBackUpVersion,
|
WrongBackUpVersion,
|
||||||
|
|
||||||
// Backup from this device is not enabled
|
/**
|
||||||
|
* Backup from this device is not enabled.
|
||||||
|
*/
|
||||||
Disabled,
|
Disabled,
|
||||||
|
|
||||||
// There is a backup available on the homeserver but it is not trusted.
|
/**
|
||||||
// It is not trusted because the signature is invalid or the device that created it is not verified
|
* There is a backup available on the homeserver but it is not trusted.
|
||||||
// Use [KeysBackup.getKeysBackupTrust()] to get trust details.
|
* It is not trusted because the signature is invalid or the device that created it is not verified.
|
||||||
// Consequently, the backup from this device is not enabled.
|
* Use [KeysBackup.getKeysBackupTrust()] to get trust details.
|
||||||
|
* Consequently, the backup from this device is not enabled.
|
||||||
|
*/
|
||||||
NotTrusted,
|
NotTrusted,
|
||||||
|
|
||||||
// Backup is being enabled: the backup version is being created on the homeserver
|
/**
|
||||||
|
* Backup is being enabled: the backup version is being created on the homeserver.
|
||||||
|
*/
|
||||||
Enabling,
|
Enabling,
|
||||||
|
|
||||||
// Backup is enabled and ready to send backup to the homeserver
|
/**
|
||||||
|
* Backup is enabled and ready to send backup to the homeserver.
|
||||||
|
*/
|
||||||
ReadyToBackUp,
|
ReadyToBackUp,
|
||||||
|
|
||||||
// e2e keys are going to be sent to the homeserver
|
/**
|
||||||
|
* e2e keys are going to be sent to the homeserver.
|
||||||
|
*/
|
||||||
WillBackUp,
|
WillBackUp,
|
||||||
|
|
||||||
// e2e keys are being sent to the homeserver
|
/**
|
||||||
|
* e2e keys are being sent to the homeserver.
|
||||||
|
*/
|
||||||
BackingUp
|
BackingUp
|
||||||
}
|
}
|
||||||
|
@ -20,15 +20,23 @@ package org.matrix.android.sdk.api.session.crypto.model
|
|||||||
* RoomEncryptionTrustLevel represents the trust level in an encrypted room.
|
* RoomEncryptionTrustLevel represents the trust level in an encrypted room.
|
||||||
*/
|
*/
|
||||||
enum class RoomEncryptionTrustLevel {
|
enum class RoomEncryptionTrustLevel {
|
||||||
// No one in the room has been verified -> Black shield
|
/**
|
||||||
|
* No one in the room has been verified -> Black shield.
|
||||||
|
*/
|
||||||
Default,
|
Default,
|
||||||
|
|
||||||
// There are one or more device un-verified -> the app should display a red shield
|
/**
|
||||||
|
* There are one or more device un-verified -> the app should display a red shield.
|
||||||
|
*/
|
||||||
Warning,
|
Warning,
|
||||||
|
|
||||||
// All devices in the room are verified -> the app should display a green shield
|
/**
|
||||||
|
* All devices in the room are verified -> the app should display a green shield.
|
||||||
|
*/
|
||||||
Trusted,
|
Trusted,
|
||||||
|
|
||||||
// e2e is active but with an unsupported algorithm
|
/**
|
||||||
|
* e2e is active but with an unsupported algorithm.
|
||||||
|
*/
|
||||||
E2EWithUnsupportedAlgorithm
|
E2EWithUnsupportedAlgorithm
|
||||||
}
|
}
|
||||||
|
@ -20,12 +20,18 @@ package org.matrix.android.sdk.api.session.crypto.verification
|
|||||||
* Verification methods.
|
* Verification methods.
|
||||||
*/
|
*/
|
||||||
enum class VerificationMethod {
|
enum class VerificationMethod {
|
||||||
// Use it when your application supports the SAS verification method
|
/**
|
||||||
|
* Use it when your application supports the SAS verification method.
|
||||||
|
*/
|
||||||
SAS,
|
SAS,
|
||||||
|
|
||||||
// Use it if your application is able to display QR codes
|
/**
|
||||||
|
* Use it if your application is able to display QR codes.
|
||||||
|
*/
|
||||||
QR_CODE_SHOW,
|
QR_CODE_SHOW,
|
||||||
|
|
||||||
// Use it if your application is able to scan QR codes
|
/**
|
||||||
|
* Use it if your application is able to scan QR codes.
|
||||||
|
*/
|
||||||
QR_CODE_SCAN
|
QR_CODE_SCAN
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,14 @@
|
|||||||
package org.matrix.android.sdk.api.session.crypto.verification
|
package org.matrix.android.sdk.api.session.crypto.verification
|
||||||
|
|
||||||
sealed class VerificationTxState {
|
sealed class VerificationTxState {
|
||||||
// Uninitialized state
|
/**
|
||||||
|
* Uninitialized state.
|
||||||
|
*/
|
||||||
object None : VerificationTxState()
|
object None : VerificationTxState()
|
||||||
|
|
||||||
// Specific for SAS
|
/**
|
||||||
|
* Specific for SAS.
|
||||||
|
*/
|
||||||
abstract class VerificationSasTxState : VerificationTxState()
|
abstract class VerificationSasTxState : VerificationTxState()
|
||||||
|
|
||||||
object SendingStart : VerificationSasTxState()
|
object SendingStart : VerificationSasTxState()
|
||||||
@ -38,18 +42,26 @@ sealed class VerificationTxState {
|
|||||||
object MacSent : VerificationSasTxState()
|
object MacSent : VerificationSasTxState()
|
||||||
object Verifying : VerificationSasTxState()
|
object Verifying : VerificationSasTxState()
|
||||||
|
|
||||||
// Specific for QR code
|
/**
|
||||||
|
* Specific for QR code.
|
||||||
|
*/
|
||||||
abstract class VerificationQrTxState : VerificationTxState()
|
abstract class VerificationQrTxState : VerificationTxState()
|
||||||
|
|
||||||
// Will be used to ask the user if the other user has correctly scanned
|
/**
|
||||||
|
* Will be used to ask the user if the other user has correctly scanned.
|
||||||
|
*/
|
||||||
object QrScannedByOther : VerificationQrTxState()
|
object QrScannedByOther : VerificationQrTxState()
|
||||||
object WaitingOtherReciprocateConfirm : VerificationQrTxState()
|
object WaitingOtherReciprocateConfirm : VerificationQrTxState()
|
||||||
|
|
||||||
// Terminal states
|
/**
|
||||||
|
* Terminal states.
|
||||||
|
*/
|
||||||
abstract class TerminalTxState : VerificationTxState()
|
abstract class TerminalTxState : VerificationTxState()
|
||||||
|
|
||||||
object Verified : TerminalTxState()
|
object Verified : TerminalTxState()
|
||||||
|
|
||||||
// Cancelled by me or by other
|
/**
|
||||||
|
* Cancelled by me or by other.
|
||||||
|
*/
|
||||||
data class Cancelled(val cancelCode: CancelCode, val byMe: Boolean) : TerminalTxState()
|
data class Cancelled(val cancelCode: CancelCode, val byMe: Boolean) : TerminalTxState()
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.matrix.android.sdk.api.session.pushers
|
||||||
|
|
||||||
|
data class HttpPusher(
|
||||||
|
/**
|
||||||
|
* This is a unique identifier for this pusher. The value you should use for
|
||||||
|
* this is the routing or destination address information for the notification,
|
||||||
|
* for example, the APNS token for APNS or the Registration ID for GCM. If your
|
||||||
|
* notification client has no such concept, use any unique identifier. Max length, 512 chars.
|
||||||
|
*/
|
||||||
|
val pushkey: String,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The application id
|
||||||
|
* This is a reverse-DNS style identifier for the application. It is recommended
|
||||||
|
* that this end with the platform, such that different platform versions get
|
||||||
|
* different app identifiers. Max length, 64 chars.
|
||||||
|
*/
|
||||||
|
val appId: String,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This string determines which set of device specific rules this pusher executes.
|
||||||
|
*/
|
||||||
|
val profileTag: String,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The preferred language for receiving notifications (e.g. "en" or "en-US").
|
||||||
|
*/
|
||||||
|
val lang: String,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A human readable string that will allow the user to identify what application owns this pusher.
|
||||||
|
*/
|
||||||
|
val appDisplayName: String,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A human readable string that will allow the user to identify what device owns this pusher.
|
||||||
|
*/
|
||||||
|
val deviceDisplayName: String,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL to use to send notifications to. MUST be an HTTPS URL with a path of /_matrix/push/v1/notify.
|
||||||
|
*/
|
||||||
|
val url: String,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If true, the homeserver should add another pusher with the given pushkey and App ID in addition
|
||||||
|
* to any others with different user IDs. Otherwise, the homeserver must remove any other pushers
|
||||||
|
* with the same App ID and pushkey for different users.
|
||||||
|
*/
|
||||||
|
val append: Boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* true to limit the push content to only id and not message content
|
||||||
|
* Ref: https://matrix.org/docs/spec/push_gateway/r0.1.1#homeserver-behaviour
|
||||||
|
*/
|
||||||
|
val withEventIdOnly: Boolean
|
||||||
|
)
|
@ -107,61 +107,4 @@ interface PushersService {
|
|||||||
* Get the current pushers.
|
* Get the current pushers.
|
||||||
*/
|
*/
|
||||||
fun getPushers(): List<Pusher>
|
fun getPushers(): List<Pusher>
|
||||||
|
|
||||||
data class HttpPusher(
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a unique identifier for this pusher. The value you should use for
|
|
||||||
* this is the routing or destination address information for the notification,
|
|
||||||
* for example, the APNS token for APNS or the Registration ID for GCM. If your
|
|
||||||
* notification client has no such concept, use any unique identifier. Max length, 512 chars.
|
|
||||||
*/
|
|
||||||
val pushkey: String,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The application id
|
|
||||||
* This is a reverse-DNS style identifier for the application. It is recommended
|
|
||||||
* that this end with the platform, such that different platform versions get
|
|
||||||
* different app identifiers. Max length, 64 chars.
|
|
||||||
*/
|
|
||||||
val appId: String,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This string determines which set of device specific rules this pusher executes.
|
|
||||||
*/
|
|
||||||
val profileTag: String,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The preferred language for receiving notifications (e.g. "en" or "en-US").
|
|
||||||
*/
|
|
||||||
val lang: String,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A human readable string that will allow the user to identify what application owns this pusher.
|
|
||||||
*/
|
|
||||||
val appDisplayName: String,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A human readable string that will allow the user to identify what device owns this pusher.
|
|
||||||
*/
|
|
||||||
val deviceDisplayName: String,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The URL to use to send notifications to. MUST be an HTTPS URL with a path of /_matrix/push/v1/notify.
|
|
||||||
*/
|
|
||||||
val url: String,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If true, the homeserver should add another pusher with the given pushkey and App ID in addition
|
|
||||||
* to any others with different user IDs. Otherwise, the homeserver must remove any other pushers
|
|
||||||
* with the same App ID and pushkey for different users.
|
|
||||||
*/
|
|
||||||
val append: Boolean,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* true to limit the push content to only id and not message content
|
|
||||||
* Ref: https://matrix.org/docs/spec/push_gateway/r0.1.1#homeserver-behaviour
|
|
||||||
*/
|
|
||||||
val withEventIdOnly: Boolean
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataServic
|
|||||||
import org.matrix.android.sdk.api.session.room.alias.AliasService
|
import org.matrix.android.sdk.api.session.room.alias.AliasService
|
||||||
import org.matrix.android.sdk.api.session.room.call.RoomCallService
|
import org.matrix.android.sdk.api.session.room.call.RoomCallService
|
||||||
import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService
|
import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService
|
||||||
|
import org.matrix.android.sdk.api.session.room.location.LocationSharingService
|
||||||
import org.matrix.android.sdk.api.session.room.members.MembershipService
|
import org.matrix.android.sdk.api.session.room.members.MembershipService
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.relation.RelationService
|
import org.matrix.android.sdk.api.session.room.model.relation.RelationService
|
||||||
@ -163,4 +164,9 @@ interface Room {
|
|||||||
* Get the RoomVersionService associated to this Room.
|
* Get the RoomVersionService associated to this Room.
|
||||||
*/
|
*/
|
||||||
fun roomVersionService(): RoomVersionService
|
fun roomVersionService(): RoomVersionService
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the LocationSharingService associated to this Room.
|
||||||
|
*/
|
||||||
|
fun locationSharingService(): LocationSharingService
|
||||||
}
|
}
|
||||||
|
@ -97,6 +97,12 @@ interface RoomService {
|
|||||||
*/
|
*/
|
||||||
fun getRoomSummary(roomIdOrAlias: String): RoomSummary?
|
fun getRoomSummary(roomIdOrAlias: String): RoomSummary?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A live [RoomSummary] associated with the room with id [roomId].
|
||||||
|
* You can observe this summary to get dynamic data from this room, even if the room is not joined yet
|
||||||
|
*/
|
||||||
|
fun getRoomSummaryLive(roomId: String): LiveData<Optional<RoomSummary>>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a snapshot list of room summaries.
|
* Get a snapshot list of room summaries.
|
||||||
* @return the immutable list of [RoomSummary]
|
* @return the immutable list of [RoomSummary]
|
||||||
|
@ -16,9 +16,28 @@
|
|||||||
|
|
||||||
package org.matrix.android.sdk.api.session.room
|
package org.matrix.android.sdk.api.session.room
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum to sort room list.
|
||||||
|
*/
|
||||||
enum class RoomSortOrder {
|
enum class RoomSortOrder {
|
||||||
|
/**
|
||||||
|
* Sort room list by room ascending name.
|
||||||
|
*/
|
||||||
NAME,
|
NAME,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort room list by room descending last activity.
|
||||||
|
*/
|
||||||
ACTIVITY,
|
ACTIVITY,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort room list by room priority and last activity: favorite room first, low priority room last,
|
||||||
|
* then descending last activity.
|
||||||
|
*/
|
||||||
PRIORITY_AND_ACTIVITY,
|
PRIORITY_AND_ACTIVITY,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not sort room list. Useful if the order does not matter. Order can be indeterminate.
|
||||||
|
*/
|
||||||
NONE
|
NONE
|
||||||
}
|
}
|
||||||
|
@ -16,60 +16,99 @@
|
|||||||
|
|
||||||
package org.matrix.android.sdk.api.session.room
|
package org.matrix.android.sdk.api.session.room
|
||||||
|
|
||||||
import org.matrix.android.sdk.api.query.ActiveSpaceFilter
|
|
||||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||||
import org.matrix.android.sdk.api.query.RoomCategoryFilter
|
import org.matrix.android.sdk.api.query.RoomCategoryFilter
|
||||||
import org.matrix.android.sdk.api.query.RoomTagQueryFilter
|
import org.matrix.android.sdk.api.query.RoomTagQueryFilter
|
||||||
|
import org.matrix.android.sdk.api.query.SpaceFilter
|
||||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomType
|
import org.matrix.android.sdk.api.session.room.model.RoomType
|
||||||
import org.matrix.android.sdk.api.session.space.SpaceSummaryQueryParams
|
import org.matrix.android.sdk.api.session.space.SpaceSummaryQueryParams
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a [RoomSummaryQueryParams] object, calling [init] with a [RoomSummaryQueryParams.Builder].
|
||||||
|
*/
|
||||||
fun roomSummaryQueryParams(init: (RoomSummaryQueryParams.Builder.() -> Unit) = {}): RoomSummaryQueryParams {
|
fun roomSummaryQueryParams(init: (RoomSummaryQueryParams.Builder.() -> Unit) = {}): RoomSummaryQueryParams {
|
||||||
return RoomSummaryQueryParams.Builder().apply(init).build()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun spaceSummaryQueryParams(init: (RoomSummaryQueryParams.Builder.() -> Unit) = {}): SpaceSummaryQueryParams {
|
|
||||||
return RoomSummaryQueryParams.Builder()
|
return RoomSummaryQueryParams.Builder()
|
||||||
.apply(init)
|
.apply(init)
|
||||||
.apply {
|
|
||||||
includeType = listOf(RoomType.SPACE)
|
|
||||||
excludeType = null
|
|
||||||
roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS
|
|
||||||
}
|
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class can be used to filter room summaries to use with:
|
* Create a [SpaceSummaryQueryParams] object (which is a [RoomSummaryQueryParams]), calling [init] with a [RoomSummaryQueryParams.Builder].
|
||||||
* [org.matrix.android.sdk.api.session.room.Room] and [org.matrix.android.sdk.api.session.room.RoomService].
|
* This is specific for spaces, other filters will be applied after invoking [init]
|
||||||
|
*/
|
||||||
|
fun spaceSummaryQueryParams(init: (RoomSummaryQueryParams.Builder.() -> Unit) = {}): SpaceSummaryQueryParams {
|
||||||
|
return roomSummaryQueryParams {
|
||||||
|
init()
|
||||||
|
includeType = listOf(RoomType.SPACE)
|
||||||
|
excludeType = null
|
||||||
|
roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class can be used to filter room summaries to use with [RoomService].
|
||||||
|
* It provides a [Builder].
|
||||||
|
* [roomSummaryQueryParams] and [spaceSummaryQueryParams] can also be used to build an instance of this class.
|
||||||
*/
|
*/
|
||||||
data class RoomSummaryQueryParams(
|
data class RoomSummaryQueryParams(
|
||||||
val roomId: QueryStringValue,
|
/**
|
||||||
|
* Query for the displayName of the room. The display name can be the value of the state event,
|
||||||
|
* or a value returned by [org.matrix.android.sdk.api.RoomDisplayNameFallbackProvider].
|
||||||
|
*/
|
||||||
val displayName: QueryStringValue,
|
val displayName: QueryStringValue,
|
||||||
|
/**
|
||||||
|
* Query for the canonical alias of the room.
|
||||||
|
*/
|
||||||
val canonicalAlias: QueryStringValue,
|
val canonicalAlias: QueryStringValue,
|
||||||
|
/**
|
||||||
|
* Used to filter room by membership.
|
||||||
|
*/
|
||||||
val memberships: List<Membership>,
|
val memberships: List<Membership>,
|
||||||
|
/**
|
||||||
|
* Used to filter room by room category.
|
||||||
|
*/
|
||||||
val roomCategoryFilter: RoomCategoryFilter?,
|
val roomCategoryFilter: RoomCategoryFilter?,
|
||||||
|
/**
|
||||||
|
* Used to filter room by room tag.
|
||||||
|
*/
|
||||||
val roomTagQueryFilter: RoomTagQueryFilter?,
|
val roomTagQueryFilter: RoomTagQueryFilter?,
|
||||||
|
/**
|
||||||
|
* Used to filter room by room type.
|
||||||
|
* @see [includeType]
|
||||||
|
*/
|
||||||
val excludeType: List<String?>?,
|
val excludeType: List<String?>?,
|
||||||
|
/**
|
||||||
|
* Used to filter room by room type.
|
||||||
|
* @see [excludeType]
|
||||||
|
*/
|
||||||
val includeType: List<String?>?,
|
val includeType: List<String?>?,
|
||||||
val activeSpaceFilter: ActiveSpaceFilter?,
|
/**
|
||||||
|
* Used to filter room using the current space.
|
||||||
|
*/
|
||||||
|
val spaceFilter: SpaceFilter?,
|
||||||
|
/**
|
||||||
|
* Used to filter room using the current group.
|
||||||
|
*/
|
||||||
val activeGroupId: String? = null
|
val activeGroupId: String? = null
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder for [RoomSummaryQueryParams].
|
||||||
|
* [roomSummaryQueryParams] and [spaceSummaryQueryParams] can also be used to build an instance of [RoomSummaryQueryParams].
|
||||||
|
*/
|
||||||
class Builder {
|
class Builder {
|
||||||
var roomId: QueryStringValue = QueryStringValue.IsNotEmpty
|
var displayName: QueryStringValue = QueryStringValue.NoCondition
|
||||||
var displayName: QueryStringValue = QueryStringValue.IsNotEmpty
|
|
||||||
var canonicalAlias: QueryStringValue = QueryStringValue.NoCondition
|
var canonicalAlias: QueryStringValue = QueryStringValue.NoCondition
|
||||||
var memberships: List<Membership> = Membership.all()
|
var memberships: List<Membership> = Membership.all()
|
||||||
var roomCategoryFilter: RoomCategoryFilter? = RoomCategoryFilter.ALL
|
var roomCategoryFilter: RoomCategoryFilter? = null
|
||||||
var roomTagQueryFilter: RoomTagQueryFilter? = null
|
var roomTagQueryFilter: RoomTagQueryFilter? = null
|
||||||
var excludeType: List<String?>? = listOf(RoomType.SPACE)
|
var excludeType: List<String?>? = listOf(RoomType.SPACE)
|
||||||
var includeType: List<String?>? = null
|
var includeType: List<String?>? = null
|
||||||
var activeSpaceFilter: ActiveSpaceFilter = ActiveSpaceFilter.None
|
var spaceFilter: SpaceFilter? = null
|
||||||
var activeGroupId: String? = null
|
var activeGroupId: String? = null
|
||||||
|
|
||||||
fun build() = RoomSummaryQueryParams(
|
fun build() = RoomSummaryQueryParams(
|
||||||
roomId = roomId,
|
|
||||||
displayName = displayName,
|
displayName = displayName,
|
||||||
canonicalAlias = canonicalAlias,
|
canonicalAlias = canonicalAlias,
|
||||||
memberships = memberships,
|
memberships = memberships,
|
||||||
@ -77,7 +116,7 @@ data class RoomSummaryQueryParams(
|
|||||||
roomTagQueryFilter = roomTagQueryFilter,
|
roomTagQueryFilter = roomTagQueryFilter,
|
||||||
excludeType = excludeType,
|
excludeType = excludeType,
|
||||||
includeType = includeType,
|
includeType = includeType,
|
||||||
activeSpaceFilter = activeSpaceFilter,
|
spaceFilter = spaceFilter,
|
||||||
activeGroupId = activeGroupId
|
activeGroupId = activeGroupId
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.matrix.android.sdk.api.session.room.location
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationShareAggregatedSummary
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manage all location sharing related features.
|
||||||
|
*/
|
||||||
|
interface LocationSharingService {
|
||||||
|
fun getRunningLiveLocationShareSummaries(): LiveData<List<LiveLocationShareAggregatedSummary>>
|
||||||
|
}
|
@ -28,65 +28,200 @@ import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
|||||||
* It can be retrieved by [org.matrix.android.sdk.api.session.room.Room] and [org.matrix.android.sdk.api.session.room.RoomService]
|
* It can be retrieved by [org.matrix.android.sdk.api.session.room.Room] and [org.matrix.android.sdk.api.session.room.RoomService]
|
||||||
*/
|
*/
|
||||||
data class RoomSummary(
|
data class RoomSummary(
|
||||||
|
/**
|
||||||
|
* The roomId of the room.
|
||||||
|
*/
|
||||||
val roomId: String,
|
val roomId: String,
|
||||||
// Computed display name
|
/**
|
||||||
|
* Computed display name. The value of the state event `m.room.name` if not empty, else can be the value returned
|
||||||
|
* by [org.matrix.android.sdk.api.RoomDisplayNameFallbackProvider].
|
||||||
|
*/
|
||||||
val displayName: String = "",
|
val displayName: String = "",
|
||||||
|
/**
|
||||||
|
* The value of the live state event `m.room.name`.
|
||||||
|
*/
|
||||||
val name: String = "",
|
val name: String = "",
|
||||||
|
/**
|
||||||
|
* The value of the live state event `m.room.topic`.
|
||||||
|
*/
|
||||||
val topic: String = "",
|
val topic: String = "",
|
||||||
|
/**
|
||||||
|
* The value of the live state event `m.room.avatar`.
|
||||||
|
*/
|
||||||
val avatarUrl: String = "",
|
val avatarUrl: String = "",
|
||||||
|
/**
|
||||||
|
* The value of the live state event `m.room.canonical_alias`.
|
||||||
|
*/
|
||||||
val canonicalAlias: String? = null,
|
val canonicalAlias: String? = null,
|
||||||
|
/**
|
||||||
|
* The list of all the aliases of this room. Content of the live state event `m.room.aliases`.
|
||||||
|
*/
|
||||||
val aliases: List<String> = emptyList(),
|
val aliases: List<String> = emptyList(),
|
||||||
|
/**
|
||||||
|
* The value of the live state event `m.room.join_rules`.
|
||||||
|
*/
|
||||||
val joinRules: RoomJoinRules? = null,
|
val joinRules: RoomJoinRules? = null,
|
||||||
|
/**
|
||||||
|
* True is this room is referenced in the account data `m.direct`.
|
||||||
|
*/
|
||||||
val isDirect: Boolean = false,
|
val isDirect: Boolean = false,
|
||||||
|
/**
|
||||||
|
* If [isDirect] is true, this is the id of the first other member of this room.
|
||||||
|
*/
|
||||||
val directUserId: String? = null,
|
val directUserId: String? = null,
|
||||||
|
/**
|
||||||
|
* If [isDirect] is true, this it the presence of the first other member of this room.
|
||||||
|
*/
|
||||||
val directUserPresence: UserPresence? = null,
|
val directUserPresence: UserPresence? = null,
|
||||||
|
/**
|
||||||
|
* Number of members who have joined this room.
|
||||||
|
*/
|
||||||
val joinedMembersCount: Int? = 0,
|
val joinedMembersCount: Int? = 0,
|
||||||
|
/**
|
||||||
|
* Number of members who are invited to this room.
|
||||||
|
*/
|
||||||
val invitedMembersCount: Int? = 0,
|
val invitedMembersCount: Int? = 0,
|
||||||
|
/**
|
||||||
|
* Latest [TimelineEvent] which can be displayed in this room. Can be used in the room list.
|
||||||
|
*/
|
||||||
val latestPreviewableEvent: TimelineEvent? = null,
|
val latestPreviewableEvent: TimelineEvent? = null,
|
||||||
|
/**
|
||||||
|
* List of other member ids of this room.
|
||||||
|
*/
|
||||||
val otherMemberIds: List<String> = emptyList(),
|
val otherMemberIds: List<String> = emptyList(),
|
||||||
|
/**
|
||||||
|
* Number of unread message in this room.
|
||||||
|
*/
|
||||||
val notificationCount: Int = 0,
|
val notificationCount: Int = 0,
|
||||||
|
/**
|
||||||
|
* Number of unread and highlighted message in this room.
|
||||||
|
*/
|
||||||
val highlightCount: Int = 0,
|
val highlightCount: Int = 0,
|
||||||
|
/**
|
||||||
|
* True if this room has unread messages.
|
||||||
|
*/
|
||||||
val hasUnreadMessages: Boolean = false,
|
val hasUnreadMessages: Boolean = false,
|
||||||
|
/**
|
||||||
|
* List of tags in this room.
|
||||||
|
*/
|
||||||
val tags: List<RoomTag> = emptyList(),
|
val tags: List<RoomTag> = emptyList(),
|
||||||
|
/**
|
||||||
|
* Current user membership in this room.
|
||||||
|
*/
|
||||||
val membership: Membership = Membership.NONE,
|
val membership: Membership = Membership.NONE,
|
||||||
|
/**
|
||||||
|
* Versioning state of this room.
|
||||||
|
*/
|
||||||
val versioningState: VersioningState = VersioningState.NONE,
|
val versioningState: VersioningState = VersioningState.NONE,
|
||||||
|
/**
|
||||||
|
* Value of `m.fully_read` for this room.
|
||||||
|
*/
|
||||||
val readMarkerId: String? = null,
|
val readMarkerId: String? = null,
|
||||||
|
/**
|
||||||
|
* Message saved as draft for this room.
|
||||||
|
*/
|
||||||
val userDrafts: List<UserDraft> = emptyList(),
|
val userDrafts: List<UserDraft> = emptyList(),
|
||||||
|
/**
|
||||||
|
* True if this room is encrypted.
|
||||||
|
*/
|
||||||
val isEncrypted: Boolean,
|
val isEncrypted: Boolean,
|
||||||
|
/**
|
||||||
|
* Timestamp of the `m.room.encryption` state event.
|
||||||
|
*/
|
||||||
val encryptionEventTs: Long?,
|
val encryptionEventTs: Long?,
|
||||||
|
/**
|
||||||
|
* List of users who are currently typing on this room.
|
||||||
|
*/
|
||||||
val typingUsers: List<SenderInfo>,
|
val typingUsers: List<SenderInfo>,
|
||||||
|
/**
|
||||||
|
* UserId of the user who has invited the current user to this room.
|
||||||
|
*/
|
||||||
val inviterId: String? = null,
|
val inviterId: String? = null,
|
||||||
|
/**
|
||||||
|
* Breadcrumb index, util to sort rooms by last seen.
|
||||||
|
*/
|
||||||
val breadcrumbsIndex: Int = NOT_IN_BREADCRUMBS,
|
val breadcrumbsIndex: Int = NOT_IN_BREADCRUMBS,
|
||||||
|
/**
|
||||||
|
* The room encryption trust level.
|
||||||
|
* @see [RoomEncryptionTrustLevel]
|
||||||
|
*/
|
||||||
val roomEncryptionTrustLevel: RoomEncryptionTrustLevel? = null,
|
val roomEncryptionTrustLevel: RoomEncryptionTrustLevel? = null,
|
||||||
|
/**
|
||||||
|
* True if a message has not been sent in this room.
|
||||||
|
*/
|
||||||
val hasFailedSending: Boolean = false,
|
val hasFailedSending: Boolean = false,
|
||||||
|
/**
|
||||||
|
* The type of the room. Null for regular room.
|
||||||
|
* @see [RoomType]
|
||||||
|
*/
|
||||||
val roomType: String? = null,
|
val roomType: String? = null,
|
||||||
|
/**
|
||||||
|
* List of parent spaces.
|
||||||
|
*/
|
||||||
val spaceParents: List<SpaceParentInfo>? = null,
|
val spaceParents: List<SpaceParentInfo>? = null,
|
||||||
|
/**
|
||||||
|
* List of children space.
|
||||||
|
*/
|
||||||
val spaceChildren: List<SpaceChildInfo>? = null,
|
val spaceChildren: List<SpaceChildInfo>? = null,
|
||||||
|
/**
|
||||||
|
* List of all the space parents. Will be empty by default, you have to explicitly request it.
|
||||||
|
*/
|
||||||
|
val flattenParents: List<RoomSummary> = emptyList(),
|
||||||
|
/**
|
||||||
|
* List of all the space parent Ids.
|
||||||
|
*/
|
||||||
val flattenParentIds: List<String> = emptyList(),
|
val flattenParentIds: List<String> = emptyList(),
|
||||||
val roomEncryptionAlgorithm: RoomEncryptionAlgorithm? = null
|
/**
|
||||||
|
* Information about the encryption algorithm, if this room is encrypted.
|
||||||
|
*/
|
||||||
|
val roomEncryptionAlgorithm: RoomEncryptionAlgorithm? = null,
|
||||||
) {
|
) {
|
||||||
|
/**
|
||||||
|
* True if [versioningState] is not [VersioningState.NONE].
|
||||||
|
*/
|
||||||
val isVersioned: Boolean
|
val isVersioned: Boolean
|
||||||
get() = versioningState != VersioningState.NONE
|
get() = versioningState != VersioningState.NONE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if [notificationCount] is not `0`.
|
||||||
|
*/
|
||||||
val hasNewMessages: Boolean
|
val hasNewMessages: Boolean
|
||||||
get() = notificationCount != 0
|
get() = notificationCount != 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if the room has the tag `m.lowpriority`.
|
||||||
|
*/
|
||||||
val isLowPriority: Boolean
|
val isLowPriority: Boolean
|
||||||
get() = hasTag(RoomTag.ROOM_TAG_LOW_PRIORITY)
|
get() = hasTag(RoomTag.ROOM_TAG_LOW_PRIORITY)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if the room has the tag `m.favourite`.
|
||||||
|
*/
|
||||||
val isFavorite: Boolean
|
val isFavorite: Boolean
|
||||||
get() = hasTag(RoomTag.ROOM_TAG_FAVOURITE)
|
get() = hasTag(RoomTag.ROOM_TAG_FAVOURITE)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if [joinRules] is [RoomJoinRules.PUBLIC].
|
||||||
|
*/
|
||||||
val isPublic: Boolean
|
val isPublic: Boolean
|
||||||
get() = joinRules == RoomJoinRules.PUBLIC
|
get() = joinRules == RoomJoinRules.PUBLIC
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if the room has the provided [tag].
|
||||||
|
*/
|
||||||
fun hasTag(tag: String) = tags.any { it.name == tag }
|
fun hasTag(tag: String) = tags.any { it.name == tag }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if a 1-1 call can be started, i.e. the room has exactly 2 joined members.
|
||||||
|
*/
|
||||||
val canStartCall: Boolean
|
val canStartCall: Boolean
|
||||||
get() = joinedMembersCount == 2
|
get() = joinedMembersCount == 2
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
/**
|
||||||
|
* Constant to indicated that the room is not on the breadcrumbs.
|
||||||
|
* Used by [breadcrumbsIndex].
|
||||||
|
*/
|
||||||
const val NOT_IN_BREADCRUMBS = -1
|
const val NOT_IN_BREADCRUMBS = -1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,22 @@
|
|||||||
|
|
||||||
package org.matrix.android.sdk.api.session.room.model
|
package org.matrix.android.sdk.api.session.room.model
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum for the versioning state of a room.
|
||||||
|
*/
|
||||||
enum class VersioningState {
|
enum class VersioningState {
|
||||||
|
/**
|
||||||
|
* The room is not versioned.
|
||||||
|
*/
|
||||||
NONE,
|
NONE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The room has been upgraded, but the new room is not joined yet.
|
||||||
|
*/
|
||||||
UPGRADED_ROOM_NOT_JOINED,
|
UPGRADED_ROOM_NOT_JOINED,
|
||||||
UPGRADED_ROOM_JOINED
|
|
||||||
|
/**
|
||||||
|
* The room has been upgraded, and the new room has been joined.
|
||||||
|
*/
|
||||||
|
UPGRADED_ROOM_JOINED,
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,10 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocati
|
|||||||
* Aggregation info concerning a live location share.
|
* Aggregation info concerning a live location share.
|
||||||
*/
|
*/
|
||||||
data class LiveLocationShareAggregatedSummary(
|
data class LiveLocationShareAggregatedSummary(
|
||||||
|
val userId: String?,
|
||||||
|
/**
|
||||||
|
* Indicate whether the live is currently running.
|
||||||
|
*/
|
||||||
val isActive: Boolean?,
|
val isActive: Boolean?,
|
||||||
val endOfLiveTimestampMillis: Long?,
|
val endOfLiveTimestampMillis: Long?,
|
||||||
val lastLocationDataContent: MessageBeaconLocationDataContent?,
|
val lastLocationDataContent: MessageBeaconLocationDataContent?,
|
||||||
|
@ -17,27 +17,44 @@
|
|||||||
package org.matrix.android.sdk.api.session.room.send
|
package org.matrix.android.sdk.api.session.room.send
|
||||||
|
|
||||||
enum class SendState {
|
enum class SendState {
|
||||||
|
/**
|
||||||
|
* The state is unknown.
|
||||||
|
*/
|
||||||
UNKNOWN,
|
UNKNOWN,
|
||||||
|
|
||||||
// the event has not been sent
|
/**
|
||||||
|
* The event has not been sent.
|
||||||
|
*/
|
||||||
UNSENT,
|
UNSENT,
|
||||||
|
|
||||||
// the event is encrypting
|
/**
|
||||||
|
* The event is encrypting.
|
||||||
|
*/
|
||||||
ENCRYPTING,
|
ENCRYPTING,
|
||||||
|
|
||||||
// the event is currently sending
|
/**
|
||||||
|
* The event is currently sending.
|
||||||
|
*/
|
||||||
SENDING,
|
SENDING,
|
||||||
|
|
||||||
// the event has been sent
|
/**
|
||||||
|
* The event has been sent.
|
||||||
|
*/
|
||||||
SENT,
|
SENT,
|
||||||
|
|
||||||
// the event has been received from server
|
/**
|
||||||
|
* The event has been received from server.
|
||||||
|
*/
|
||||||
SYNCED,
|
SYNCED,
|
||||||
|
|
||||||
// The event failed to be sent
|
/**
|
||||||
|
* The event failed to be sent.
|
||||||
|
*/
|
||||||
UNDELIVERED,
|
UNDELIVERED,
|
||||||
|
|
||||||
// the event failed to be sent because some unknown devices have been found while encrypting it
|
/**
|
||||||
|
* The event failed to be sent because some unknown devices have been found while encrypting it.
|
||||||
|
*/
|
||||||
FAILED_UNKNOWN_DEVICES;
|
FAILED_UNKNOWN_DEVICES;
|
||||||
|
|
||||||
internal companion object {
|
internal companion object {
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.matrix.android.sdk.api.session.securestorage
|
||||||
|
|
||||||
|
data class KeyRef(
|
||||||
|
val keyId: String?,
|
||||||
|
val keySpec: SsssKeySpec?
|
||||||
|
)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user