mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-22 01:15:54 +03:00
Merge branch 'release/1.1.1'
This commit is contained in:
commit
bc81931773
450 changed files with 18176 additions and 16025 deletions
23
.github/dependabot.yml
vendored
Normal file
23
.github/dependabot.yml
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
# Updates for Github Actions used in the repo
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
# Updates for Gradle dependencies used in the app
|
||||
- package-ecosystem: gradle
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
open-pull-requests-limit: 200
|
||||
reviewers:
|
||||
- "bmarty"
|
||||
### ignore:
|
||||
### - dependency-name: com.squareup.okhttp3:logging-interceptor
|
||||
### versions: "> 3.12.10"
|
|
@ -31,6 +31,7 @@
|
|||
<w>signin</w>
|
||||
<w>signout</w>
|
||||
<w>signup</w>
|
||||
<w>snackbar</w>
|
||||
<w>ssss</w>
|
||||
<w>sygnal</w>
|
||||
<w>threepid</w>
|
||||
|
|
41
CHANGES.md
41
CHANGES.md
|
@ -1,3 +1,42 @@
|
|||
Changes in Element 1.1.1 (2021-XX-XX)
|
||||
===================================================
|
||||
|
||||
Features ✨:
|
||||
-
|
||||
|
||||
Improvements 🙌:
|
||||
- Allow non-HTTPS connections to homeservers on Tor (#2941)
|
||||
- Fetch homeserver type and version and display in a new setting screen and add info in rageshakes (#2831)
|
||||
- Improve initial sync performance - split into 2 transactions (#983)
|
||||
- PIP support for Jitsi call (#2418)
|
||||
- Add tooltip for room quick actions
|
||||
- Pre-share session keys when opening a room or start typing (#2771)
|
||||
- Sending is now queuing by room and not uniquely to the session
|
||||
- Improve Snackbar duration (#2929)
|
||||
- Improve sending message state (#2937)
|
||||
|
||||
Bugfix 🐛:
|
||||
- Try to fix crash about UrlPreview (#2640)
|
||||
- Be robust if Event.type is missing (#2946)
|
||||
- Snappier message send status
|
||||
- Fix MainActivity display (#2927)
|
||||
|
||||
Translations 🗣:
|
||||
- All string resources and translations have been moved to the application module. Weblate project for the SDK will be removed.
|
||||
|
||||
SDK API changes ⚠️:
|
||||
-
|
||||
|
||||
Build 🧱:
|
||||
- Update a lot of dependencies, with the help of dependabot.
|
||||
- Add a script to download and install APK from the CI
|
||||
|
||||
Test:
|
||||
-
|
||||
|
||||
Other changes:
|
||||
- Rework edition of event management
|
||||
|
||||
Changes in Element 1.1.0 (2021-02-19)
|
||||
===================================================
|
||||
|
||||
|
@ -1196,7 +1235,7 @@ Mode details here: https://medium.com/@RiotChat/introducing-the-riotx-beta-for-a
|
|||
=======================================================
|
||||
|
||||
|
||||
Changes in Element 1.X.X (2021-XX-XX)
|
||||
Changes in Element 1.1.X (2021-XX-XX)
|
||||
===================================================
|
||||
|
||||
Features ✨:
|
||||
|
|
|
@ -29,7 +29,7 @@ To create a new screen:
|
|||
- Then right click on the package, and select `New/New Vector/RiotX Feature`.
|
||||
- Follow the Wizard, especially replace `Main` by something more relevant to your feature.
|
||||
- Click on `Finish`.
|
||||
- Remaining steps are described as TODO in the generated files, or will be pointed out by the compilator, or at runtime :)
|
||||
- Remaining steps are described as TODO in the generated files, or will be pointed out by the compiler, or at runtime :)
|
||||
|
||||
Note that if the templates are modified, the only things to do is to restart Android Studio for the change to take effect.
|
||||
|
||||
|
|
|
@ -63,13 +63,13 @@ android {
|
|||
dependencies {
|
||||
implementation 'com.github.chrisbanes:PhotoView:2.1.4'
|
||||
|
||||
implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0'
|
||||
implementation 'io.reactivex.rxjava2:rxkotlin:2.4.0'
|
||||
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
implementation 'androidx.core:core-ktx:1.3.2'
|
||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||
implementation "androidx.recyclerview:recyclerview:1.1.0"
|
||||
implementation "androidx.recyclerview:recyclerview:1.2.0-beta02"
|
||||
|
||||
implementation 'com.google.android.material:material:1.2.1'
|
||||
implementation 'com.google.android.material:material:1.3.0'
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/design_default_color_primary">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/testPage"
|
||||
android:layout_centerInParent="true"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="1"
|
||||
android:textSize="80sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
|
||||
</RelativeLayout>
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
buildscript {
|
||||
// Ref: https://kotlinlang.org/releases.html
|
||||
ext.kotlin_version = '1.4.21'
|
||||
ext.kotlin_coroutines_version = "1.4.1"
|
||||
ext.kotlin_version = '1.4.31'
|
||||
ext.kotlin_coroutines_version = "1.4.2"
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
|
@ -15,8 +15,9 @@ buildscript {
|
|||
classpath 'com.android.tools.build:gradle:4.1.2'
|
||||
classpath 'com.google.gms:google-services:4.3.5'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.7.1'
|
||||
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.1.1'
|
||||
classpath 'com.google.android.gms:oss-licenses-plugin:0.10.2'
|
||||
classpath "com.likethesalad.android:string-reference:1.2.1"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
|
|
2
fastlane/metadata/android/ca/changelogs/40101000.txt
Normal file
2
fastlane/metadata/android/ca/changelogs/40101000.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
Canvis principals d'aquesta versió: millora de VoIP (trucades i videotrucades en xats personals) i correcció d'errors!
|
||||
Registre de canvis complet: https://github.com/vector-im/element-android/releases/tag/v1.1.0
|
|
@ -1,2 +1,2 @@
|
|||
Hlavní změny v této verzi: Náhled URL, nová klávesice s Emoji, nové možnosti nastavení místností a sníh na vánoce!
|
||||
Plné znění změn: https://github.com/vector-im/element-android/releases/tag/v1.0.12
|
||||
Plné znění změn: https://github.com/vector-im/element-android/releases/tag/v1.0.13
|
||||
|
|
2
fastlane/metadata/android/cs/changelogs/40100140.txt
Normal file
2
fastlane/metadata/android/cs/changelogs/40100140.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
Hlavní změny v této verzi: Úpravy práv místností, automatický tmavý/světlý vzhled a řada oprav chyb.
|
||||
Úplný záznam změn: https://github.com/vector-im/element-android/releases/tag/v1.0.14
|
2
fastlane/metadata/android/cs/changelogs/40100150.txt
Normal file
2
fastlane/metadata/android/cs/changelogs/40100150.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
Hlavní změny v této verzi: Podpora přihlášení v sociálních sítích.
|
||||
Úplný záznam změn: https://github.com/vector-im/element-android/releases/tag/v1.0.15
|
2
fastlane/metadata/android/cs/changelogs/40100160.txt
Normal file
2
fastlane/metadata/android/cs/changelogs/40100160.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
Hlavní změny v této verzi: Podpora přihlášení v sociálních sítích.
|
||||
Úplný záznam změn: https://github.com/vector-im/element-android/releases/tag/v1.0.15 a https://github.com/vector-im/element-android/releases/tag/v1.0.16
|
2
fastlane/metadata/android/cs/changelogs/40100170.txt
Normal file
2
fastlane/metadata/android/cs/changelogs/40100170.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
Hlavní změny v této verzi: Opravy chyb!
|
||||
Úplný záznam změn: https://github.com/vector-im/element-android/releases/tag/v1.0.17
|
2
fastlane/metadata/android/cs/changelogs/40101000.txt
Normal file
2
fastlane/metadata/android/cs/changelogs/40101000.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
Hlavní změny v této verzi: VoIP (audio a video hovory v DM), vylepšení a opravy chyb!
|
||||
Úplný záznam změn: https://github.com/vector-im/element-android/releases/tag/v1.1.0
|
|
@ -1,30 +1,30 @@
|
|||
Element je nový typ aplikace pro výměnu zpráv a kolaboraci, která:
|
||||
Element je nový typ aplikace pro výměnu zpráv a spolupráci, která:
|
||||
|
||||
1. Vám dá moc zachovat si soukromí
|
||||
2. Vás nechá komunikovat s kýmkoli v síti Matrix a dokonce dále integrací s aplikacemi jako Slack
|
||||
3. Vás ochrání před inzercí, těžbou dat a uzavřenými zahradami
|
||||
4. Vás zabezpečí šifrováním end-to-end s křížovým podepisováním pro ověření ostatních
|
||||
1. Vám dá kontrolu nad ochranou vašeho soukromí
|
||||
2. Umožní vám komunikovat s kýmkoli v síti Matrix a dokonce i mimo ni pomocí integrací s aplikacemi, jako je Slack
|
||||
3. Ochrání vás před inzercí, dataminingem a uzavřenými zahradami
|
||||
4. Zabezpečí vás end-to-end šifrováním s křížovým podpisem pro ověření ostatních
|
||||
|
||||
Element is completely different from other messaging and collaboration apps because it is decentralised and open source.
|
||||
Element je zcela odlišný od ostatních aplikací pro zasílání zpráv a spolupráci, protože je decentralizovaný a otevřený.
|
||||
|
||||
Element lets you self-host - or choose a host - so that you have privacy, ownership and control of your data and conversations. It gives you access to an open network; so you’re not just stuck speaking to other Element users only. And it is very secure.
|
||||
Element vám umožňuje použít vlastní domovský server - nebo si vybrat hostitele - abyste měli soukromí, vlastnictví a kontrolu nad svými daty a konverzacemi. Poskytuje vám přístup k otevřené síti; takže nejste zaseknuti jen při konverzaci s ostatními uživateli Elementu. A je velmi bezpečný.
|
||||
|
||||
Element is able to do all this because it operates on Matrix - the standard for open, decentralised communication.
|
||||
Element je toho všeho schopen, protože pracuje na Matrixu - standardu otevřené, decentralizované komunikace.
|
||||
|
||||
Element puts you in control by letting you choose who hosts your conversations. From the Element app, you can choose to host in different ways:
|
||||
Element vám dává kontrolu nad tím, že si můžete vybrat, kdo bude hostovat vaše konverzace. Z aplikace Element si můžete vybrat hostování různými způsoby:
|
||||
|
||||
1. Get a free account on the matrix.org public server hosted by the Matrix developers, or choose from thousands of public servers hosted by volunteers
|
||||
2. Self-host your account by running a server on your own hardware
|
||||
3. Sign up for an account on a custom server by simply subscribing to the Element Matrix Services hosting platform
|
||||
1. Získejte zdarma účet na veřejném serveru matrix.org hostovaném vývojáři Matrixu, nebo si vyberte z tisíců veřejných serverů hostovaných dobrovolníky
|
||||
2. Hostujte svůj účet spuštěním serveru na svém vlastním hardwaru
|
||||
3. Zaregistrujte si účet na vlastním serveru jednoduchým přihlášením k hostitelské platformě Element Matrix Services
|
||||
|
||||
<b>Why choose Element?</b>
|
||||
<b>Proč zvolit Element?</b>
|
||||
|
||||
<b>OWN YOUR DATA</b>: You decide where to keep your data and messages. You own it and control it, not some MEGACORP that mines your data or gives access to third parties.
|
||||
<b>VLASTNĚTE SVÁ DATA</b>: Vy rozhodnete, kde svá data a zprávy ponecháte. Vlastníte je a jsou pod vaší kontrolou, ne nějaký MEGACORP, který těží vaše data nebo poskytuje přístup třetím stranám.
|
||||
|
||||
<b>OPEN MESSAGING AND COLLABORATION</b>: You can chat with anyone else in the Matrix network, whether they’re using Element or another Matrix app, and even if they are using a different messaging system of the likes of Slack, IRC or XMPP.
|
||||
<b>ZPRÁVY A SPOLUPRÁCE</b>: Můžete chatovat s kýmkoli v síti Matrix, ať už používá Element nebo jinou aplikaci, a to i v případě, že používají jiný systém zasílání zpráv, jako je Slack, IRC nebo XMPP.
|
||||
|
||||
<b>SUPER-SECURE</b>: Real end-to-end encryption (only those in the conversation can decrypt messages), and cross-signing to verify the devices of conversation participants.
|
||||
<b>MAXIMÁLNĚ BEZPEČNÉ</b>: Skutečné šifrování typu end-to-end (pouze ti v konverzaci mohou dešifrovat zprávy) a křížové podepisování k ověření zařízení účastníků konverzace.
|
||||
|
||||
<b>COMPLETE COMMUNICATION</b>: Messaging, voice and video calls, file sharing, screen sharing and a whole bunch of integrations, bots and widgets. Build rooms, communities, stay in touch and get things done.
|
||||
<b>KOMPLETNÍ KOMUNIKACE</b>: Zprávy, hlasové hovory a videohovory, sdílení souborů, sdílení obrazovky a celá řada integrací, robotů a widgetů. Budujte místnosti, komunity, zůstaňte v kontaktu a spolupracujte.
|
||||
|
||||
<b>EVERYWHERE YOU ARE</b>: Stay in touch wherever you are with fully synchronised message history across all your devices and on the web at https://app.element.io.
|
||||
<b>KDEKOLIV JSTE</b>: Zůstaňte v kontaktu, ať jste kdekoli, s plně synchronizovanou historií zpráv na všech vašich zařízeních a na webu na adrese https://app.element.io.
|
||||
|
|
|
@ -1 +1 @@
|
|||
Zabezpečený decentralizovaný chat & VoIP. Uchovejte svá data v bezpečí.
|
||||
Zabezpečený decentralizovaný chat a VoIP. Uchovejte svá data v bezpečí.
|
||||
|
|
2
fastlane/metadata/android/de/changelogs/40101000.txt
Normal file
2
fastlane/metadata/android/de/changelogs/40101000.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
Hauptänderungen in dieser Version: VoIP-Verbesserung (Audio- und Video-Anrufe in Direktnachrichten) und Fehlerkorrekturen!
|
||||
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases/tag/v1.1.0
|
2
fastlane/metadata/android/en-US/changelogs/40101010.txt
Normal file
2
fastlane/metadata/android/en-US/changelogs/40101010.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
Main changes in this version: performance improvement and bug fixes!
|
||||
Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.1.1
|
2
fastlane/metadata/android/et/changelogs/40101000.txt
Normal file
2
fastlane/metadata/android/et/changelogs/40101000.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
Olulisemad muutused selles versioonis: Heli- ja videokõnede parandused otsevestluses ning üldised veaparandused!
|
||||
Muudatuste logi täismahus: https://github.com/vector-im/element-android/releases/tag/v1.1.0
|
|
@ -1,2 +1,2 @@
|
|||
Tärkeimmät muutokset tässä versiossa: URL-esikatselu, uusi emoji-näppäimistö, uudet huoneasetukset ja lunta jouluna!
|
||||
Tärkeimmät muutokset tässä versiossa: URL-esikatselu, uusi emoji-näppäimistö, uudet huoneasetukset ja lunta jouluksi!
|
||||
Täysi muutosloki: https://github.com/vector-im/element-android/releases/tag/v1.0.12
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
Tärkeimmät muutokset tässä versiossa: URL-esikatselu, uusi emoji-näppäimistö, uudet huoneasetukset ja lunta jouluna!
|
||||
Täysi muutosloki: https://github.com/vector-im/element-android/releases/tag/v1.0.12
|
||||
Tärkeimmät muutokset tässä versiossa: URL-esikatselu, uusi emoji-näppäimistö, uudet huoneasetukset ja lunta jouluksi!
|
||||
Täysi muutosloki: https://github.com/vector-im/element-android/releases/tag/v1.0.13
|
||||
|
|
2
fastlane/metadata/android/fi/changelogs/40100140.txt
Normal file
2
fastlane/metadata/android/fi/changelogs/40100140.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
Tärkeimmät muutokset tässä versiossa: Huoneoikeuksien muokkaus, automaattinen valoisa/tumma teema ja läjäpäin virheenkorjauksia.
|
||||
Täysi muutosloki: https://github.com/vector-im/element-android/releases/tag/v1.0.14
|
2
fastlane/metadata/android/fi/changelogs/40100150.txt
Normal file
2
fastlane/metadata/android/fi/changelogs/40100150.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
Tärkeimmät muutokset tässä versiossa: Social Login -tuki.
|
||||
Täysi muutosloki: https://github.com/vector-im/element-android/releases/tag/v1.0.15
|
2
fastlane/metadata/android/fi/changelogs/40100160.txt
Normal file
2
fastlane/metadata/android/fi/changelogs/40100160.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
Tärkeimmät muutokset tässä versiossa: Social Login -tuki.
|
||||
Täysi muutosloki: https://github.com/vector-im/element-android/releases/tag/v1.0.15 and https://github.com/vector-im/element-android/releases/tag/v1.0.16
|
2
fastlane/metadata/android/fi/changelogs/40100170.txt
Normal file
2
fastlane/metadata/android/fi/changelogs/40100170.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
Tärkeimmät muutokset tässä versiossa: Virheenkorjauksia!
|
||||
Täysi muutosloki: https://github.com/vector-im/element-android/releases/tag/v1.0.17
|
2
fastlane/metadata/android/pt-BR/changelogs/40100170.txt
Normal file
2
fastlane/metadata/android/pt-BR/changelogs/40100170.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
Principais mudanças nessa versão: correções de erros!
|
||||
Registro de todas as alterações: https://github.com/vector-im/element-android/releases/tag/v1.0.17
|
2
fastlane/metadata/android/ru/changelogs/40100170.txt
Normal file
2
fastlane/metadata/android/ru/changelogs/40100170.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
Основные изменения в этой версии: Исправлены ошибки!
|
||||
Полный список изменений: https://github.com/vector-im/element-android/releases/tag/v1.0.17
|
1
fastlane/metadata/android/si/title.txt
Normal file
1
fastlane/metadata/android/si/title.txt
Normal file
|
@ -0,0 +1 @@
|
|||
ඉලෙමන්ට් (මීට පෙර Riot.im)
|
2
fastlane/metadata/android/sv/changelogs/40100170.txt
Normal file
2
fastlane/metadata/android/sv/changelogs/40100170.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
Huvudsakliga ändringar i den här versionen: Buggfixar!
|
||||
Full ändringslogg: https://github.com/vector-im/element-android/releases/tag/v1.0.17
|
2
fastlane/metadata/android/sv/changelogs/40101000.txt
Normal file
2
fastlane/metadata/android/sv/changelogs/40101000.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
Huvudsakliga ändringar i den här versionen: Förbättringar för VoIP (ljud- och videosamtal i DM) och buggfixar!
|
||||
Full ändringslogg: https://github.com/vector-im/element-android/releases/tag/v1.1.0
|
2
fastlane/metadata/android/uk/changelogs/40101000.txt
Normal file
2
fastlane/metadata/android/uk/changelogs/40101000.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
Основні зміни в цій версії: поліпшення VoIP (аудіо та відео дзвінки в DM) та виправлення помилок!
|
||||
Повний журнал змін: https://github.com/vector-im/element-android/releases/tag/v1.1.0
|
|
@ -0,0 +1,2 @@
|
|||
此版本中的主要變動:錯誤修復!
|
||||
完整變更紀錄:https://github.com/vector-im/element-android/releases/tag/v1.0.17
|
|
@ -0,0 +1,2 @@
|
|||
此版本的主要變更:VoIP(直接訊息中的音訊與視訊通話)改善與錯誤修復!
|
||||
完整變更紀錄:https://github.com/vector-im/element-android/releases/tag/v1.1.0
|
5
gradle/wrapper/gradle-wrapper.properties
vendored
5
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,7 +1,6 @@
|
|||
#Fri Jan 29 18:05:42 CET 2021
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=1433372d903ffba27496f8d5af24265310d2da0d78bf6b4e5138831d4fe066e9
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-all.zip
|
||||
distributionSha256Sum=9af5c8e7e2cd1a3b0f694a4ac262b9f38c75262e74a9e8b5101af302a6beadd7
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
|
@ -36,7 +36,7 @@ android {
|
|||
dependencies {
|
||||
implementation project(":matrix-sdk-android")
|
||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||
implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0'
|
||||
implementation 'io.reactivex.rxjava2:rxkotlin:2.4.0'
|
||||
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-rx2:$kotlin_coroutines_version"
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ buildscript {
|
|||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath "io.realm:realm-gradle-plugin:10.1.2"
|
||||
classpath "io.realm:realm-gradle-plugin:10.3.1"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,9 +112,9 @@ dependencies {
|
|||
def lifecycle_version = '2.2.0'
|
||||
def arch_version = '2.1.0'
|
||||
def markwon_version = '3.1.0'
|
||||
def daggerVersion = '2.31'
|
||||
def work_version = '2.4.0'
|
||||
def retrofit_version = '2.6.2'
|
||||
def daggerVersion = '2.33'
|
||||
def work_version = '2.5.0'
|
||||
def retrofit_version = '2.9.0'
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
|
||||
|
@ -130,7 +130,7 @@ dependencies {
|
|||
implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
|
||||
implementation "com.squareup.retrofit2:converter-moshi:$retrofit_version"
|
||||
|
||||
implementation(platform("com.squareup.okhttp3:okhttp-bom:4.8.1"))
|
||||
implementation(platform("com.squareup.okhttp3:okhttp-bom:4.9.1"))
|
||||
implementation 'com.squareup.okhttp3:okhttp'
|
||||
implementation 'com.squareup.okhttp3:logging-interceptor'
|
||||
implementation 'com.squareup.okhttp3:okhttp-urlconnection'
|
||||
|
@ -141,11 +141,11 @@ dependencies {
|
|||
implementation "ru.noties.markwon:core:$markwon_version"
|
||||
|
||||
// Image
|
||||
implementation 'androidx.exifinterface:exifinterface:1.3.1'
|
||||
implementation 'androidx.exifinterface:exifinterface:1.3.2'
|
||||
|
||||
// Database
|
||||
implementation 'com.github.Zhuinden:realm-monarchy:0.7.1'
|
||||
kapt 'dk.ilios:realmfieldnameshelper:1.1.1'
|
||||
kapt 'dk.ilios:realmfieldnameshelper:2.0.0'
|
||||
|
||||
// Work
|
||||
implementation "androidx.work:work-runtime-ktx:$work_version"
|
||||
|
@ -155,7 +155,7 @@ dependencies {
|
|||
implementation "io.arrow-kt:arrow-instances-core:$arrow_version"
|
||||
|
||||
// olm lib is now hosted by jitpack: https://jitpack.io/#org.matrix.gitlab.matrix-org/olm
|
||||
implementation 'org.matrix.gitlab.matrix-org:olm:3.1.2'
|
||||
implementation 'org.matrix.gitlab.matrix-org:olm:3.2.2'
|
||||
|
||||
// DI
|
||||
implementation "com.google.dagger:dagger:$daggerVersion"
|
||||
|
@ -166,14 +166,14 @@ dependencies {
|
|||
implementation 'com.facebook.stetho:stetho-okhttp3:1.5.1'
|
||||
|
||||
// Phone number https://github.com/google/libphonenumber
|
||||
implementation 'com.googlecode.libphonenumber:libphonenumber:8.10.23'
|
||||
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.19'
|
||||
|
||||
testImplementation 'junit:junit:4.13'
|
||||
testImplementation 'org.robolectric:robolectric:4.3'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
testImplementation 'org.robolectric:robolectric:4.5.1'
|
||||
//testImplementation 'org.robolectric:shadows-support-v4:3.0'
|
||||
// Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281
|
||||
testImplementation 'io.mockk:mockk:1.9.2.kotlin12'
|
||||
testImplementation 'org.amshove.kluent:kluent-android:1.61'
|
||||
testImplementation 'io.mockk:mockk:1.10.6'
|
||||
testImplementation 'org.amshove.kluent:kluent-android:1.65'
|
||||
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
|
||||
// Plant Timber tree for test
|
||||
testImplementation 'net.lachlanmckee:timber-junit-rule:1.0.1'
|
||||
|
@ -186,7 +186,7 @@ dependencies {
|
|||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
||||
androidTestImplementation 'org.amshove.kluent:kluent-android:1.61'
|
||||
// Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281
|
||||
androidTestImplementation 'io.mockk:mockk-android:1.9.2.kotlin12'
|
||||
androidTestImplementation 'io.mockk:mockk-android:1.10.6'
|
||||
androidTestImplementation "androidx.arch.core:core-testing:$arch_version"
|
||||
androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
|
||||
// Plant Timber tree for test
|
||||
|
|
|
@ -19,6 +19,15 @@ package org.matrix.android.sdk.common
|
|||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import androidx.lifecycle.Observer
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withTimeout
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNotNull
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.matrix.android.sdk.api.Matrix
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.MatrixConfiguration
|
||||
|
@ -34,15 +43,6 @@ 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.TimelineSettings
|
||||
import org.matrix.android.sdk.api.session.sync.SyncState
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withTimeout
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNotNull
|
||||
import org.junit.Assert.assertTrue
|
||||
import java.util.ArrayList
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.CountDownLatch
|
||||
|
@ -59,7 +59,13 @@ class CommonTestHelper(context: Context) {
|
|||
fun getTestInterceptor(session: Session): MockOkHttpInterceptor? = TestNetworkModule.interceptorForSession(session.sessionId) as? MockOkHttpInterceptor
|
||||
|
||||
init {
|
||||
Matrix.initialize(context, MatrixConfiguration("TestFlavor"))
|
||||
Matrix.initialize(
|
||||
context,
|
||||
MatrixConfiguration(
|
||||
applicationFlavor = "TestFlavor",
|
||||
roomDisplayNameFallbackProvider = TestRoomDisplayNameFallbackProvider()
|
||||
)
|
||||
)
|
||||
matrix = Matrix.getInstance(context)
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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.common
|
||||
|
||||
import org.matrix.android.sdk.api.RoomDisplayNameFallbackProvider
|
||||
|
||||
class TestRoomDisplayNameFallbackProvider() : RoomDisplayNameFallbackProvider {
|
||||
|
||||
override fun getNameForRoomInvite() =
|
||||
"Room invite"
|
||||
|
||||
override fun getNameForEmptyRoom() =
|
||||
"Empty room"
|
||||
|
||||
override fun getNameFor2members(name1: String?, name2: String?) =
|
||||
"$name1 and $name2"
|
||||
|
||||
override fun getNameFor3members(name1: String?, name2: String?, name3: String?) =
|
||||
"$name1, $name2 and $name3"
|
||||
|
||||
override fun getNameFor4members(name1: String?, name2: String?, name3: String?, name4: String?) =
|
||||
"$name1, $name2, $name3 and $name4"
|
||||
|
||||
override fun getNameFor4membersAndMore(name1: String?, name2: String?, name3: String?, remainingCount: Int) =
|
||||
"$name1, $name2, $name3 and $remainingCount others"
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright 2020 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 android.util.Log
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
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.EventType
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.common.CommonTestHelper
|
||||
import org.matrix.android.sdk.common.CryptoTestHelper
|
||||
import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent
|
||||
import org.matrix.android.sdk.internal.crypto.model.event.RoomKeyContent
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNotNull
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@FixMethodOrder(MethodSorters.JVM)
|
||||
class PreShareKeysTest : InstrumentedTest {
|
||||
|
||||
private val mTestHelper = CommonTestHelper(context())
|
||||
private val mCryptoTestHelper = CryptoTestHelper(mTestHelper)
|
||||
|
||||
@Test
|
||||
fun ensure_outbound_session_happy_path() {
|
||||
val testData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
|
||||
val e2eRoomID = testData.roomId
|
||||
val aliceSession = testData.firstSession
|
||||
val bobSession = testData.secondSession!!
|
||||
|
||||
// clear any outbound session
|
||||
aliceSession.cryptoService().discardOutboundSession(e2eRoomID)
|
||||
|
||||
val preShareCount = bobSession.cryptoService().getGossipingEvents().count {
|
||||
it.senderId == aliceSession.myUserId
|
||||
&& it.getClearType() == EventType.ROOM_KEY
|
||||
}
|
||||
|
||||
assertEquals(0, preShareCount, "Bob should not have receive any key from alice at this point")
|
||||
Log.d("#Test", "Room Key Received from alice $preShareCount")
|
||||
|
||||
// Force presharing of new outbound key
|
||||
mTestHelper.doSync<Unit> {
|
||||
aliceSession.cryptoService().prepareToEncrypt(e2eRoomID, it)
|
||||
}
|
||||
|
||||
mTestHelper.waitWithLatch { latch ->
|
||||
mTestHelper.retryPeriodicallyWithLatch(latch) {
|
||||
val newGossipCount = bobSession.cryptoService().getGossipingEvents().count {
|
||||
it.senderId == aliceSession.myUserId
|
||||
&& it.getClearType() == EventType.ROOM_KEY
|
||||
}
|
||||
newGossipCount > preShareCount
|
||||
}
|
||||
}
|
||||
|
||||
val latest = bobSession.cryptoService().getGossipingEvents().lastOrNull {
|
||||
it.senderId == aliceSession.myUserId
|
||||
&& it.getClearType() == EventType.ROOM_KEY
|
||||
}
|
||||
|
||||
val content = latest?.getClearContent().toModel<RoomKeyContent>()
|
||||
assertNotNull(content, "Bob should have received and decrypted a room key event from alice")
|
||||
assertEquals(e2eRoomID, content.roomId, "Wrong room")
|
||||
val megolmSessionId = content.sessionId!!
|
||||
|
||||
val sharedIndex = aliceSession.cryptoService().getSharedWithInfo(e2eRoomID, megolmSessionId)
|
||||
.getObject(bobSession.myUserId, bobSession.sessionParams.deviceId)
|
||||
|
||||
assertEquals(0, sharedIndex, "The session received by bob should match what alice sent")
|
||||
|
||||
// Just send a real message as test
|
||||
val sentEvent = mTestHelper.sendTextMessage(aliceSession.getRoom(e2eRoomID)!!, "Allo", 1).first()
|
||||
|
||||
assertEquals(megolmSessionId, sentEvent.root.content.toModel<EncryptedEventContent>()?.sessionId, "Unexpected megolm session")
|
||||
mTestHelper.waitWithLatch { latch ->
|
||||
mTestHelper.retryPeriodicallyWithLatch(latch) {
|
||||
bobSession.getRoom(e2eRoomID)?.getTimeLineEvent(sentEvent.eventId)?.root?.getClearType() == EventType.MESSAGE
|
||||
}
|
||||
}
|
||||
|
||||
mTestHelper.signOutAndClose(aliceSession)
|
||||
mTestHelper.signOutAndClose(bobSession)
|
||||
}
|
||||
}
|
|
@ -51,7 +51,7 @@ class WithHeldTests : InstrumentedTest {
|
|||
// =============================
|
||||
|
||||
val aliceSession = mTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
|
||||
val bobSession = mTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
|
||||
val bobSession = mTestHelper.createAccount(TestConstants.USER_BOB, SessionTestParams(true))
|
||||
|
||||
// Initialize cross signing on both
|
||||
mCryptoTestHelper.initializeCrossSigning(aliceSession)
|
||||
|
|
|
@ -39,7 +39,11 @@ data class MatrixConfiguration(
|
|||
/**
|
||||
* True to advertise support for call transfers to other parties on Matrix calls.
|
||||
*/
|
||||
val supportsCallTransfer: Boolean = false
|
||||
val supportsCallTransfer: Boolean = false,
|
||||
/**
|
||||
* RoomDisplayNameFallbackProvider to provide default room display name.
|
||||
*/
|
||||
val roomDisplayNameFallbackProvider: RoomDisplayNameFallbackProvider
|
||||
) {
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* 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
|
||||
|
||||
interface RoomDisplayNameFallbackProvider {
|
||||
fun getNameForRoomInvite(): String
|
||||
fun getNameForEmptyRoom(): String
|
||||
fun getNameFor2members(name1: String?, name2: String?): String
|
||||
fun getNameFor3members(name1: String?, name2: String?, name3: String?): String
|
||||
fun getNameFor4members(name1: String?, name2: String?, name3: String?, name4: String?): String
|
||||
fun getNameFor4membersAndMore(name1: String?, name2: String?, name3: String?, remainingCount: Int): String
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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.crypto
|
||||
|
||||
enum class VerificationState {
|
||||
REQUEST,
|
||||
WAITING,
|
||||
CANCELED_BY_ME,
|
||||
CANCELED_BY_OTHER,
|
||||
DONE
|
||||
}
|
||||
|
||||
fun VerificationState.isCanceled(): Boolean {
|
||||
return this == VerificationState.CANCELED_BY_ME || this == VerificationState.CANCELED_BY_OTHER
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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.federation
|
||||
|
||||
interface FederationService {
|
||||
/**
|
||||
* Get information about the homeserver
|
||||
*/
|
||||
suspend fun getFederationVersion(): FederationVersion
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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.federation
|
||||
|
||||
/**
|
||||
* Ref: https://matrix.org/docs/spec/server_server/latest#get-matrix-federation-v1-version
|
||||
*/
|
||||
data class FederationVersion(
|
||||
/**
|
||||
* Arbitrary name that identify this implementation.
|
||||
*/
|
||||
val name: String?,
|
||||
/**
|
||||
* Version of this implementation. The version format depends on the implementation.
|
||||
*/
|
||||
val version: String?
|
||||
)
|
|
@ -21,6 +21,7 @@ import androidx.lifecycle.LiveData
|
|||
import okhttp3.OkHttpClient
|
||||
import org.matrix.android.sdk.api.auth.data.SessionParams
|
||||
import org.matrix.android.sdk.api.failure.GlobalError
|
||||
import org.matrix.android.sdk.api.federation.FederationService
|
||||
import org.matrix.android.sdk.api.pushrules.PushRuleService
|
||||
import org.matrix.android.sdk.api.session.account.AccountService
|
||||
import org.matrix.android.sdk.api.session.accountdata.AccountDataService
|
||||
|
@ -34,6 +35,7 @@ import org.matrix.android.sdk.api.session.file.FileService
|
|||
import org.matrix.android.sdk.api.session.group.GroupService
|
||||
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilitiesService
|
||||
import org.matrix.android.sdk.api.session.identity.IdentityService
|
||||
import org.matrix.android.sdk.api.session.initsync.InitialSyncProgressService
|
||||
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService
|
||||
import org.matrix.android.sdk.api.session.media.MediaService
|
||||
import org.matrix.android.sdk.api.session.permalinks.PermalinkService
|
||||
|
@ -213,6 +215,11 @@ interface Session :
|
|||
*/
|
||||
fun searchService(): SearchService
|
||||
|
||||
/**
|
||||
* Returns the federation service associated with the session
|
||||
*/
|
||||
fun federationService(): FederationService
|
||||
|
||||
/**
|
||||
* Returns the third party service associated with the session
|
||||
*/
|
||||
|
|
|
@ -156,4 +156,10 @@ interface CryptoService {
|
|||
fun getWithHeldMegolmSession(roomId: String, sessionId: String): RoomKeyWithHeldContent?
|
||||
|
||||
fun logDbUsageInfo()
|
||||
|
||||
/**
|
||||
* Perform any background tasks that can be done before a message is ready to
|
||||
* send, in order to speed up sending of the message.
|
||||
*/
|
||||
fun prepareToEncrypt(roomId: String, callback: MatrixCallback<Unit>)
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ inline fun <reified T> T.toContent(): Content {
|
|||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class Event(
|
||||
@Json(name = "type") val type: String,
|
||||
@Json(name = "type") val type: String? = null,
|
||||
@Json(name = "event_id") val eventId: String? = null,
|
||||
@Json(name = "content") val content: Content? = null,
|
||||
@Json(name = "prev_content") val prevContent: Content? = null,
|
||||
|
@ -98,6 +98,19 @@ data class Event(
|
|||
@Transient
|
||||
var ageLocalTs: Long? = null
|
||||
|
||||
/**
|
||||
* Copy all fields, including transient fields
|
||||
*/
|
||||
fun copyAll(): Event {
|
||||
return copy().also {
|
||||
it.mxDecryptionResult = mxDecryptionResult
|
||||
it.mCryptoError = mCryptoError
|
||||
it.mCryptoErrorReason = mCryptoErrorReason
|
||||
it.sendState = sendState
|
||||
it.ageLocalTs = ageLocalTs
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if event is a state event.
|
||||
* @return true if event is state event.
|
||||
|
@ -135,7 +148,7 @@ data class Event(
|
|||
* @return the event type
|
||||
*/
|
||||
fun getClearType(): String {
|
||||
return mxDecryptionResult?.payload?.get("type")?.toString() ?: type
|
||||
return mxDecryptionResult?.payload?.get("type")?.toString() ?: type ?: EventType.MISSING_TYPE
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,6 +20,8 @@ package org.matrix.android.sdk.api.session.events.model
|
|||
* Constants defining known event types from Matrix specifications.
|
||||
*/
|
||||
object EventType {
|
||||
// Used when the type is missing, which should not happen
|
||||
const val MISSING_TYPE = "org.matrix.android.sdk.missing_type"
|
||||
|
||||
const val PRESENCE = "m.presence"
|
||||
const val MESSAGE = "m.room.message"
|
||||
|
|
|
@ -21,6 +21,11 @@ package org.matrix.android.sdk.api.session.homeserver
|
|||
*/
|
||||
interface HomeServerCapabilitiesService {
|
||||
|
||||
/**
|
||||
* Force a refresh of the stored data
|
||||
*/
|
||||
suspend fun refreshHomeServerCapabilities()
|
||||
|
||||
/**
|
||||
* Get the HomeServer capabilities
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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.session.initsync
|
||||
|
||||
enum class InitSyncStep {
|
||||
ServerComputing,
|
||||
Downloading,
|
||||
ImportingAccount,
|
||||
ImportingAccountCrypto,
|
||||
ImportingAccountRoom,
|
||||
ImportingAccountGroups,
|
||||
ImportingAccountData,
|
||||
ImportingAccountJoinedRooms,
|
||||
ImportingAccountInvitedRooms,
|
||||
ImportingAccountLeftRooms
|
||||
}
|
|
@ -13,9 +13,8 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.matrix.android.sdk.api.session
|
||||
package org.matrix.android.sdk.api.session.initsync
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.lifecycle.LiveData
|
||||
|
||||
interface InitialSyncProgressService {
|
||||
|
@ -25,7 +24,7 @@ interface InitialSyncProgressService {
|
|||
sealed class Status {
|
||||
object Idle : Status()
|
||||
data class Progressing(
|
||||
@StringRes val statusText: Int,
|
||||
val initSyncStep: InitSyncStep,
|
||||
val percentProgress: Int = 0
|
||||
) : Status()
|
||||
}
|
|
@ -16,11 +16,9 @@
|
|||
|
||||
package org.matrix.android.sdk.api.session.room
|
||||
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
|
||||
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsParams
|
||||
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsResponse
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
|
||||
/**
|
||||
* This interface defines methods to get and join public rooms. It's implemented at the session level.
|
||||
|
@ -30,9 +28,8 @@ interface RoomDirectoryService {
|
|||
/**
|
||||
* Get rooms from directory
|
||||
*/
|
||||
fun getPublicRooms(server: String?,
|
||||
publicRoomsParams: PublicRoomsParams,
|
||||
callback: MatrixCallback<PublicRoomsResponse>): Cancelable
|
||||
suspend fun getPublicRooms(server: String?,
|
||||
publicRoomsParams: PublicRoomsParams): PublicRoomsResponse
|
||||
|
||||
/**
|
||||
* Get the visibility of a room in the directory
|
||||
|
|
|
@ -30,4 +30,10 @@ interface RoomCryptoService {
|
|||
* Enable encryption of the room
|
||||
*/
|
||||
suspend fun enableEncryption(algorithm: String = MXCRYPTO_ALGORITHM_MEGOLM)
|
||||
|
||||
/**
|
||||
* Ensures all members of the room are loaded and outbound session keys are shared.
|
||||
* If this method is not called, CryptoService will ensure it before sending events.
|
||||
*/
|
||||
suspend fun prepareToEncrypt()
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ package org.matrix.android.sdk.api.session.room.model
|
|||
import org.matrix.android.sdk.api.session.events.model.Content
|
||||
|
||||
data class EditAggregatedSummary(
|
||||
val aggregatedContent: Content? = null,
|
||||
val latestContent: Content? = null,
|
||||
// The list of the eventIDs used to build the summary (might be out of sync if chunked received from message chunk)
|
||||
val sourceEvents: List<String>,
|
||||
val localEchos: List<String>,
|
||||
|
|
|
@ -17,7 +17,7 @@ package org.matrix.android.sdk.api.session.room.model
|
|||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import org.matrix.android.sdk.internal.session.room.VerificationState
|
||||
import org.matrix.android.sdk.api.crypto.VerificationState
|
||||
|
||||
/**
|
||||
* Contains an aggregated summary info of the references.
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
package org.matrix.android.sdk.api.session.room.model.relation
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.room.model.EventAnnotationsSummary
|
||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||
|
@ -67,11 +66,11 @@ interface RelationService {
|
|||
|
||||
/**
|
||||
* Edit a text message body. Limited to "m.text" contentType
|
||||
* @param targetEventId The event to edit
|
||||
* @param targetEvent The event to edit
|
||||
* @param newBodyText The edited body
|
||||
* @param compatibilityBodyText The text that will appear on clients that don't support yet edition
|
||||
*/
|
||||
fun editTextMessage(targetEventId: String,
|
||||
fun editTextMessage(targetEvent: TimelineEvent,
|
||||
msgType: String,
|
||||
newBodyText: CharSequence,
|
||||
newBodyAutoMarkdown: Boolean,
|
||||
|
@ -92,8 +91,11 @@ interface RelationService {
|
|||
|
||||
/**
|
||||
* Get the edit history of the given event
|
||||
* The return list will contain the original event and all the editions of this event, done by the
|
||||
* same sender, sorted in the reverse order (so the original event is the latest element, and the
|
||||
* latest edition is the first element of the list)
|
||||
*/
|
||||
fun fetchEditHistory(eventId: String, callback: MatrixCallback<List<Event>>)
|
||||
suspend fun fetchEditHistory(eventId: String): List<Event>
|
||||
|
||||
/**
|
||||
* Reply to an event in the timeline (must be in same room)
|
||||
|
|
|
@ -17,14 +17,11 @@
|
|||
|
||||
package org.matrix.android.sdk.api.session.room.powerlevels
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import org.matrix.android.sdk.R
|
||||
|
||||
sealed class Role(open val value: Int, @StringRes val res: Int) : Comparable<Role> {
|
||||
object Admin : Role(100, R.string.power_level_admin)
|
||||
object Moderator : Role(50, R.string.power_level_moderator)
|
||||
object Default : Role(0, R.string.power_level_default)
|
||||
data class Custom(override val value: Int) : Role(value, R.string.power_level_custom)
|
||||
sealed class Role(open val value: Int) : Comparable<Role> {
|
||||
object Admin : Role(100)
|
||||
object Moderator : Role(50)
|
||||
object Default : Role(0)
|
||||
data class Custom(override val value: Int) : Role(value)
|
||||
|
||||
override fun compareTo(other: Role): Int {
|
||||
return value.compareTo(other.value)
|
||||
|
|
|
@ -132,4 +132,9 @@ interface SendService {
|
|||
* Resend all failed messages one by one (and keep order)
|
||||
*/
|
||||
fun resendAllFailedMessages()
|
||||
|
||||
/**
|
||||
* Cancel all failed messages
|
||||
*/
|
||||
fun cancelAllFailedMessages()
|
||||
}
|
||||
|
|
|
@ -38,6 +38,9 @@ import org.matrix.android.sdk.api.util.ContentUtils.extractUsefulTextFromReply
|
|||
*/
|
||||
data class TimelineEvent(
|
||||
val root: Event,
|
||||
/**
|
||||
* Uniquely identify an event, computed locally by the sdk
|
||||
*/
|
||||
val localId: Long,
|
||||
val eventId: String,
|
||||
val displayIndex: Int,
|
||||
|
@ -123,8 +126,7 @@ fun TimelineEvent.getLastMessageContent(): MessageContent? {
|
|||
return if (root.getClearType() == EventType.STICKER) {
|
||||
root.getClearContent().toModel<MessageStickerContent>()
|
||||
} else {
|
||||
annotations?.editSummary?.aggregatedContent?.toModel()
|
||||
?: root.getClearContent().toModel()
|
||||
(annotations?.editSummary?.latestContent ?: root.getClearContent()).toModel()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,9 +36,23 @@ interface TimelineService {
|
|||
*/
|
||||
fun createTimeline(eventId: String?, settings: TimelineSettings): Timeline
|
||||
|
||||
/**
|
||||
* Returns a snapshot of TimelineEvent event with eventId.
|
||||
* At the opposite of getTimeLineEventLive which will be updated when local echo event is synced, it will return null in this case.
|
||||
* @param eventId the eventId to get the TimelineEvent
|
||||
*/
|
||||
fun getTimeLineEvent(eventId: String): TimelineEvent?
|
||||
|
||||
/**
|
||||
* Creates a LiveData of Optional TimelineEvent event with eventId.
|
||||
* If the eventId is a local echo eventId, it will make the LiveData be updated with the synced TimelineEvent when coming through the sync.
|
||||
* In this case, makes sure to use the new synced eventId from the TimelineEvent class if you want to interact, as the local echo is removed from the SDK.
|
||||
* @param eventId the eventId to listen for TimelineEvent
|
||||
*/
|
||||
fun getTimeLineEventLive(eventId: String): LiveData<Optional<TimelineEvent>>
|
||||
|
||||
/**
|
||||
* Returns a snapshot list of TimelineEvent with EventType.MESSAGE and MessageType.MSGTYPE_IMAGE or MessageType.MSGTYPE_VIDEO.
|
||||
*/
|
||||
fun getAttachmentMessages(): List<TimelineEvent>
|
||||
}
|
||||
|
|
|
@ -22,9 +22,9 @@ interface FilterService {
|
|||
NoFilter,
|
||||
|
||||
/**
|
||||
* Filter for Riot, will include only known event type
|
||||
* Filter for Element, will include only known event type
|
||||
*/
|
||||
RiotFilter
|
||||
ElementFilter
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -53,6 +53,7 @@ import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
|
|||
import org.matrix.android.sdk.internal.crypto.actions.MegolmSessionDataImporter
|
||||
import org.matrix.android.sdk.internal.crypto.actions.SetDeviceVerificationAction
|
||||
import org.matrix.android.sdk.internal.crypto.algorithms.IMXEncrypting
|
||||
import org.matrix.android.sdk.internal.crypto.algorithms.IMXGroupEncryption
|
||||
import org.matrix.android.sdk.internal.crypto.algorithms.IMXWithHeldExtension
|
||||
import org.matrix.android.sdk.internal.crypto.algorithms.megolm.MXMegolmEncryptionFactory
|
||||
import org.matrix.android.sdk.internal.crypto.algorithms.olm.MXOlmEncryptionFactory
|
||||
|
@ -97,7 +98,6 @@ import org.matrix.olm.OlmManager
|
|||
import timber.log.Timber
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import javax.inject.Inject
|
||||
import kotlin.jvm.Throws
|
||||
import kotlin.math.max
|
||||
|
||||
/**
|
||||
|
@ -667,7 +667,12 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
|
||||
override fun discardOutboundSession(roomId: String) {
|
||||
cryptoCoroutineScope.launch(coroutineDispatchers.crypto) {
|
||||
roomEncryptorsStore.get(roomId)?.discardSessionKey()
|
||||
val roomEncryptor = roomEncryptorsStore.get(roomId)
|
||||
if (roomEncryptor is IMXGroupEncryption) {
|
||||
roomEncryptor.discardSessionKey()
|
||||
} else {
|
||||
Timber.e("## CRYPTO | discardOutboundSession() for:$roomId: Unable to handle IMXGroupEncryption")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1290,6 +1295,43 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
cryptoStore.logDbUsageInfo()
|
||||
}
|
||||
|
||||
override fun prepareToEncrypt(roomId: String, callback: MatrixCallback<Unit>) {
|
||||
cryptoCoroutineScope.launch(coroutineDispatchers.crypto) {
|
||||
Timber.d("## CRYPTO | prepareToEncrypt() : Check room members up to date")
|
||||
// Ensure to load all room members
|
||||
try {
|
||||
loadRoomMembersTask.execute(LoadRoomMembersTask.Params(roomId))
|
||||
} catch (failure: Throwable) {
|
||||
Timber.e("## CRYPTO | prepareToEncrypt() : Failed to load room members")
|
||||
callback.onFailure(failure)
|
||||
return@launch
|
||||
}
|
||||
|
||||
val userIds = getRoomUserIds(roomId)
|
||||
val alg = roomEncryptorsStore.get(roomId)
|
||||
?: getEncryptionAlgorithm(roomId)
|
||||
?.let { setEncryptionInRoom(roomId, it, false, userIds) }
|
||||
?.let { roomEncryptorsStore.get(roomId) }
|
||||
|
||||
if (alg == null) {
|
||||
val reason = String.format(MXCryptoError.UNABLE_TO_ENCRYPT_REASON, MXCryptoError.NO_MORE_ALGORITHM_REASON)
|
||||
Timber.e("## CRYPTO | prepareToEncrypt() : $reason")
|
||||
callback.onFailure(IllegalArgumentException("Missing algorithm"))
|
||||
return@launch
|
||||
}
|
||||
|
||||
runCatching {
|
||||
(alg as? IMXGroupEncryption)?.preshareKey(userIds)
|
||||
}.fold(
|
||||
{ callback.onSuccess(Unit) },
|
||||
{
|
||||
Timber.e("## CRYPTO | prepareToEncrypt() failed.")
|
||||
callback.onFailure(it)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/* ==========================================================================================
|
||||
* For test only
|
||||
* ========================================================================================== */
|
||||
|
|
|
@ -105,7 +105,7 @@ internal class EventDecryptor @Inject constructor(
|
|||
try {
|
||||
return alg.decryptEvent(event, timeline)
|
||||
} catch (mxCryptoError: MXCryptoError) {
|
||||
Timber.d("## CRYPTO | internalDecryptEvent : Failed to decrypt ${event.eventId} reason: $mxCryptoError")
|
||||
Timber.v("## CRYPTO | internalDecryptEvent : Failed to decrypt ${event.eventId} reason: $mxCryptoError")
|
||||
if (algorithm == MXCRYPTO_ALGORITHM_OLM) {
|
||||
if (mxCryptoError is MXCryptoError.Base
|
||||
&& mxCryptoError.errorType == MXCryptoError.ErrorType.BAD_ENCRYPTED_MESSAGE) {
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.matrix.android.sdk.api.session.crypto.keyshare.GossipingRequestListen
|
|||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.internal.crypto.algorithms.IMXGroupEncryption
|
||||
import org.matrix.android.sdk.internal.crypto.crosssigning.toBase64NoPadding
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.util.extractCurveKeyFromRecoveryKey
|
||||
import org.matrix.android.sdk.internal.crypto.model.rest.GossipingDefaultContent
|
||||
|
@ -290,6 +291,7 @@ internal class IncomingGossipingRequestManager @Inject constructor(
|
|||
.also { cryptoStore.updateGossipingRequestState(request, GossipingRequestState.REJECTED) }
|
||||
|
||||
cryptoCoroutineScope.launch(coroutineDispatchers.crypto) {
|
||||
if (roomEncryptor is IMXGroupEncryption) {
|
||||
val isSuccess = roomEncryptor.reshareKey(sessionId, userId, deviceId, senderKey)
|
||||
|
||||
if (isSuccess) {
|
||||
|
@ -297,6 +299,9 @@ internal class IncomingGossipingRequestManager @Inject constructor(
|
|||
} else {
|
||||
cryptoStore.updateGossipingRequestState(request, GossipingRequestState.UNABLE_TO_PROCESS)
|
||||
}
|
||||
} else {
|
||||
Timber.e("## CRYPTO | handleKeyRequestFromOtherUser() from:$userId: Unable to handle IMXGroupEncryption.reshareKey for $alg")
|
||||
}
|
||||
}
|
||||
cryptoStore.updateGossipingRequestState(request, GossipingRequestState.RE_REQUESTED)
|
||||
}
|
||||
|
|
|
@ -32,34 +32,4 @@ internal interface IMXEncrypting {
|
|||
* @return the encrypted content
|
||||
*/
|
||||
suspend fun encryptEventContent(eventContent: Content, eventType: String, userIds: List<String>): Content
|
||||
|
||||
/**
|
||||
* In Megolm, each recipient maintains a record of the ratchet value which allows
|
||||
* them to decrypt any messages sent in the session after the corresponding point
|
||||
* in the conversation. If this value is compromised, an attacker can similarly
|
||||
* decrypt past messages which were encrypted by a key derived from the
|
||||
* compromised or subsequent ratchet values. This gives 'partial' forward
|
||||
* secrecy.
|
||||
*
|
||||
* To mitigate this issue, the application should offer the user the option to
|
||||
* discard historical conversations, by winding forward any stored ratchet values,
|
||||
* or discarding sessions altogether.
|
||||
*/
|
||||
fun discardSessionKey()
|
||||
|
||||
/**
|
||||
* Re-shares a session key with devices if the key has already been
|
||||
* sent to them.
|
||||
*
|
||||
* @param sessionId The id of the outbound session to share.
|
||||
* @param userId The id of the user who owns the target device.
|
||||
* @param deviceId The id of the target device.
|
||||
* @param senderKey The key of the originating device for the session.
|
||||
*
|
||||
* @return true in case of success
|
||||
*/
|
||||
suspend fun reshareKey(sessionId: String,
|
||||
userId: String,
|
||||
deviceId: String,
|
||||
senderKey: String): Boolean
|
||||
}
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright 2020 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.algorithms
|
||||
|
||||
internal interface IMXGroupEncryption {
|
||||
|
||||
/**
|
||||
* In Megolm, each recipient maintains a record of the ratchet value which allows
|
||||
* them to decrypt any messages sent in the session after the corresponding point
|
||||
* in the conversation. If this value is compromised, an attacker can similarly
|
||||
* decrypt past messages which were encrypted by a key derived from the
|
||||
* compromised or subsequent ratchet values. This gives 'partial' forward
|
||||
* secrecy.
|
||||
*
|
||||
* To mitigate this issue, the application should offer the user the option to
|
||||
* discard historical conversations, by winding forward any stored ratchet values,
|
||||
* or discarding sessions altogether.
|
||||
*/
|
||||
fun discardSessionKey()
|
||||
|
||||
suspend fun preshareKey(userIds: List<String>)
|
||||
|
||||
/**
|
||||
* Re-shares a session key with devices if the key has already been
|
||||
* sent to them.
|
||||
*
|
||||
* @param sessionId The id of the outbound session to share.
|
||||
* @param userId The id of the user who owns the target device.
|
||||
* @param deviceId The id of the target device.
|
||||
* @param senderKey The key of the originating device for the session.
|
||||
*
|
||||
* @return true in case of success
|
||||
*/
|
||||
suspend fun reshareKey(sessionId: String,
|
||||
userId: String,
|
||||
deviceId: String,
|
||||
senderKey: String): Boolean
|
||||
}
|
|
@ -18,8 +18,6 @@ package org.matrix.android.sdk.internal.crypto.algorithms.megolm
|
|||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.auth.data.Credentials
|
||||
import org.matrix.android.sdk.api.session.crypto.MXCryptoError
|
||||
import org.matrix.android.sdk.api.session.events.model.Content
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
|
@ -30,6 +28,7 @@ import org.matrix.android.sdk.internal.crypto.MXOlmDevice
|
|||
import org.matrix.android.sdk.internal.crypto.actions.EnsureOlmSessionsForDevicesAction
|
||||
import org.matrix.android.sdk.internal.crypto.actions.MessageEncrypter
|
||||
import org.matrix.android.sdk.internal.crypto.algorithms.IMXEncrypting
|
||||
import org.matrix.android.sdk.internal.crypto.algorithms.IMXGroupEncryption
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.DefaultKeysBackupService
|
||||
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
|
||||
import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap
|
||||
|
@ -39,8 +38,6 @@ import org.matrix.android.sdk.internal.crypto.model.forEach
|
|||
import org.matrix.android.sdk.internal.crypto.repository.WarnOnUnknownDeviceRepository
|
||||
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
|
||||
import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask
|
||||
import org.matrix.android.sdk.internal.task.TaskExecutor
|
||||
import org.matrix.android.sdk.internal.task.configureWith
|
||||
import org.matrix.android.sdk.internal.util.JsonCanonicalizer
|
||||
import org.matrix.android.sdk.internal.util.MatrixCoroutineDispatchers
|
||||
import org.matrix.android.sdk.internal.util.convertToUTF8
|
||||
|
@ -54,14 +51,14 @@ internal class MXMegolmEncryption(
|
|||
private val cryptoStore: IMXCryptoStore,
|
||||
private val deviceListManager: DeviceListManager,
|
||||
private val ensureOlmSessionsForDevicesAction: EnsureOlmSessionsForDevicesAction,
|
||||
private val credentials: Credentials,
|
||||
private val userId: String,
|
||||
private val deviceId: String,
|
||||
private val sendToDeviceTask: SendToDeviceTask,
|
||||
private val messageEncrypter: MessageEncrypter,
|
||||
private val warnOnUnknownDevicesRepository: WarnOnUnknownDeviceRepository,
|
||||
private val taskExecutor: TaskExecutor,
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
private val cryptoCoroutineScope: CoroutineScope
|
||||
) : IMXEncrypting {
|
||||
) : IMXEncrypting, IMXGroupEncryption {
|
||||
|
||||
// OutboundSessionInfo. Null if we haven't yet started setting one up. Note
|
||||
// that even if this is non-null, it may not be ready for use (in which
|
||||
|
@ -93,6 +90,7 @@ internal class MXMegolmEncryption(
|
|||
// annoyingly we have to serialize again the saved outbound session to store message index :/
|
||||
// if not we would see duplicate message index errors
|
||||
olmDevice.storeOutboundGroupSessionForRoom(roomId, outboundSession.sessionId)
|
||||
Timber.v("## CRYPTO | encryptEventContent: Finished in ${System.currentTimeMillis() - ts} millis")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,6 +115,16 @@ internal class MXMegolmEncryption(
|
|||
olmDevice.discardOutboundGroupSessionForRoom(roomId)
|
||||
}
|
||||
|
||||
override suspend fun preshareKey(userIds: List<String>) {
|
||||
val ts = System.currentTimeMillis()
|
||||
Timber.v("## CRYPTO | preshareKey : getDevicesInRoom")
|
||||
val devices = getDevicesInRoom(userIds)
|
||||
val outboundSession = ensureOutboundSession(devices.allowedDevices)
|
||||
|
||||
notifyWithheldForSession(devices.withHeldDevices, outboundSession)
|
||||
|
||||
Timber.v("## CRYPTO | preshareKey ${System.currentTimeMillis() - ts} millis")
|
||||
}
|
||||
/**
|
||||
* Prepare a new session.
|
||||
*
|
||||
|
@ -252,7 +260,7 @@ internal class MXMegolmEncryption(
|
|||
|
||||
continue
|
||||
}
|
||||
Timber.i("## CRYPTO | shareUserDevicesKey() : Sharing keys with device $userId:$deviceID")
|
||||
Timber.i("## CRYPTO | shareUserDevicesKey() : Add to share keys contentMap for $userId:$deviceID")
|
||||
contentMap.setObject(userId, deviceID, messageEncrypter.encryptMessage(payload, listOf(sessionResult.deviceInfo)))
|
||||
haveTargets = true
|
||||
}
|
||||
|
@ -263,12 +271,14 @@ internal class MXMegolmEncryption(
|
|||
// attempted to share with) rather than the contentMap (those we did
|
||||
// share with), because we don't want to try to claim a one-time-key
|
||||
// for dead devices on every message.
|
||||
val gossipingEventBuffer = arrayListOf<Event>()
|
||||
for ((userId, devicesToShareWith) in devicesByUser) {
|
||||
for ((deviceId) in devicesToShareWith) {
|
||||
session.sharedWithHelper.markedSessionAsShared(userId, deviceId, chainIndex)
|
||||
cryptoStore.saveGossipingEvent(Event(
|
||||
gossipingEventBuffer.add(
|
||||
Event(
|
||||
type = EventType.ROOM_KEY,
|
||||
senderId = credentials.userId,
|
||||
senderId = this.userId,
|
||||
content = submap.apply {
|
||||
this["session_key"] = ""
|
||||
// we add a fake key for trail
|
||||
|
@ -278,6 +288,8 @@ internal class MXMegolmEncryption(
|
|||
}
|
||||
}
|
||||
|
||||
cryptoStore.saveGossipingEvents(gossipingEventBuffer)
|
||||
|
||||
if (haveTargets) {
|
||||
t0 = System.currentTimeMillis()
|
||||
Timber.i("## CRYPTO | shareUserDevicesKey() ${session.sessionId} : has target")
|
||||
|
@ -294,8 +306,11 @@ internal class MXMegolmEncryption(
|
|||
}
|
||||
}
|
||||
|
||||
private fun notifyKeyWithHeld(targets: List<UserDevice>, sessionId: String, senderKey: String?, code: WithHeldCode) {
|
||||
Timber.i("## CRYPTO | notifyKeyWithHeld() :sending withheld key for $targets session:$sessionId ")
|
||||
private suspend fun notifyKeyWithHeld(targets: List<UserDevice>,
|
||||
sessionId: String,
|
||||
senderKey: String?,
|
||||
code: WithHeldCode) {
|
||||
Timber.i("## CRYPTO | notifyKeyWithHeld() :sending withheld key for $targets session:$sessionId and code $code")
|
||||
val withHeldContent = RoomKeyWithHeldContent(
|
||||
roomId = roomId,
|
||||
senderKey = senderKey,
|
||||
|
@ -311,14 +326,12 @@ internal class MXMegolmEncryption(
|
|||
}
|
||||
}
|
||||
)
|
||||
sendToDeviceTask.configureWith(params) {
|
||||
callback = object : MatrixCallback<Unit> {
|
||||
override fun onFailure(failure: Throwable) {
|
||||
try {
|
||||
sendToDeviceTask.execute(params)
|
||||
} catch (failure: Throwable) {
|
||||
Timber.e("## CRYPTO | notifyKeyWithHeld() : Failed to notify withheld key for $targets session: $sessionId ")
|
||||
}
|
||||
}
|
||||
}.executeBy(taskExecutor)
|
||||
}
|
||||
|
||||
/**
|
||||
* process the pending encryptions
|
||||
|
@ -343,7 +356,7 @@ internal class MXMegolmEncryption(
|
|||
|
||||
// Include our device ID so that recipients can send us a
|
||||
// m.new_device message if they don't have our session key.
|
||||
map["device_id"] = credentials.deviceId!!
|
||||
map["device_id"] = deviceId
|
||||
session.useCount++
|
||||
return map
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
package org.matrix.android.sdk.internal.crypto.algorithms.megolm
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import org.matrix.android.sdk.api.auth.data.Credentials
|
||||
import org.matrix.android.sdk.internal.crypto.DeviceListManager
|
||||
import org.matrix.android.sdk.internal.crypto.MXOlmDevice
|
||||
import org.matrix.android.sdk.internal.crypto.actions.EnsureOlmSessionsForDevicesAction
|
||||
|
@ -26,7 +25,8 @@ import org.matrix.android.sdk.internal.crypto.keysbackup.DefaultKeysBackupServic
|
|||
import org.matrix.android.sdk.internal.crypto.repository.WarnOnUnknownDeviceRepository
|
||||
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
|
||||
import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask
|
||||
import org.matrix.android.sdk.internal.task.TaskExecutor
|
||||
import org.matrix.android.sdk.internal.di.DeviceId
|
||||
import org.matrix.android.sdk.internal.di.UserId
|
||||
import org.matrix.android.sdk.internal.util.MatrixCoroutineDispatchers
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -36,29 +36,29 @@ internal class MXMegolmEncryptionFactory @Inject constructor(
|
|||
private val cryptoStore: IMXCryptoStore,
|
||||
private val deviceListManager: DeviceListManager,
|
||||
private val ensureOlmSessionsForDevicesAction: EnsureOlmSessionsForDevicesAction,
|
||||
private val credentials: Credentials,
|
||||
@UserId private val userId: String,
|
||||
@DeviceId private val deviceId: String?,
|
||||
private val sendToDeviceTask: SendToDeviceTask,
|
||||
private val messageEncrypter: MessageEncrypter,
|
||||
private val warnOnUnknownDevicesRepository: WarnOnUnknownDeviceRepository,
|
||||
private val taskExecutor: TaskExecutor,
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
private val cryptoCoroutineScope: CoroutineScope) {
|
||||
|
||||
fun create(roomId: String): MXMegolmEncryption {
|
||||
return MXMegolmEncryption(
|
||||
roomId,
|
||||
olmDevice,
|
||||
defaultKeysBackupService,
|
||||
cryptoStore,
|
||||
deviceListManager,
|
||||
ensureOlmSessionsForDevicesAction,
|
||||
credentials,
|
||||
sendToDeviceTask,
|
||||
messageEncrypter,
|
||||
warnOnUnknownDevicesRepository,
|
||||
taskExecutor,
|
||||
coroutineDispatchers,
|
||||
cryptoCoroutineScope
|
||||
roomId = roomId,
|
||||
olmDevice = olmDevice,
|
||||
defaultKeysBackupService = defaultKeysBackupService,
|
||||
cryptoStore = cryptoStore,
|
||||
deviceListManager = deviceListManager,
|
||||
ensureOlmSessionsForDevicesAction = ensureOlmSessionsForDevicesAction,
|
||||
userId = userId,
|
||||
deviceId = deviceId!!,
|
||||
sendToDeviceTask = sendToDeviceTask,
|
||||
messageEncrypter = messageEncrypter,
|
||||
warnOnUnknownDevicesRepository = warnOnUnknownDevicesRepository,
|
||||
coroutineDispatchers = coroutineDispatchers,
|
||||
cryptoCoroutineScope = cryptoCoroutineScope
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,13 +76,4 @@ internal class MXOlmEncryption(
|
|||
deviceListManager.downloadKeys(users, false)
|
||||
ensureOlmSessionsForUsersAction.handle(users)
|
||||
}
|
||||
|
||||
override fun discardSessionKey() {
|
||||
// No need for olm
|
||||
}
|
||||
|
||||
override suspend fun reshareKey(sessionId: String, userId: String, deviceId: String, senderKey: String): Boolean {
|
||||
// No need for olm
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ internal class DefaultEncryptEventTask @Inject constructor(
|
|||
// don't want to wait for any query
|
||||
// if (!params.crypto.isRoomEncrypted(params.roomId)) return params.event
|
||||
val localEvent = params.event
|
||||
if (localEvent.eventId == null) {
|
||||
if (localEvent.eventId == null || localEvent.type == null) {
|
||||
throw IllegalArgumentException()
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue