Merge branch 'develop' into feature/fga/new_voip_design
This commit is contained in:
commit
4788630949
|
@ -0,0 +1,84 @@
|
|||
---
|
||||
name: Release
|
||||
about: Checklist for each release. To be used by the core team only.
|
||||
title: "[Release] Element Android v"
|
||||
labels: "\U0001F680 Release"
|
||||
assignees: bmarty
|
||||
|
||||
---
|
||||
|
||||
For the example, we are releasing the version 1.1.10. Delete this line and replace 1.1.10 with the version in the issue content.
|
||||
|
||||
### Before the release
|
||||
|
||||
- [ ] Weblate sync, fix lint issue if any (in a dedicated PR)
|
||||
- [ ] Check the update of the store descriptions (using Google Translate if necessary) to ensure that the changes are acceptable to be published to the stores.
|
||||
- [ ] Run the script `./tools/release/pushPlayStoreMetaData.sh`. You can check in the GooglePlay console the Activity log to check the effect.
|
||||
|
||||
### Do the release
|
||||
|
||||
- [ ] Create release with gitflow, branch name `release/1.1.10`
|
||||
- [ ] Run `./tools/import_emojis.py` and commit the change if any.
|
||||
- [ ] Run `./tools/import_sas_strings.py` and commit the change if any. If there is no change since a while, ping Travis
|
||||
- [ ] Check the crashes from the PlayStore
|
||||
- [ ] Check the rageshake with the current dev version: https://github.com/matrix-org/element-android-rageshakes/labels/1.1.10-dev
|
||||
- [ ] Run the integration test, and especially `UiAllScreensSanityTest.allScreensTest()`
|
||||
- [ ] Create an account on matrix.org
|
||||
- [ ] Run towncrier: `towncrier --version v1.1.10 --draft` (remove `--draft` do write the file CHANGES.md)
|
||||
- [ ] Add file for fastlane under ./fastlane/metadata/android/en-US/changelogs
|
||||
- [ ] Push the branch and start a draft PR (will not be merged), to check that the CI is happy with all the changes.
|
||||
- [ ] Finish release with gitflow, delete the draft PR
|
||||
- [ ] Push `main` and the new tag `v1.1.10` to origin
|
||||
- [ ] Checkout `develop`
|
||||
- [ ] Increase version in `./vector/build.gradle`
|
||||
- [ ] Commit and push `develop`
|
||||
- [ ] Wait for [Buildkite](https://buildkite.com/matrix-dot-org/element-android/builds?branch=main) to build the `main` branch.
|
||||
- [ ] Run the script `~/scripts/releaseElement.sh`. It will download the APKs from Buildkite check them and sign them.
|
||||
- [ ] Install the APK on your phone to check that the upgrade went well (no init sync, etc.)
|
||||
- [ ] Create a new beta release on the GooglePlay console and upload the 4 signed Apks.
|
||||
- [ ] Check that the version codes are correct
|
||||
- [ ] Copy the fastlane change to the GooglePlay console in the section en-GB.
|
||||
- [ ] Push to beta release to 100% of the users
|
||||
- [ ] Create the release on gitHub [from the tag](https://github.com/vector-im/element-android/tags), copy paste the block from the file CHANGES.md
|
||||
- [ ] Add the 4 signed APKs to the GitHub release
|
||||
- [ ] Ping the Android Internal room
|
||||
- [ ] Add an entry in the internal diary
|
||||
|
||||
### Once Live on PlayStore
|
||||
|
||||
- [ ] Ping the Android public room and update its topic
|
||||
|
||||
### After at least 2 days
|
||||
|
||||
- [ ] Check the [rageshakes](https://github.com/matrix-org/element-android-rageshakes/issues)
|
||||
- [ ] Check the crash reports on the GooglePlay console
|
||||
- [ ] Check the Android Element room for any reported issues on the new version
|
||||
- [ ] If all is OK, push to production and notify Markus (Bubu) to release the F-Droid version
|
||||
- [ ] Ping the Android public room and update its topic with the new available version
|
||||
|
||||
### Android SDK2
|
||||
|
||||
- [ ] Checkout the `main` branch on Element Android project
|
||||
|
||||
#### On the SDK2 project
|
||||
|
||||
https://github.com/matrix-org/matrix-android-sdk2
|
||||
|
||||
- [ ] Create a release with GitFlow
|
||||
- [ ] Update the files `./build.gradle` and `./gradle/gradle-wrapper.properties` manually, to use the latest version for the dependency. You can get inspired by the same files on Element Android project.
|
||||
- [ ] Run the script `./tools/import_from_element.sh`
|
||||
- [ ] Update the version in `./matrix-sdk-android/build.gradle` and let the script finish to build the library
|
||||
- [ ] Update the file `CHANGES.md`
|
||||
- [ ] Finish the release using GitFlow
|
||||
- [ ] Create the release on GitHub from [the tag](https://github.com/matrix-org/matrix-android-sdk2/tags)
|
||||
- [ ] Upload the AAR on the GitHub release
|
||||
|
||||
### Android SDK2 sample
|
||||
|
||||
https://github.com/matrix-org/matrix-android-sdk2-sample
|
||||
|
||||
- [ ] Update the dependency to the new version of the SDK2. Jitpack will have to build the AAR, it can take a few minutes. You can check status on https://jitpack.io/#matrix-org/matrix-android-sdk2
|
||||
- [ ] Build and run the sample, you may have to fix some API break
|
||||
- [ ] Commit and push directly on `main`
|
||||
|
||||
<!-- Note: some scripts are not public because they contain some private keys -->
|
|
@ -38,6 +38,7 @@
|
|||
<w>unpublish</w>
|
||||
<w>unwedging</w>
|
||||
<w>vctr</w>
|
||||
<w>wellknown</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
</component>
|
49
CHANGES.md
49
CHANGES.md
|
@ -1,3 +1,52 @@
|
|||
Changes in Element 1.1.14 (2021-07-23)
|
||||
======================================
|
||||
|
||||
Features ✨
|
||||
----------
|
||||
- Add low priority section in DM tab ([#3463](https://github.com/vector-im/element-android/issues/3463))
|
||||
- Show missed call notification. ([#3710](https://github.com/vector-im/element-android/issues/3710))
|
||||
|
||||
Bugfixes 🐛
|
||||
----------
|
||||
- Don't use the transaction ID of the verification for the request ([#3589](https://github.com/vector-im/element-android/issues/3589))
|
||||
- Avoid incomplete downloads in cache ([#3656](https://github.com/vector-im/element-android/issues/3656))
|
||||
- Fix a crash which can happen when user signs out ([#3720](https://github.com/vector-im/element-android/issues/3720))
|
||||
- Ensure OTKs are uploaded when the session is created ([#3724](https://github.com/vector-im/element-android/issues/3724))
|
||||
|
||||
SDK API changes ⚠️
|
||||
------------------
|
||||
- Add initialState support to CreateRoomParams (#3713) ([#3713](https://github.com/vector-im/element-android/issues/3713))
|
||||
|
||||
Other changes
|
||||
-------------
|
||||
- Apply grammatical fixes to the Server ACL timeline messages. ([#3721](https://github.com/vector-im/element-android/issues/3721))
|
||||
- Add tags in the log, especially for VoIP, but can be used for other features in the future ([#3723](https://github.com/vector-im/element-android/issues/3723))
|
||||
|
||||
|
||||
Changes in Element v1.1.13 (2021-07-19)
|
||||
=======================================
|
||||
|
||||
Features ✨
|
||||
----------
|
||||
- Remove redundant mimetype (vector-im/element-web#2547) ([#3273](https://github.com/vector-im/element-android/issues/3273))
|
||||
- Room version capabilities and room upgrade support, better error feedback ([#3551](https://github.com/vector-im/element-android/issues/3551))
|
||||
- Add retry support in room addresses screen ([#3635](https://github.com/vector-im/element-android/issues/3635))
|
||||
- Better management of permission requests ([#3667](https://github.com/vector-im/element-android/issues/3667))
|
||||
|
||||
Bugfixes 🐛
|
||||
----------
|
||||
- Standardise spelling and casing of homeserver, identity server, and integration manager. ([#491](https://github.com/vector-im/element-android/issues/491))
|
||||
- Perform .well-known request first, even if the entered URL is a valid homeserver base url ([#2843](https://github.com/vector-im/element-android/issues/2843))
|
||||
- Use different copy for self verification. ([#3624](https://github.com/vector-im/element-android/issues/3624))
|
||||
- Crash when opening room addresses screen with no internet connection ([#3634](https://github.com/vector-im/element-android/issues/3634))
|
||||
- Fix unread messages marker being hidden in collapsed membership item ([#3655](https://github.com/vector-im/element-android/issues/3655))
|
||||
- Ensure reaction emoji picker tabs look fine on small displays ([#3661](https://github.com/vector-im/element-android/issues/3661))
|
||||
|
||||
SDK API changes ⚠️
|
||||
------------------
|
||||
- RawService.getWellknown() now takes a domain instead of a matrixId as parameter ([#3572](https://github.com/vector-im/element-android/issues/3572))
|
||||
|
||||
|
||||
Changes in Element 1.1.12 (2021-07-05)
|
||||
======================================
|
||||
|
||||
|
|
68
Gemfile.lock
68
Gemfile.lock
|
@ -2,25 +2,25 @@ GEM
|
|||
remote: https://rubygems.org/
|
||||
specs:
|
||||
CFPropertyList (3.0.3)
|
||||
addressable (2.7.0)
|
||||
addressable (2.8.0)
|
||||
public_suffix (>= 2.0.2, < 5.0)
|
||||
artifactory (3.0.15)
|
||||
atomos (0.1.3)
|
||||
aws-eventstream (1.1.1)
|
||||
aws-partitions (1.462.0)
|
||||
aws-sdk-core (3.114.0)
|
||||
aws-partitions (1.479.0)
|
||||
aws-sdk-core (3.117.0)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
aws-partitions (~> 1, >= 1.239.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
jmespath (~> 1.0)
|
||||
aws-sdk-kms (1.43.0)
|
||||
aws-sdk-kms (1.44.0)
|
||||
aws-sdk-core (~> 3, >= 3.112.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-sdk-s3 (1.95.1)
|
||||
aws-sdk-s3 (1.96.1)
|
||||
aws-sdk-core (~> 3, >= 3.112.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-sigv4 (1.2.3)
|
||||
aws-sigv4 (1.2.4)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
babosa (1.0.4)
|
||||
claide (1.0.3)
|
||||
|
@ -35,13 +35,15 @@ GEM
|
|||
unf (>= 0.0.5, < 1.0.0)
|
||||
dotenv (2.7.6)
|
||||
emoji_regex (3.2.2)
|
||||
excon (0.81.0)
|
||||
faraday (1.4.2)
|
||||
excon (0.85.0)
|
||||
faraday (1.5.1)
|
||||
faraday-em_http (~> 1.0)
|
||||
faraday-em_synchrony (~> 1.0)
|
||||
faraday-excon (~> 1.1)
|
||||
faraday-httpclient (~> 1.0.1)
|
||||
faraday-net_http (~> 1.0)
|
||||
faraday-net_http_persistent (~> 1.1)
|
||||
faraday-patron (~> 1.0)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
ruby2_keywords (>= 0.0.4)
|
||||
faraday-cookie_jar (0.0.7)
|
||||
|
@ -50,12 +52,14 @@ GEM
|
|||
faraday-em_http (1.0.0)
|
||||
faraday-em_synchrony (1.0.0)
|
||||
faraday-excon (1.1.0)
|
||||
faraday-httpclient (1.0.1)
|
||||
faraday-net_http (1.0.1)
|
||||
faraday-net_http_persistent (1.1.0)
|
||||
faraday-net_http_persistent (1.2.0)
|
||||
faraday-patron (1.0.0)
|
||||
faraday_middleware (1.0.0)
|
||||
faraday (~> 1.0)
|
||||
fastimage (2.2.3)
|
||||
fastlane (2.184.0)
|
||||
fastimage (2.2.4)
|
||||
fastlane (2.187.0)
|
||||
CFPropertyList (>= 2.3, < 4.0.0)
|
||||
addressable (>= 2.3, < 3.0.0)
|
||||
artifactory (~> 3.0)
|
||||
|
@ -94,37 +98,36 @@ GEM
|
|||
xcpretty (~> 0.3.0)
|
||||
xcpretty-travis-formatter (>= 0.0.3)
|
||||
gh_inspector (1.1.3)
|
||||
google-apis-androidpublisher_v3 (0.4.0)
|
||||
google-apis-core (~> 0.1)
|
||||
google-apis-core (0.3.0)
|
||||
google-apis-androidpublisher_v3 (0.8.0)
|
||||
google-apis-core (>= 0.4, < 2.a)
|
||||
google-apis-core (0.4.0)
|
||||
addressable (~> 2.5, >= 2.5.1)
|
||||
googleauth (~> 0.14)
|
||||
httpclient (>= 2.8.1, < 3.0)
|
||||
googleauth (>= 0.16.2, < 2.a)
|
||||
httpclient (>= 2.8.1, < 3.a)
|
||||
mini_mime (~> 1.0)
|
||||
representable (~> 3.0)
|
||||
retriable (>= 2.0, < 4.0)
|
||||
retriable (>= 2.0, < 4.a)
|
||||
rexml
|
||||
signet (~> 0.14)
|
||||
webrick
|
||||
google-apis-iamcredentials_v1 (0.4.0)
|
||||
google-apis-core (~> 0.1)
|
||||
google-apis-playcustomapp_v1 (0.3.0)
|
||||
google-apis-core (~> 0.1)
|
||||
google-apis-storage_v1 (0.4.0)
|
||||
google-apis-core (~> 0.1)
|
||||
google-apis-iamcredentials_v1 (0.6.0)
|
||||
google-apis-core (>= 0.4, < 2.a)
|
||||
google-apis-playcustomapp_v1 (0.5.0)
|
||||
google-apis-core (>= 0.4, < 2.a)
|
||||
google-apis-storage_v1 (0.6.0)
|
||||
google-apis-core (>= 0.4, < 2.a)
|
||||
google-cloud-core (1.6.0)
|
||||
google-cloud-env (~> 1.0)
|
||||
google-cloud-errors (~> 1.0)
|
||||
google-cloud-env (1.5.0)
|
||||
faraday (>= 0.17.3, < 2.0)
|
||||
google-cloud-errors (1.1.0)
|
||||
google-cloud-storage (1.31.1)
|
||||
google-cloud-storage (1.34.1)
|
||||
addressable (~> 2.5)
|
||||
digest-crc (~> 0.4)
|
||||
google-apis-iamcredentials_v1 (~> 0.1)
|
||||
google-apis-storage_v1 (~> 0.1)
|
||||
google-cloud-core (~> 1.2)
|
||||
googleauth (~> 0.9)
|
||||
google-cloud-core (~> 1.6)
|
||||
googleauth (>= 0.16.2, < 2.a)
|
||||
mini_mime (~> 1.0)
|
||||
googleauth (0.16.2)
|
||||
faraday (>= 0.17.3, < 2.0)
|
||||
|
@ -134,7 +137,7 @@ GEM
|
|||
os (>= 0.9, < 2.0)
|
||||
signet (~> 0.14)
|
||||
highline (2.0.3)
|
||||
http-cookie (1.0.3)
|
||||
http-cookie (1.0.4)
|
||||
domain_name (~> 0.5)
|
||||
httpclient (2.8.3)
|
||||
jmespath (1.4.0)
|
||||
|
@ -150,7 +153,7 @@ GEM
|
|||
os (1.1.1)
|
||||
plist (3.6.0)
|
||||
public_suffix (4.0.6)
|
||||
rake (13.0.3)
|
||||
rake (13.0.6)
|
||||
representable (3.1.1)
|
||||
declarative (< 0.1.0)
|
||||
trailblazer-option (>= 0.1.1, < 0.2.0)
|
||||
|
@ -158,8 +161,8 @@ GEM
|
|||
retriable (3.1.2)
|
||||
rexml (3.2.5)
|
||||
rouge (2.0.7)
|
||||
ruby2_keywords (0.0.4)
|
||||
rubyzip (2.3.0)
|
||||
ruby2_keywords (0.0.5)
|
||||
rubyzip (2.3.2)
|
||||
security (0.1.3)
|
||||
signet (0.15.0)
|
||||
addressable (~> 2.3)
|
||||
|
@ -184,12 +187,13 @@ GEM
|
|||
unicode-display_width (1.7.0)
|
||||
webrick (1.7.0)
|
||||
word_wrap (1.0.0)
|
||||
xcodeproj (1.19.0)
|
||||
xcodeproj (1.20.0)
|
||||
CFPropertyList (>= 2.3.3, < 4.0)
|
||||
atomos (~> 0.1.3)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
colored2 (~> 3.1)
|
||||
nanaimo (~> 0.3.0)
|
||||
rexml (~> 3.2.4)
|
||||
xcpretty (0.3.0)
|
||||
rouge (~> 2.0.7)
|
||||
xcpretty-travis-formatter (1.0.1)
|
||||
|
|
|
@ -56,8 +56,8 @@ dependencies {
|
|||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
implementation 'androidx.core:core-ktx:1.6.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.3.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.3.1'
|
||||
implementation "androidx.recyclerview:recyclerview:1.2.1"
|
||||
|
||||
implementation 'com.google.android.material:material:1.3.0'
|
||||
implementation 'com.google.android.material:material:1.4.0'
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
buildscript {
|
||||
// Ref: https://kotlinlang.org/releases.html
|
||||
ext.kotlin_version = '1.5.20'
|
||||
ext.kotlin_version = '1.5.21'
|
||||
ext.kotlin_coroutines_version = "1.5.0"
|
||||
repositories {
|
||||
google()
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
Remove redundant mimetype (vector-im/element-web#2547)
|
|
@ -4,7 +4,7 @@ Issue: #607
|
|||
PR: #1354
|
||||
|
||||
## Introduction
|
||||
Identity Servers support contact discovery on Matrix by letting people look up Third Party Identifiers to see if the owner has publicly linked them with their Matrix ID.
|
||||
Identity servers support contact discovery on Matrix by letting people look up Third Party Identifiers to see if the owner has publicly linked them with their Matrix ID.
|
||||
|
||||
## Implementation
|
||||
|
||||
|
@ -87,6 +87,6 @@ This screen displays the identity server configuration and the binding of the us
|
|||
This screen is a form to set a new identity server URL
|
||||
|
||||
## Ref:
|
||||
- https://matrix.org/blog/2019/09/27/privacy-improvements-in-synapse-1-4-and-riot-1-4 is a good summary of the role of an Identity server and the proper way to configure and use it in respect to the privacy and the consent of the user.
|
||||
- https://matrix.org/blog/2019/09/27/privacy-improvements-in-synapse-1-4-and-riot-1-4 is a good summary of the role of an identity server and the proper way to configure and use it in respect to the privacy and the consent of the user.
|
||||
- API documentation: https://matrix.org/docs/spec/identity_service/latest
|
||||
- vector.im TOS: https://vector.im/identity-server-privacy-notice
|
||||
|
|
|
@ -2,11 +2,11 @@ This document aims to describe how Element android displays notifications to the
|
|||
|
||||
# Table of Contents
|
||||
1. [Prerequisites Knowledge](#prerequisites-knowledge)
|
||||
* [How does a matrix client get a message from a Home Server?](#how-does-a-matrix-client-get-a-message-from-a-home-server)
|
||||
* [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 in the matrix federated world](#push-in-the-matrix-federated-world)
|
||||
* [How does the Home Server knows when to notify a client?](#how-does-the-home-server-knows-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)
|
||||
* [Background processing limitations](#background-processing-limitations)
|
||||
2. [Element Notification implementations](#element-notification-implementations)
|
||||
|
@ -22,9 +22,9 @@ First let's start with some prerequisite knowledge
|
|||
|
||||
# Prerequisites Knowledge
|
||||
|
||||
## How does a matrix client get a message from a Home Server?
|
||||
## How does a matrix client get a message from a homeserver?
|
||||
|
||||
In order to get messages from a home server, 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.
|
||||
|
||||
`To read events, the intended flow of operation is for clients to first call the /sync API without a since parameter. This returns the most recent message events for each room, as well as the state of the room at the start of the returned timeline. `
|
||||
|
||||
|
@ -90,7 +90,7 @@ That means that Element Android, a matrix client created by New Vector, is using
|
|||
|
||||
If you create your own matrix client, you will also need to deploy an instance of a **Push Gateway** with the credentials needed to use FCM for your app.
|
||||
|
||||
On registration, a matrix client must tell to it's Home Server what Push Gateway to use.
|
||||
On registration, a matrix client must tell its homeserver what Push Gateway to use.
|
||||
|
||||
See [Sygnal](https://github.com/matrix-org/sygnal/) for a reference implementation.
|
||||
```
|
||||
|
@ -122,13 +122,13 @@ Recommended reading:
|
|||
* https://matrix.org/docs/spec/client_server/r0.4.0.html#id128
|
||||
|
||||
|
||||
## How does the Home Server knows 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-).
|
||||
|
||||
`A push rule is a single rule that states under what conditions an event should be passed onto a push gateway and how the notification should be presented (sound / importance).`
|
||||
|
||||
A Home Server can be configured with default rules (for Direct messages, group messages, mentions, etc.. ).
|
||||
A homeserver can be configured with default rules (for Direct messages, group messages, mentions, etc.. ).
|
||||
|
||||
There are different kind of push rules, it can be per room (each new message on this room should be notified), it can also define a pattern that a message should match (when you are mentioned, or key word based).
|
||||
|
||||
|
@ -187,7 +187,7 @@ In background, and depending on wether push is available or not, Element will us
|
|||
|
||||
## 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.
|
||||
|
||||
When a message should be notified to a user, the user's homeserver notifies the registered `push gateway` for Element, that is [sygnal](https://github.com/matrix-org/sygnal) _- The reference implementation for push gateways -_ hosted by matrix.org.
|
||||
|
||||
|
@ -199,7 +199,7 @@ Homeserver ----> Sygnal (configured for Element) ----> FCM ----> Element
|
|||
|
||||
The push gateway is configured to only send `(eventId,roomId)` in the push payload (for better [privacy](#push-vs-privacy-and-mitigation)).
|
||||
|
||||
Element needs then to synchronise with the user's HomeServer, in order to resolve the event and create a notification.
|
||||
Element needs then to synchronise with the user's homeserver, in order to resolve the event and create a notification.
|
||||
|
||||
As per [Google recommendation](https://android-developers.googleblog.com/2018/09/notifying-your-users-with-fcm.html), Element will then use the WorkManager API in order to trigger a background sync.
|
||||
|
||||
|
@ -217,7 +217,7 @@ Homeserver ----> Sygnal ----> FCM ----> Element
|
|||
|
||||
**Possible outcomes**
|
||||
|
||||
Upon reception of the FCM push, Element will perform a sync call to the Home Server, during this process it is possible that:
|
||||
Upon reception of the FCM push, Element will perform a sync call to the homeserver, during this process it is possible that:
|
||||
* Happy path, the sync is performed, the message resolved and displayed in the notification drawer
|
||||
* The notified message is not in the sync. Can happen if a lot of things did happen since the push (`gappy sync`)
|
||||
* The sync generates additional notifications (e.g an encrypted message where the user is mentioned detected locally)
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Hlavní změny v této verzi: aktualizace vzhledu a stylu a nové funkce prostorů.
|
||||
Úplný záznam změn: https://github.com/vector-im/element-android/releases/tag/v1.1.10
|
|
@ -0,0 +1,2 @@
|
|||
Hlavní změny v této verzi: aktualizace vzhledu a stylu a nové funkce prostorů (bugfix pro 1.1.10)
|
||||
Úplný záznam změn: https://github.com/vector-im/element-android/releases/tag/v1.1.11
|
|
@ -0,0 +1,2 @@
|
|||
Hauptänderungen: Design-Update und neue Features für Spaces
|
||||
Vollständige Änderungsliste: https://github.com/vector-im/element-android/releases/tag/v1.1.10
|
|
@ -0,0 +1,2 @@
|
|||
Hauptänderungen: Design-Update und neue Features für Spaces (Bugfix für 1.1.10)
|
||||
Vollständige Änderungsliste: https://github.com/vector-im/element-android/releases/tag/v1.1.11
|
|
@ -0,0 +1,2 @@
|
|||
Main changes in this version: mainly stability and bugfixes update.
|
||||
Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.1.13
|
|
@ -0,0 +1,2 @@
|
|||
Main changes in this version: fix an issue about encrypted messages.
|
||||
Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.1.14
|
|
@ -0,0 +1,2 @@
|
|||
Põhilised muutused selles versioonis: teemade ja välimuse uuendused ning mõned kogukondade uuendused
|
||||
Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases/tag/v1.1.10
|
|
@ -0,0 +1,2 @@
|
|||
Põhilised muutused selles versioonis: teemade ja välimuse uuendused ning mõned kogukondade uuendused (1.1.10 veaparandus)
|
||||
Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases/tag/v1.1.11
|
|
@ -0,0 +1,2 @@
|
|||
Főbb változtatások ebben a verzióban: kinézet és stílus frissítések és új funkciók a terekhez
|
||||
Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.1.10
|
|
@ -0,0 +1,2 @@
|
|||
Főbb változtatások ebben a verzióban: kinézet és stílus frissítések és új funkciók a terekhez (hibajavítás az 1.1.10-hez)
|
||||
Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.1.11
|
|
@ -0,0 +1,2 @@
|
|||
Modifiche principali in questa versione: aggiornati tema e stile e nuove funzioni per gli spazi .
|
||||
Cronologia completa: https://github.com/vector-im/element-android/releases/tag/v1.1.10
|
|
@ -0,0 +1,2 @@
|
|||
Modifiche principali in questa versione: aggiornati tema e stile e nuove funzioni per gli spazi (bugfix per 1.1.10)
|
||||
Cronologia completa: https://github.com/vector-im/element-android/releases/tag/v1.1.11
|
|
@ -1,2 +1,2 @@
|
|||
Principais mudanças nesta version: suporte beta para Espaços. Comprimir vídeo antes de enviar.
|
||||
Principais mudanças nesta versão: suporte beta para Espaços. Comprimir vídeo antes de enviar.
|
||||
Changelog completo: https://github.com/vector-im/element-android/releases/tag/v1.1.7
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
Principais mudanças nesta version: melhoramento para Espaços.
|
||||
Principais mudanças nesta versão: melhoramento para Espaços.
|
||||
Changelog completo: https://github.com/vector-im/element-android/releases/tag/v1.1.8
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
Principais mudanças nesta version: adicionar supporte a rede gitter.im.
|
||||
Principais mudanças nesta versão: adicionar supporte a rede gitter.im.
|
||||
Changelog completo: https://github.com/vector-im/element-android/releases/tag/v1.1.9
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Principais mudanças nesta versão: atualização de tema e estilo e novas funcionalidades para espaços.
|
||||
Changelog completo: https://github.com/vector-im/element-android/releases/tag/v1.1.10
|
|
@ -0,0 +1,2 @@
|
|||
Principais mudanças nesta versão: atualização de tema e estilo e novas funcionalidades para espaços (bugfix para 1.1.10)
|
||||
Changelog completo: https://github.com/vector-im/element-android/releases/tag/v1.1.11
|
|
@ -0,0 +1,2 @@
|
|||
Основні зміни цієї версії: оновлено зовнішній вигляд та нові можливості для просторів
|
||||
Вичерпний перелік змін: https://github.com/vector-im/element-android/releases/tag/v1.1.10
|
|
@ -0,0 +1,2 @@
|
|||
Основні зміни цієї версії: оновлено зовнішній вигляд та нові можливості для просторів (bugfix для 1.1.10)
|
||||
Вичерпний перелік змін: https://github.com/vector-im/element-android/releases/tag/v1.1.11
|
|
@ -0,0 +1,2 @@
|
|||
此版本的主要变化:主题和样式更新以及空间的新功能。
|
||||
完整更新日志:https://github.com/vector-im/element-android/releases/tag/v1.1.10
|
|
@ -0,0 +1,2 @@
|
|||
此版本的主要变化:主题和样式更新以及空间的新功能(1.1.10 的错误修复)
|
||||
完整更新日志:https://github.com/vector-im/element-android/releases/tag/v1.1.11
|
|
@ -0,0 +1,2 @@
|
|||
此版本中的主要變動:佈景主題與樣式更新,以及空間的新功能。
|
||||
完整的變更紀錄:https://github.com/vector-im/element-android/releases/tag/v1.1.10
|
|
@ -0,0 +1,2 @@
|
|||
此版本中的主要變動:佈景主題與樣式更新,以及空間的新功能(1.1.10 的臭蟲修復版本)
|
||||
完整的變更紀錄:https://github.com/vector-im/element-android/releases/tag/v1.1.11
|
|
@ -52,8 +52,8 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'androidx.appcompat:appcompat:1.3.0'
|
||||
implementation 'com.google.android.material:material:1.3.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.3.1'
|
||||
implementation 'com.google.android.material:material:1.4.0'
|
||||
// Pref theme
|
||||
implementation 'androidx.preference:preference-ktx:1.1.1'
|
||||
// PFLockScreen attrs
|
||||
|
|
|
@ -35,7 +35,7 @@ android {
|
|||
|
||||
dependencies {
|
||||
implementation project(":matrix-sdk-android")
|
||||
implementation 'androidx.appcompat:appcompat:1.3.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.3.1'
|
||||
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"
|
||||
|
|
|
@ -112,7 +112,7 @@ dependencies {
|
|||
def lifecycle_version = '2.2.0'
|
||||
def arch_version = '2.1.0'
|
||||
def markwon_version = '3.1.0'
|
||||
def daggerVersion = '2.37'
|
||||
def daggerVersion = '2.38'
|
||||
def work_version = '2.5.0'
|
||||
def retrofit_version = '2.9.0'
|
||||
|
||||
|
@ -120,7 +120,7 @@ dependencies {
|
|||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
|
||||
|
||||
implementation "androidx.appcompat:appcompat:1.3.0"
|
||||
implementation "androidx.appcompat:appcompat:1.3.1"
|
||||
implementation "androidx.core:core-ktx:1.6.0"
|
||||
|
||||
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
|
||||
|
@ -169,14 +169,14 @@ dependencies {
|
|||
implementation 'com.otaliastudios:transcoder:0.10.3'
|
||||
|
||||
// Phone number https://github.com/google/libphonenumber
|
||||
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.26'
|
||||
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.28'
|
||||
|
||||
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.12.0'
|
||||
testImplementation 'org.amshove.kluent:kluent-android:1.67'
|
||||
testImplementation 'org.amshove.kluent:kluent-android:1.68'
|
||||
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
|
||||
// Plant Timber tree for test
|
||||
testImplementation 'net.lachlanmckee:timber-junit-rule:1.0.1'
|
||||
|
@ -185,9 +185,9 @@ dependencies {
|
|||
androidTestImplementation 'androidx.test:core:1.4.0'
|
||||
androidTestImplementation 'androidx.test:runner:1.4.0'
|
||||
androidTestImplementation 'androidx.test:rules:1.4.0'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
androidTestImplementation 'org.amshove.kluent:kluent-android:1.65'
|
||||
androidTestImplementation 'org.amshove.kluent:kluent-android:1.68'
|
||||
androidTestImplementation 'io.mockk:mockk-android:1.12.0'
|
||||
androidTestImplementation "androidx.arch.core:core-testing:$arch_version"
|
||||
androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
|
||||
|
|
|
@ -78,7 +78,7 @@ class CommonTestHelper(context: Context) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a Home server configuration, with Http connection allowed for test
|
||||
* Create a homeserver configuration, with Http connection allowed for test
|
||||
*/
|
||||
fun createHomeServerConfig(): HomeServerConnectionConfig {
|
||||
return HomeServerConnectionConfig.Builder()
|
||||
|
|
|
@ -816,7 +816,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||
// - Do an e2e backup to the homeserver
|
||||
mKeysBackupTestHelper.prepareAndCreateKeysBackupData(keysBackup)
|
||||
|
||||
// Get key backup version from the home server
|
||||
// Get key backup version from the homeserver
|
||||
val keysVersionResult = mTestHelper.doSync<KeysVersionResult?> {
|
||||
keysBackup.getCurrentVersion(it)
|
||||
}
|
||||
|
|
|
@ -16,8 +16,12 @@
|
|||
|
||||
package org.matrix.android.sdk.api
|
||||
|
||||
import org.matrix.android.sdk.BuildConfig
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* This class contains pattern to match the different Matrix ids
|
||||
* Ref: https://matrix.org/docs/spec/appendices#identifier-grammar
|
||||
*/
|
||||
object MatrixPatterns {
|
||||
|
||||
|
@ -25,7 +29,7 @@ object MatrixPatterns {
|
|||
private const val DOMAIN_REGEX = ":[A-Z0-9.-]+(:[0-9]{2,5})?"
|
||||
|
||||
// regex pattern to find matrix user ids in a string.
|
||||
// See https://matrix.org/speculator/spec/HEAD/appendices.html#historical-user-ids
|
||||
// See https://matrix.org/docs/spec/appendices#historical-user-ids
|
||||
private const val MATRIX_USER_IDENTIFIER_REGEX = "@[A-Z0-9\\x21-\\x39\\x3B-\\x7F]+$DOMAIN_REGEX"
|
||||
val PATTERN_CONTAIN_MATRIX_USER_IDENTIFIER = MATRIX_USER_IDENTIFIER_REGEX.toRegex(RegexOption.IGNORE_CASE)
|
||||
|
||||
|
@ -154,7 +158,7 @@ object MatrixPatterns {
|
|||
* Orders which are not strings, or do not consist solely of ascii characters in the range \x20 (space) to \x7E (~),
|
||||
* or consist of more than 50 characters, are forbidden and the field should be ignored if received.
|
||||
*/
|
||||
fun isValidOrderString(order: String?) : Boolean {
|
||||
fun isValidOrderString(order: String?): Boolean {
|
||||
return order != null && order.length < 50 && order matches ORDER_STRING_REGEX
|
||||
}
|
||||
|
||||
|
@ -163,4 +167,18 @@ object MatrixPatterns {
|
|||
"[^a-z0-9._%#@=+-]".toRegex().replace(it, "")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the domain form a userId
|
||||
* Examples:
|
||||
* - "@alice:domain.org".getDomain() will return "domain.org"
|
||||
* - "@bob:domain.org:3455".getDomain() will return "domain.org:3455"
|
||||
*/
|
||||
fun String.getDomain(): String {
|
||||
if (BuildConfig.DEBUG && !isUserId(this)) {
|
||||
// They are some invalid userId localpart in the wild, but the domain part should be there anyway
|
||||
Timber.w("Not a valid user ID: $this")
|
||||
}
|
||||
return substringAfter(":")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,11 +18,11 @@ package org.matrix.android.sdk.api.auth.data
|
|||
|
||||
import android.net.Uri
|
||||
import com.squareup.moshi.JsonClass
|
||||
import okhttp3.CipherSuite
|
||||
import okhttp3.TlsVersion
|
||||
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig.Builder
|
||||
import org.matrix.android.sdk.internal.network.ssl.Fingerprint
|
||||
import org.matrix.android.sdk.internal.util.ensureTrailingSlash
|
||||
import okhttp3.CipherSuite
|
||||
import okhttp3.TlsVersion
|
||||
|
||||
/**
|
||||
* This data class holds how to connect to a specific Homeserver.
|
||||
|
@ -31,7 +31,12 @@ import okhttp3.TlsVersion
|
|||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class HomeServerConnectionConfig(
|
||||
// This is the homeserver URL entered by the user
|
||||
val homeServerUri: Uri,
|
||||
// This is the homeserver base URL for the client-server API. Default to homeServerUri,
|
||||
// but can be updated with data from .Well-Known before login, and/or with the data
|
||||
// included in the login response
|
||||
val homeServerUriBase: Uri = homeServerUri,
|
||||
val identityServerUri: Uri? = null,
|
||||
val antiVirusServerUri: Uri? = null,
|
||||
val allowedFingerprints: List<Fingerprint> = emptyList(),
|
||||
|
@ -47,7 +52,6 @@ data class HomeServerConnectionConfig(
|
|||
* This builder should be use to create a [HomeServerConnectionConfig] instance.
|
||||
*/
|
||||
class Builder {
|
||||
|
||||
private lateinit var homeServerUri: Uri
|
||||
private var identityServerUri: Uri? = null
|
||||
private var antiVirusServerUri: Uri? = null
|
||||
|
@ -69,14 +73,14 @@ data class HomeServerConnectionConfig(
|
|||
*/
|
||||
fun withHomeServerUri(hsUri: Uri): Builder {
|
||||
if (hsUri.scheme != "http" && hsUri.scheme != "https") {
|
||||
throw RuntimeException("Invalid home server URI: $hsUri")
|
||||
throw RuntimeException("Invalid homeserver URI: $hsUri")
|
||||
}
|
||||
// ensure trailing /
|
||||
val hsString = hsUri.toString().ensureTrailingSlash()
|
||||
homeServerUri = try {
|
||||
Uri.parse(hsString)
|
||||
} catch (e: Exception) {
|
||||
throw RuntimeException("Invalid home server URI: $hsUri")
|
||||
throw RuntimeException("Invalid homeserver URI: $hsUri")
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
@ -134,7 +138,7 @@ data class HomeServerConnectionConfig(
|
|||
}
|
||||
|
||||
/**
|
||||
* Add an accepted TLS version for TLS connections with the home server.
|
||||
* Add an accepted TLS version for TLS connections with the homeserver.
|
||||
*
|
||||
* @param tlsVersion the tls version to add to the set of TLS versions accepted.
|
||||
* @return this builder
|
||||
|
@ -156,7 +160,7 @@ data class HomeServerConnectionConfig(
|
|||
}
|
||||
|
||||
/**
|
||||
* Add a TLS cipher suite to the list of accepted TLS connections with the home server.
|
||||
* Add a TLS cipher suite to the list of accepted TLS connections with the homeserver.
|
||||
*
|
||||
* @param tlsCipherSuite the tls cipher suite to add.
|
||||
* @return this builder
|
||||
|
@ -234,16 +238,16 @@ data class HomeServerConnectionConfig(
|
|||
*/
|
||||
fun build(): HomeServerConnectionConfig {
|
||||
return HomeServerConnectionConfig(
|
||||
homeServerUri,
|
||||
identityServerUri,
|
||||
antiVirusServerUri,
|
||||
allowedFingerprints,
|
||||
shouldPin,
|
||||
tlsVersions,
|
||||
tlsCipherSuites,
|
||||
shouldAcceptTlsExtensions,
|
||||
allowHttpExtension,
|
||||
forceUsageTlsVersions
|
||||
homeServerUri = homeServerUri,
|
||||
identityServerUri = identityServerUri,
|
||||
antiVirusServerUri = antiVirusServerUri,
|
||||
allowedFingerprints = allowedFingerprints,
|
||||
shouldPin = shouldPin,
|
||||
tlsVersions = tlsVersions,
|
||||
tlsCipherSuites = tlsCipherSuites,
|
||||
shouldAcceptTlsExtensions = shouldAcceptTlsExtensions,
|
||||
allowHttpExtension = allowHttpExtension,
|
||||
forceUsageTlsVersions = forceUsageTlsVersions
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,13 +51,18 @@ data class SessionParams(
|
|||
val deviceId = credentials.deviceId
|
||||
|
||||
/**
|
||||
* The current homeserver Url. It can be different that the homeserver url entered
|
||||
* during login phase, because a redirection may have occurred
|
||||
* The homeserver Url entered by the user during the login phase.
|
||||
*/
|
||||
val homeServerUrl = homeServerConnectionConfig.homeServerUri.toString()
|
||||
|
||||
/**
|
||||
* The current homeserver host
|
||||
* The current homeserver Url for client-server API. It can be different that the homeserver url entered
|
||||
* during login phase, because a redirection may have occurred
|
||||
*/
|
||||
val homeServerUrlBase = homeServerConnectionConfig.homeServerUriBase.toString()
|
||||
|
||||
/**
|
||||
* The current homeserver host, using what has been entered by the user during login phase
|
||||
*/
|
||||
val homeServerHost = homeServerConnectionConfig.homeServerUri.host
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ data class RegistrationFlowResponse(
|
|||
val completedStages: List<String>? = null,
|
||||
|
||||
/**
|
||||
* The session identifier that the client must pass back to the home server, if one is provided,
|
||||
* The session identifier that the client must pass back to the homeserver, if one is provided,
|
||||
* in subsequent attempts to authenticate in the same API call.
|
||||
*/
|
||||
@Json(name = "session")
|
||||
|
|
|
@ -22,11 +22,6 @@ import org.matrix.android.sdk.api.auth.data.WellKnown
|
|||
* Ref: https://matrix.org/docs/spec/client_server/latest#well-known-uri
|
||||
*/
|
||||
sealed class WellknownResult {
|
||||
/**
|
||||
* The provided matrixId is no valid. Unable to extract a domain name.
|
||||
*/
|
||||
object InvalidMatrixId : WellknownResult()
|
||||
|
||||
/**
|
||||
* Retrieve the specific piece of information from the user in a way which fits within the existing client user experience,
|
||||
* if the client is inclined to do so. Failure can take place instead if no good user experience for this is possible at this point.
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* 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.failure
|
||||
|
||||
sealed class MatrixIdFailure : Failure.FeatureFailure() {
|
||||
object InvalidMatrixId : MatrixIdFailure()
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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.logger
|
||||
|
||||
/**
|
||||
* Parent class for custom logger tags. Can be used with Timber :
|
||||
*
|
||||
* val loggerTag = LoggerTag("MyTag", LoggerTag.VOIP)
|
||||
* Timber.tag(loggerTag.value).v("My log message")
|
||||
*/
|
||||
open class LoggerTag(_value: String, parentTag: LoggerTag? = null) {
|
||||
|
||||
object VOIP : LoggerTag("VOIP")
|
||||
|
||||
val value: String = if (parentTag == null) {
|
||||
_value
|
||||
} else {
|
||||
"${parentTag.value}/$_value"
|
||||
}
|
||||
}
|
|
@ -29,8 +29,10 @@ interface RawService {
|
|||
|
||||
/**
|
||||
* Specific case for the well-known file. Cache validity is 8 hours
|
||||
* @param domain the domain to get the .well-known file, for instance "matrix.org".
|
||||
* The URL will be "https://{domain}/.well-known/matrix/client"
|
||||
*/
|
||||
suspend fun getWellknown(userId: String): String
|
||||
suspend fun getWellknown(domain: String): String
|
||||
|
||||
/**
|
||||
* Clear all the cache data
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
package org.matrix.android.sdk.api.session.call
|
||||
|
||||
import org.matrix.android.sdk.api.session.room.model.call.EndCallReason
|
||||
|
||||
sealed class CallState {
|
||||
|
||||
/** Idle, setting up objects */
|
||||
|
@ -42,6 +44,6 @@ sealed class CallState {
|
|||
* */
|
||||
data class Connected(val iceConnectionState: MxPeerConnectionState) : CallState()
|
||||
|
||||
/** Terminated. Incoming/Outgoing call, the call is terminated */
|
||||
object Terminated : CallState()
|
||||
/** Ended. Incoming/Outgoing call, the call is terminated */
|
||||
data class Ended(val reason: EndCallReason? = null) : CallState()
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ package org.matrix.android.sdk.api.session.call
|
|||
|
||||
import org.matrix.android.sdk.api.session.room.model.call.CallCandidate
|
||||
import org.matrix.android.sdk.api.session.room.model.call.CallCapabilities
|
||||
import org.matrix.android.sdk.api.session.room.model.call.CallHangupContent
|
||||
import org.matrix.android.sdk.api.session.room.model.call.EndCallReason
|
||||
import org.matrix.android.sdk.api.session.room.model.call.SdpType
|
||||
import org.matrix.android.sdk.api.util.Optional
|
||||
|
||||
|
@ -69,7 +69,7 @@ interface MxCall : MxCallDetail {
|
|||
/**
|
||||
* End the call
|
||||
*/
|
||||
fun hangUp(reason: CallHangupContent.Reason? = null)
|
||||
fun hangUp(reason: EndCallReason? = null)
|
||||
|
||||
/**
|
||||
* Start a call
|
||||
|
|
|
@ -28,7 +28,7 @@ import org.matrix.android.sdk.internal.crypto.store.SavedKeyBackupKeyInfo
|
|||
|
||||
interface KeysBackupService {
|
||||
/**
|
||||
* Retrieve the current version of the backup from the home server
|
||||
* Retrieve the current version of the backup from the homeserver
|
||||
*
|
||||
* It can be different than keysBackupVersion.
|
||||
* @param callback onSuccess(null) will be called if there is no backup on the server
|
||||
|
|
|
@ -54,7 +54,7 @@ enum class KeysBackupState {
|
|||
// Need to check the current backup version on the homeserver
|
||||
Unknown,
|
||||
|
||||
// Checking if backup is enabled on home server
|
||||
// Checking if backup is enabled on homeserver
|
||||
CheckingBackUpOnHomeserver,
|
||||
|
||||
// Backup has been stopped because a new backup version has been detected on the homeserver
|
||||
|
|
|
@ -104,7 +104,7 @@ data class Event(
|
|||
|
||||
/**
|
||||
* The `age` value transcoded in a timestamp based on the device clock when the SDK received
|
||||
* the event from the home server.
|
||||
* the event from the homeserver.
|
||||
* Unlike `age`, this value is static.
|
||||
*/
|
||||
@Transient
|
||||
|
|
|
@ -32,7 +32,13 @@ data class HomeServerCapabilities(
|
|||
/**
|
||||
* Default identity server url, provided in Wellknown
|
||||
*/
|
||||
val defaultIdentityServerUrl: String? = null
|
||||
val defaultIdentityServerUrl: String? = null,
|
||||
/**
|
||||
* Room versions supported by the server
|
||||
* This capability describes the default and available room versions a server supports, and at what level of stability.
|
||||
* Clients should make use of this capability to determine if users need to be encouraged to upgrade their rooms.
|
||||
*/
|
||||
val roomVersions: RoomVersionCapabilities? = null
|
||||
) {
|
||||
companion object {
|
||||
const val MAX_UPLOAD_FILE_SIZE_UNKNOWN = -1L
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright 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.homeserver
|
||||
|
||||
data class RoomVersionCapabilities(
|
||||
val defaultRoomVersion: String,
|
||||
val supportedVersion: List<RoomVersionInfo>
|
||||
)
|
||||
|
||||
data class RoomVersionInfo(
|
||||
val version: String,
|
||||
val status: RoomVersionStatus
|
||||
)
|
||||
|
||||
enum class RoomVersionStatus {
|
||||
STABLE,
|
||||
UNSTABLE
|
||||
}
|
|
@ -34,6 +34,7 @@ import org.matrix.android.sdk.api.session.room.tags.TagsService
|
|||
import org.matrix.android.sdk.api.session.room.timeline.TimelineService
|
||||
import org.matrix.android.sdk.api.session.room.typing.TypingService
|
||||
import org.matrix.android.sdk.api.session.room.uploads.UploadsService
|
||||
import org.matrix.android.sdk.api.session.room.version.RoomVersionService
|
||||
import org.matrix.android.sdk.api.session.search.SearchResult
|
||||
import org.matrix.android.sdk.api.session.space.Space
|
||||
import org.matrix.android.sdk.api.util.Optional
|
||||
|
@ -57,7 +58,8 @@ interface Room :
|
|||
RelationService,
|
||||
RoomCryptoService,
|
||||
RoomPushRuleService,
|
||||
RoomAccountDataService {
|
||||
RoomAccountDataService,
|
||||
RoomVersionService {
|
||||
|
||||
/**
|
||||
* The roomId of this room
|
||||
|
|
|
@ -39,12 +39,6 @@ fun spaceSummaryQueryParams(init: (RoomSummaryQueryParams.Builder.() -> Unit) =
|
|||
.build()
|
||||
}
|
||||
|
||||
enum class RoomCategoryFilter {
|
||||
ONLY_DM,
|
||||
ONLY_ROOMS,
|
||||
ALL
|
||||
}
|
||||
|
||||
/**
|
||||
* This class can be used to filter room summaries to use with:
|
||||
* [org.matrix.android.sdk.api.session.room.Room] and [org.matrix.android.sdk.api.session.room.RoomService]
|
||||
|
@ -59,11 +53,10 @@ data class RoomSummaryQueryParams(
|
|||
val excludeType: List<String?>?,
|
||||
val includeType: List<String?>?,
|
||||
val activeSpaceFilter: ActiveSpaceFilter?,
|
||||
var activeGroupId: String? = null
|
||||
val activeGroupId: String? = null
|
||||
) {
|
||||
|
||||
class Builder {
|
||||
|
||||
var roomId: QueryStringValue = QueryStringValue.IsNotEmpty
|
||||
var displayName: QueryStringValue = QueryStringValue.IsNotEmpty
|
||||
var canonicalAlias: QueryStringValue = QueryStringValue.NoCondition
|
||||
|
|
|
@ -43,29 +43,5 @@ data class CallHangupContent(
|
|||
* or `invite_timeout` for when the other party did not answer in time.
|
||||
* One of: ["ice_failed", "invite_timeout"]
|
||||
*/
|
||||
@Json(name = "reason") val reason: Reason? = null
|
||||
) : CallSignalingContent {
|
||||
@JsonClass(generateAdapter = false)
|
||||
enum class Reason {
|
||||
@Json(name = "ice_failed")
|
||||
ICE_FAILED,
|
||||
|
||||
@Json(name = "ice_timeout")
|
||||
ICE_TIMEOUT,
|
||||
|
||||
@Json(name = "user_hangup")
|
||||
USER_HANGUP,
|
||||
|
||||
@Json(name = "replaced")
|
||||
REPLACED,
|
||||
|
||||
@Json(name = "user_media_failed")
|
||||
USER_MEDIA_FAILED,
|
||||
|
||||
@Json(name = "invite_timeout")
|
||||
INVITE_TIMEOUT,
|
||||
|
||||
@Json(name = "unknown_error")
|
||||
UNKWOWN_ERROR
|
||||
}
|
||||
}
|
||||
@Json(name = "reason") val reason: EndCallReason? = null
|
||||
) : CallSignalingContent
|
||||
|
|
|
@ -36,5 +36,10 @@ data class CallRejectContent(
|
|||
/**
|
||||
* Required. The version of the VoIP specification this message adheres to.
|
||||
*/
|
||||
@Json(name = "version") override val version: String?
|
||||
@Json(name = "version") override val version: String?,
|
||||
|
||||
/**
|
||||
* Optional error reason for the reject.
|
||||
*/
|
||||
@Json(name = "reason") val reason: EndCallReason? = null
|
||||
) : CallSignalingContent
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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.room.model.call
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = false)
|
||||
enum class EndCallReason {
|
||||
@Json(name = "ice_failed")
|
||||
ICE_FAILED,
|
||||
|
||||
@Json(name = "ice_timeout")
|
||||
ICE_TIMEOUT,
|
||||
|
||||
@Json(name = "user_hangup")
|
||||
USER_HANGUP,
|
||||
|
||||
@Json(name = "replaced")
|
||||
REPLACED,
|
||||
|
||||
@Json(name = "user_media_failed")
|
||||
USER_MEDIA_FAILED,
|
||||
|
||||
@Json(name = "invite_timeout")
|
||||
INVITE_TIMEOUT,
|
||||
|
||||
@Json(name = "unknown_error")
|
||||
UNKWOWN_ERROR,
|
||||
|
||||
@Json(name = "user_busy")
|
||||
USER_BUSY,
|
||||
|
||||
@Json(name = "answered_elsewhere")
|
||||
ANSWERED_ELSEWHERE
|
||||
}
|
|
@ -25,7 +25,6 @@ import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
|
|||
import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesAllowEntry
|
||||
import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
|
||||
|
||||
// TODO Give a way to include other initial states
|
||||
open class CreateRoomParams {
|
||||
/**
|
||||
* A public visibility indicates that the room will be shown in the published room list.
|
||||
|
@ -103,6 +102,13 @@ open class CreateRoomParams {
|
|||
*/
|
||||
val creationContent = mutableMapOf<String, Any>()
|
||||
|
||||
/**
|
||||
* A list of state events to set in the new room. This allows the user to override the default state events
|
||||
* set in the new room. The expected format of the state events are an object with type, state_key and content keys set.
|
||||
* Takes precedence over events set by preset, but gets overridden by name and topic keys.
|
||||
*/
|
||||
val initialStates = mutableListOf<CreateRoomStateEvent>()
|
||||
|
||||
/**
|
||||
* Set to true to disable federation of this room.
|
||||
* Default: false
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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.room.model.create
|
||||
|
||||
import org.matrix.android.sdk.api.session.events.model.Content
|
||||
|
||||
data class CreateRoomStateEvent(
|
||||
/**
|
||||
* Required. The type of event to send.
|
||||
*/
|
||||
val type: String,
|
||||
|
||||
/**
|
||||
* Required. The content of the event.
|
||||
*/
|
||||
val content: Content,
|
||||
|
||||
/**
|
||||
* The state_key of the state event. Defaults to an empty string.
|
||||
*/
|
||||
val stateKey: String = ""
|
||||
)
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright 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.room.version
|
||||
|
||||
interface RoomVersionService {
|
||||
/**
|
||||
* Return the room version of this room
|
||||
*/
|
||||
fun getRoomVersion(): String
|
||||
|
||||
/**
|
||||
* Upgrade to the given room version
|
||||
* @return the replacement room id
|
||||
*/
|
||||
suspend fun upgradeToVersion(version: String): String
|
||||
|
||||
/**
|
||||
* Get the recommended room version for the current homeserver
|
||||
*/
|
||||
fun getRecommendedVersion() : String
|
||||
|
||||
/**
|
||||
* Ask if the user has enough power level to upgrade the room
|
||||
*/
|
||||
fun userMayUpgradeRoom(userId: String): Boolean
|
||||
|
||||
/**
|
||||
* Return true if the current room version is declared unstable by the homeserver
|
||||
*/
|
||||
fun isUsingUnstableRoomVersion(): Boolean
|
||||
}
|
|
@ -18,6 +18,7 @@ package org.matrix.android.sdk.api.session.space
|
|||
|
||||
import org.matrix.android.sdk.api.session.room.Room
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import org.matrix.android.sdk.api.session.space.model.SpaceChildContent
|
||||
|
||||
interface Space {
|
||||
|
||||
|
@ -38,6 +39,8 @@ interface Space {
|
|||
autoJoin: Boolean = false,
|
||||
suggested: Boolean? = false)
|
||||
|
||||
fun getChildInfo(roomId: String): SpaceChildContent?
|
||||
|
||||
suspend fun removeChildren(roomId: String)
|
||||
|
||||
@Throws
|
||||
|
|
|
@ -21,8 +21,8 @@ import org.matrix.android.sdk.api.util.JsonDict
|
|||
import org.matrix.android.sdk.internal.auth.data.Availability
|
||||
import org.matrix.android.sdk.internal.auth.data.LoginFlowResponse
|
||||
import org.matrix.android.sdk.internal.auth.data.PasswordLoginParams
|
||||
import org.matrix.android.sdk.internal.auth.data.RiotConfig
|
||||
import org.matrix.android.sdk.internal.auth.data.TokenLoginParams
|
||||
import org.matrix.android.sdk.internal.auth.data.WebClientConfig
|
||||
import org.matrix.android.sdk.internal.auth.login.ResetPasswordMailConfirmed
|
||||
import org.matrix.android.sdk.internal.auth.registration.AddThreePidRegistrationParams
|
||||
import org.matrix.android.sdk.internal.auth.registration.AddThreePidRegistrationResponse
|
||||
|
@ -44,16 +44,16 @@ import retrofit2.http.Url
|
|||
*/
|
||||
internal interface AuthAPI {
|
||||
/**
|
||||
* Get a Riot config file, using the name including the domain
|
||||
* Get a Web client config file, using the name including the domain
|
||||
*/
|
||||
@GET("config.{domain}.json")
|
||||
suspend fun getRiotConfigDomain(@Path("domain") domain: String): RiotConfig
|
||||
suspend fun getWebClientConfigDomain(@Path("domain") domain: String): WebClientConfig
|
||||
|
||||
/**
|
||||
* Get a Riot config file
|
||||
* Get a Web client default config file
|
||||
*/
|
||||
@GET("config.json")
|
||||
suspend fun getRiotConfig(): RiotConfig
|
||||
suspend fun getWebClientConfig(): WebClientConfig
|
||||
|
||||
/**
|
||||
* Get the version information of the homeserver
|
||||
|
|
|
@ -19,6 +19,8 @@ package org.matrix.android.sdk.internal.auth
|
|||
import android.net.Uri
|
||||
import dagger.Lazy
|
||||
import okhttp3.OkHttpClient
|
||||
import org.matrix.android.sdk.api.MatrixPatterns
|
||||
import org.matrix.android.sdk.api.MatrixPatterns.getDomain
|
||||
import org.matrix.android.sdk.api.auth.AuthenticationService
|
||||
import org.matrix.android.sdk.api.auth.data.Credentials
|
||||
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
|
||||
|
@ -28,10 +30,11 @@ import org.matrix.android.sdk.api.auth.login.LoginWizard
|
|||
import org.matrix.android.sdk.api.auth.registration.RegistrationWizard
|
||||
import org.matrix.android.sdk.api.auth.wellknown.WellknownResult
|
||||
import org.matrix.android.sdk.api.failure.Failure
|
||||
import org.matrix.android.sdk.api.failure.MatrixIdFailure
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.api.util.appendParamToUrl
|
||||
import org.matrix.android.sdk.internal.SessionManager
|
||||
import org.matrix.android.sdk.internal.auth.data.RiotConfig
|
||||
import org.matrix.android.sdk.internal.auth.data.WebClientConfig
|
||||
import org.matrix.android.sdk.internal.auth.db.PendingSessionData
|
||||
import org.matrix.android.sdk.internal.auth.login.DefaultLoginWizard
|
||||
import org.matrix.android.sdk.internal.auth.login.DirectLoginTask
|
||||
|
@ -122,7 +125,7 @@ internal class DefaultAuthenticationService @Inject constructor(
|
|||
private fun getHomeServerUrlBase(): String? {
|
||||
return pendingSessionData
|
||||
?.homeServerConnectionConfig
|
||||
?.homeServerUri
|
||||
?.homeServerUriBase
|
||||
?.toString()
|
||||
?.trim { it == '/' }
|
||||
}
|
||||
|
@ -143,9 +146,9 @@ internal class DefaultAuthenticationService @Inject constructor(
|
|||
return result.fold(
|
||||
{
|
||||
// The homeserver exists and up to date, keep the config
|
||||
// Homeserver url may have been changed, if it was a Riot url
|
||||
// Homeserver url may have been changed, if it was a Web client url
|
||||
val alteredHomeServerConnectionConfig = homeServerConnectionConfig.copy(
|
||||
homeServerUri = Uri.parse(it.homeServerUrl)
|
||||
homeServerUriBase = Uri.parse(it.homeServerUrl)
|
||||
)
|
||||
|
||||
pendingSessionData = PendingSessionData(alteredHomeServerConnectionConfig)
|
||||
|
@ -154,7 +157,7 @@ internal class DefaultAuthenticationService @Inject constructor(
|
|||
},
|
||||
{
|
||||
if (it is UnrecognizedCertificateException) {
|
||||
throw Failure.UnrecognizedCertificateFailure(homeServerConnectionConfig.homeServerUri.toString(), it.fingerprint)
|
||||
throw Failure.UnrecognizedCertificateFailure(homeServerConnectionConfig.homeServerUriBase.toString(), it.fingerprint)
|
||||
} else {
|
||||
throw it
|
||||
}
|
||||
|
@ -165,46 +168,57 @@ internal class DefaultAuthenticationService @Inject constructor(
|
|||
private suspend fun getLoginFlowInternal(homeServerConnectionConfig: HomeServerConnectionConfig): LoginFlowResult {
|
||||
val authAPI = buildAuthAPI(homeServerConnectionConfig)
|
||||
|
||||
// First check the homeserver version
|
||||
return runCatching {
|
||||
executeRequest(null) {
|
||||
authAPI.versions()
|
||||
// First check if there is a well-known file
|
||||
return try {
|
||||
getWellknownLoginFlowInternal(homeServerConnectionConfig)
|
||||
} catch (failure: Throwable) {
|
||||
if (failure is Failure.OtherServerError
|
||||
&& failure.httpCode == HttpsURLConnection.HTTP_NOT_FOUND /* 404 */) {
|
||||
// 404, no well-known data, try direct access to the API
|
||||
// First check the homeserver version
|
||||
return runCatching {
|
||||
executeRequest(null) {
|
||||
authAPI.versions()
|
||||
}
|
||||
}
|
||||
.map { versions ->
|
||||
// Ok, it seems that the homeserver url is valid
|
||||
getLoginFlowResult(authAPI, versions, homeServerConnectionConfig.homeServerUriBase.toString())
|
||||
}
|
||||
.fold(
|
||||
{
|
||||
it
|
||||
},
|
||||
{
|
||||
if (it is Failure.OtherServerError
|
||||
&& it.httpCode == HttpsURLConnection.HTTP_NOT_FOUND /* 404 */) {
|
||||
// It's maybe a Web client url?
|
||||
getWebClientDomainLoginFlowInternal(homeServerConnectionConfig)
|
||||
} else {
|
||||
throw it
|
||||
}
|
||||
}
|
||||
)
|
||||
} else {
|
||||
throw failure
|
||||
}
|
||||
}
|
||||
.map { versions ->
|
||||
// Ok, it seems that the homeserver url is valid
|
||||
getLoginFlowResult(authAPI, versions, homeServerConnectionConfig.homeServerUri.toString())
|
||||
}
|
||||
.fold(
|
||||
{
|
||||
it
|
||||
},
|
||||
{
|
||||
if (it is Failure.OtherServerError
|
||||
&& it.httpCode == HttpsURLConnection.HTTP_NOT_FOUND /* 404 */) {
|
||||
// It's maybe a Riot url?
|
||||
getRiotDomainLoginFlowInternal(homeServerConnectionConfig)
|
||||
} else {
|
||||
throw it
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun getRiotDomainLoginFlowInternal(homeServerConnectionConfig: HomeServerConnectionConfig): LoginFlowResult {
|
||||
private suspend fun getWebClientDomainLoginFlowInternal(homeServerConnectionConfig: HomeServerConnectionConfig): LoginFlowResult {
|
||||
val authAPI = buildAuthAPI(homeServerConnectionConfig)
|
||||
|
||||
val domain = homeServerConnectionConfig.homeServerUri.host
|
||||
?: return getRiotLoginFlowInternal(homeServerConnectionConfig)
|
||||
?: return getWebClientLoginFlowInternal(homeServerConnectionConfig)
|
||||
|
||||
// Ok, try to get the config.domain.json file of a RiotWeb client
|
||||
// Ok, try to get the config.domain.json file of a Web client
|
||||
return runCatching {
|
||||
executeRequest(null) {
|
||||
authAPI.getRiotConfigDomain(domain)
|
||||
authAPI.getWebClientConfigDomain(domain)
|
||||
}
|
||||
}
|
||||
.map { riotConfig ->
|
||||
onRiotConfigRetrieved(homeServerConnectionConfig, riotConfig)
|
||||
.map { webClientConfig ->
|
||||
onWebClientConfigRetrieved(homeServerConnectionConfig, webClientConfig)
|
||||
}
|
||||
.fold(
|
||||
{
|
||||
|
@ -214,7 +228,7 @@ internal class DefaultAuthenticationService @Inject constructor(
|
|||
if (it is Failure.OtherServerError
|
||||
&& it.httpCode == HttpsURLConnection.HTTP_NOT_FOUND /* 404 */) {
|
||||
// Try with config.json
|
||||
getRiotLoginFlowInternal(homeServerConnectionConfig)
|
||||
getWebClientLoginFlowInternal(homeServerConnectionConfig)
|
||||
} else {
|
||||
throw it
|
||||
}
|
||||
|
@ -222,40 +236,24 @@ internal class DefaultAuthenticationService @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private suspend fun getRiotLoginFlowInternal(homeServerConnectionConfig: HomeServerConnectionConfig): LoginFlowResult {
|
||||
private suspend fun getWebClientLoginFlowInternal(homeServerConnectionConfig: HomeServerConnectionConfig): LoginFlowResult {
|
||||
val authAPI = buildAuthAPI(homeServerConnectionConfig)
|
||||
|
||||
// Ok, try to get the config.json file of a RiotWeb client
|
||||
return runCatching {
|
||||
executeRequest(null) {
|
||||
authAPI.getRiotConfig()
|
||||
}
|
||||
// Ok, try to get the config.json file of a Web client
|
||||
return executeRequest(null) {
|
||||
authAPI.getWebClientConfig()
|
||||
}
|
||||
.map { riotConfig ->
|
||||
onRiotConfigRetrieved(homeServerConnectionConfig, riotConfig)
|
||||
.let { webClientConfig ->
|
||||
onWebClientConfigRetrieved(homeServerConnectionConfig, webClientConfig)
|
||||
}
|
||||
.fold(
|
||||
{
|
||||
it
|
||||
},
|
||||
{
|
||||
if (it is Failure.OtherServerError
|
||||
&& it.httpCode == HttpsURLConnection.HTTP_NOT_FOUND /* 404 */) {
|
||||
// Try with wellknown
|
||||
getWellknownLoginFlowInternal(homeServerConnectionConfig)
|
||||
} else {
|
||||
throw it
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun onRiotConfigRetrieved(homeServerConnectionConfig: HomeServerConnectionConfig, riotConfig: RiotConfig): LoginFlowResult {
|
||||
val defaultHomeServerUrl = riotConfig.getPreferredHomeServerUrl()
|
||||
private suspend fun onWebClientConfigRetrieved(homeServerConnectionConfig: HomeServerConnectionConfig, webClientConfig: WebClientConfig): LoginFlowResult {
|
||||
val defaultHomeServerUrl = webClientConfig.getPreferredHomeServerUrl()
|
||||
if (defaultHomeServerUrl?.isNotEmpty() == true) {
|
||||
// Ok, good sign, we got a default hs url
|
||||
val newHomeServerConnectionConfig = homeServerConnectionConfig.copy(
|
||||
homeServerUri = Uri.parse(defaultHomeServerUrl)
|
||||
homeServerUriBase = Uri.parse(defaultHomeServerUrl)
|
||||
)
|
||||
|
||||
val newAuthAPI = buildAuthAPI(newHomeServerConnectionConfig)
|
||||
|
@ -275,15 +273,13 @@ internal class DefaultAuthenticationService @Inject constructor(
|
|||
val domain = homeServerConnectionConfig.homeServerUri.host
|
||||
?: throw Failure.OtherServerError("", HttpsURLConnection.HTTP_NOT_FOUND /* 404 */)
|
||||
|
||||
// Create a fake userId, for the getWellknown task
|
||||
val fakeUserId = "@alice:$domain"
|
||||
val wellknownResult = getWellknownTask.execute(GetWellknownTask.Params(fakeUserId, homeServerConnectionConfig))
|
||||
val wellknownResult = getWellknownTask.execute(GetWellknownTask.Params(domain, homeServerConnectionConfig))
|
||||
|
||||
return when (wellknownResult) {
|
||||
is WellknownResult.Prompt -> {
|
||||
val newHomeServerConnectionConfig = homeServerConnectionConfig.copy(
|
||||
homeServerUri = Uri.parse(wellknownResult.homeServerUrl),
|
||||
identityServerUri = wellknownResult.identityServerUrl?.let { Uri.parse(it) }
|
||||
homeServerUriBase = Uri.parse(wellknownResult.homeServerUrl),
|
||||
identityServerUri = wellknownResult.identityServerUrl?.let { Uri.parse(it) } ?: homeServerConnectionConfig.identityServerUri
|
||||
)
|
||||
|
||||
val newAuthAPI = buildAuthAPI(newHomeServerConnectionConfig)
|
||||
|
@ -379,7 +375,14 @@ internal class DefaultAuthenticationService @Inject constructor(
|
|||
|
||||
override suspend fun getWellKnownData(matrixId: String,
|
||||
homeServerConnectionConfig: HomeServerConnectionConfig?): WellknownResult {
|
||||
return getWellknownTask.execute(GetWellknownTask.Params(matrixId, homeServerConnectionConfig))
|
||||
if (!MatrixPatterns.isUserId(matrixId)) {
|
||||
throw MatrixIdFailure.InvalidMatrixId
|
||||
}
|
||||
|
||||
return getWellknownTask.execute(GetWellknownTask.Params(
|
||||
domain = matrixId.getDomain(),
|
||||
homeServerConnectionConfig = homeServerConnectionConfig)
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun directAuthentication(homeServerConnectionConfig: HomeServerConnectionConfig,
|
||||
|
@ -390,7 +393,7 @@ internal class DefaultAuthenticationService @Inject constructor(
|
|||
}
|
||||
|
||||
private fun buildAuthAPI(homeServerConnectionConfig: HomeServerConnectionConfig): AuthAPI {
|
||||
val retrofit = retrofitFactory.create(buildClient(homeServerConnectionConfig), homeServerConnectionConfig.homeServerUri.toString())
|
||||
val retrofit = retrofitFactory.create(buildClient(homeServerConnectionConfig), homeServerConnectionConfig.homeServerUriBase.toString())
|
||||
return retrofit.create(AuthAPI::class.java)
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ internal class DefaultIsValidClientServerApiTask @Inject constructor(
|
|||
|
||||
override suspend fun execute(params: IsValidClientServerApiTask.Params): Boolean {
|
||||
val client = buildClient(params.homeServerConnectionConfig)
|
||||
val homeServerUrl = params.homeServerConnectionConfig.homeServerUri.toString()
|
||||
val homeServerUrl = params.homeServerConnectionConfig.homeServerUriBase.toString()
|
||||
|
||||
val authAPI = retrofitFactory.create(client, homeServerUrl)
|
||||
.create(AuthAPI::class.java)
|
||||
|
|
|
@ -38,7 +38,7 @@ internal class DefaultSessionCreator @Inject constructor(
|
|||
) : SessionCreator {
|
||||
|
||||
/**
|
||||
* Credentials can affect the homeServerConnectionConfig, override home server url and/or
|
||||
* Credentials can affect the homeServerConnectionConfig, override homeserver url and/or
|
||||
* identity server url if provided in the credentials
|
||||
*/
|
||||
override suspend fun createSession(credentials: Credentials, homeServerConnectionConfig: HomeServerConnectionConfig): Session {
|
||||
|
@ -56,7 +56,7 @@ internal class DefaultSessionCreator @Inject constructor(
|
|||
tryOrNull {
|
||||
isValidClientServerApiTask.execute(
|
||||
IsValidClientServerApiTask.Params(
|
||||
homeServerConnectionConfig.copy(homeServerUri = it)
|
||||
homeServerConnectionConfig.copy(homeServerUriBase = it)
|
||||
)
|
||||
)
|
||||
.also { Timber.d("Overriding homeserver url: $it") }
|
||||
|
@ -66,7 +66,7 @@ internal class DefaultSessionCreator @Inject constructor(
|
|||
val sessionParams = SessionParams(
|
||||
credentials = credentials,
|
||||
homeServerConnectionConfig = homeServerConnectionConfig.copy(
|
||||
homeServerUri = overriddenUrl ?: homeServerConnectionConfig.homeServerUri,
|
||||
homeServerUriBase = overriddenUrl ?: homeServerConnectionConfig.homeServerUriBase,
|
||||
identityServerUri = credentials.discoveryInformation?.identityServer?.baseURL
|
||||
// remove trailing "/"
|
||||
?.trim { it == '/' }
|
||||
|
|
|
@ -20,7 +20,7 @@ import com.squareup.moshi.Json
|
|||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal data class RiotConfig(
|
||||
internal data class WebClientConfig(
|
||||
/**
|
||||
* This is now deprecated, but still used first, rather than value from "default_server_config"
|
||||
*/
|
||||
|
@ -28,7 +28,7 @@ internal data class RiotConfig(
|
|||
val defaultHomeServerUrl: String?,
|
||||
|
||||
@Json(name = "default_server_config")
|
||||
val defaultServerConfig: RiotConfigDefaultServerConfig?
|
||||
val defaultServerConfig: WebClientConfigDefaultServerConfig?
|
||||
) {
|
||||
fun getPreferredHomeServerUrl(): String? {
|
||||
return defaultHomeServerUrl
|
||||
|
@ -38,13 +38,13 @@ internal data class RiotConfig(
|
|||
}
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal data class RiotConfigDefaultServerConfig(
|
||||
internal data class WebClientConfigDefaultServerConfig(
|
||||
@Json(name = "m.homeserver")
|
||||
val homeServer: RiotConfigBaseConfig? = null
|
||||
val homeServer: WebClientConfigBaseConfig? = null
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal data class RiotConfigBaseConfig(
|
||||
internal data class WebClientConfigBaseConfig(
|
||||
@Json(name = "base_url")
|
||||
val baseURL: String? = null
|
||||
)
|
|
@ -16,17 +16,19 @@
|
|||
|
||||
package org.matrix.android.sdk.internal.auth.db
|
||||
|
||||
import org.matrix.android.sdk.api.auth.data.Credentials
|
||||
import org.matrix.android.sdk.api.auth.data.sessionId
|
||||
import org.matrix.android.sdk.internal.di.MoshiProvider
|
||||
import android.net.Uri
|
||||
import io.realm.DynamicRealm
|
||||
import io.realm.RealmMigration
|
||||
import org.matrix.android.sdk.api.auth.data.Credentials
|
||||
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
|
||||
import org.matrix.android.sdk.api.auth.data.sessionId
|
||||
import org.matrix.android.sdk.internal.di.MoshiProvider
|
||||
import timber.log.Timber
|
||||
|
||||
internal object AuthRealmMigration : RealmMigration {
|
||||
|
||||
// Current schema version
|
||||
const val SCHEMA_VERSION = 3L
|
||||
const val SCHEMA_VERSION = 4L
|
||||
|
||||
override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
|
||||
Timber.d("Migrating Auth Realm from $oldVersion to $newVersion")
|
||||
|
@ -34,6 +36,7 @@ internal object AuthRealmMigration : RealmMigration {
|
|||
if (oldVersion <= 0) migrateTo1(realm)
|
||||
if (oldVersion <= 1) migrateTo2(realm)
|
||||
if (oldVersion <= 2) migrateTo3(realm)
|
||||
if (oldVersion <= 3) migrateTo4(realm)
|
||||
}
|
||||
|
||||
private fun migrateTo1(realm: DynamicRealm) {
|
||||
|
@ -81,4 +84,34 @@ internal object AuthRealmMigration : RealmMigration {
|
|||
}
|
||||
?.addPrimaryKey(SessionParamsEntityFields.SESSION_ID)
|
||||
}
|
||||
|
||||
private fun migrateTo4(realm: DynamicRealm) {
|
||||
Timber.d("Step 3 -> 4")
|
||||
Timber.d("Update SessionParamsEntity to add HomeServerConnectionConfig.homeServerUriBase value")
|
||||
|
||||
val adapter = MoshiProvider.providesMoshi()
|
||||
.adapter(HomeServerConnectionConfig::class.java)
|
||||
|
||||
realm.schema.get("SessionParamsEntity")
|
||||
?.transform {
|
||||
val homeserverConnectionConfigJson = it.getString(SessionParamsEntityFields.HOME_SERVER_CONNECTION_CONFIG_JSON)
|
||||
|
||||
val homeserverConnectionConfig = adapter
|
||||
.fromJson(homeserverConnectionConfigJson)
|
||||
|
||||
val homeserverUrl = homeserverConnectionConfig?.homeServerUri?.toString()
|
||||
// Special case for matrix.org. Old session may use "https://matrix.org", newer one may use
|
||||
// "https://matrix-client.matrix.org". So fix that here
|
||||
val alteredHomeserverConnectionConfig =
|
||||
if (homeserverUrl == "https://matrix.org" || homeserverUrl == "https://matrix-client.matrix.org") {
|
||||
homeserverConnectionConfig.copy(
|
||||
homeServerUri = Uri.parse("https://matrix.org"),
|
||||
homeServerUriBase = Uri.parse("https://matrix-client.matrix.org")
|
||||
)
|
||||
} else {
|
||||
homeserverConnectionConfig
|
||||
}
|
||||
it.set(SessionParamsEntityFields.HOME_SERVER_CONNECTION_CONFIG_JSON, adapter.toJson(alteredHomeserverConnectionConfig))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ internal class DefaultDirectLoginTask @Inject constructor(
|
|||
|
||||
override suspend fun execute(params: DirectLoginTask.Params): Session {
|
||||
val client = buildClient(params.homeServerConnectionConfig)
|
||||
val homeServerUrl = params.homeServerConnectionConfig.homeServerUri.toString()
|
||||
val homeServerUrl = params.homeServerConnectionConfig.homeServerUriBase.toString()
|
||||
|
||||
val authAPI = retrofitFactory.create(client, homeServerUrl)
|
||||
.create(AuthAPI::class.java)
|
||||
|
|
|
@ -314,6 +314,12 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
cryptoCoroutineScope.launchToCallback(coroutineDispatchers.crypto, NoOpMatrixCallback()) {
|
||||
// Open the store
|
||||
cryptoStore.open()
|
||||
|
||||
if (!cryptoStore.areDeviceKeysUploaded()) {
|
||||
// Schedule upload of OTK
|
||||
oneTimeKeysUploader.updateOneTimeKeyCount(0)
|
||||
}
|
||||
|
||||
// this can throw if no network
|
||||
tryOrNull {
|
||||
uploadDeviceKeys()
|
||||
|
@ -905,7 +911,7 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
* Upload my user's device keys.
|
||||
*/
|
||||
private suspend fun uploadDeviceKeys() {
|
||||
if (cryptoStore.getDeviceKeysUploaded()) {
|
||||
if (cryptoStore.areDeviceKeysUploaded()) {
|
||||
Timber.d("Keys already uploaded, nothing to do")
|
||||
return
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package org.matrix.android.sdk.internal.crypto
|
||||
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.android.sdk.api.MatrixPatterns
|
||||
import org.matrix.android.sdk.api.auth.data.Credentials
|
||||
|
@ -336,7 +337,12 @@ internal class DeviceListManager @Inject constructor(private val cryptoStore: IM
|
|||
downloadKeysForUsersTask.execute(params)
|
||||
} catch (throwable: Throwable) {
|
||||
Timber.e(throwable, "## CRYPTO | doKeyDownloadForUsers(): error")
|
||||
onKeysDownloadFailed(filteredUsers)
|
||||
if (throwable is CancellationException) {
|
||||
// the crypto module is getting closed, so we cannot access the DB anymore
|
||||
Timber.w("The crypto module is closed, ignoring this error")
|
||||
} else {
|
||||
onKeysDownloadFailed(filteredUsers)
|
||||
}
|
||||
throw throwable
|
||||
}
|
||||
Timber.v("## CRYPTO | doKeyDownloadForUsers() : Got keys for " + filteredUsers.size + " users")
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package org.matrix.android.sdk.internal.crypto
|
||||
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.internal.crypto.model.MXKey
|
||||
import org.matrix.android.sdk.internal.crypto.model.rest.KeysUploadResponse
|
||||
import org.matrix.android.sdk.internal.crypto.tasks.UploadKeysTask
|
||||
|
@ -77,6 +78,10 @@ internal class OneTimeKeysUploader @Inject constructor(
|
|||
// discard the oldest private keys first. This will eventually clean
|
||||
// out stale private keys that won't receive a message.
|
||||
val keyLimit = floor(maxOneTimeKeys / 2.0).toInt()
|
||||
if (oneTimeKeyCount == null) {
|
||||
// Ask the server how many otk he has
|
||||
oneTimeKeyCount = fetchOtkCount()
|
||||
}
|
||||
val oneTimeKeyCountFromSync = oneTimeKeyCount
|
||||
if (oneTimeKeyCountFromSync != null) {
|
||||
// We need to keep a pool of one time public keys on the server so that
|
||||
|
@ -90,17 +95,22 @@ internal class OneTimeKeysUploader @Inject constructor(
|
|||
// private keys clogging up our local storage.
|
||||
// So we need some kind of engineering compromise to balance all of
|
||||
// these factors.
|
||||
try {
|
||||
tryOrNull("Unable to upload OTK") {
|
||||
val uploadedKeys = uploadOTK(oneTimeKeyCountFromSync, keyLimit)
|
||||
Timber.v("## uploadKeys() : success, $uploadedKeys key(s) sent")
|
||||
} finally {
|
||||
oneTimeKeyCheckInProgress = false
|
||||
}
|
||||
} else {
|
||||
Timber.w("maybeUploadOneTimeKeys: waiting to know the number of OTK from the sync")
|
||||
oneTimeKeyCheckInProgress = false
|
||||
lastOneTimeKeyCheck = 0
|
||||
}
|
||||
oneTimeKeyCheckInProgress = false
|
||||
}
|
||||
|
||||
private suspend fun fetchOtkCount(): Int? {
|
||||
return tryOrNull("Unable to get OTK count") {
|
||||
val result = uploadKeysTask.execute(UploadKeysTask.Params(null, null))
|
||||
result.oneTimeKeyCountsForAlgorithm(MXKey.KEY_SIGNED_CURVE_25519_TYPE)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -56,7 +56,7 @@ data class MXDeviceInfo(
|
|||
val signatures: Map<String, Map<String, String>>? = null,
|
||||
|
||||
/*
|
||||
* Additional data from the home server.
|
||||
* Additional data from the homeserver.
|
||||
*/
|
||||
@Json(name = "unsigned")
|
||||
val unsigned: JsonDict? = null,
|
||||
|
|
|
@ -475,7 +475,7 @@ internal interface IMXCryptoStore {
|
|||
fun getGossipingEvents(): List<Event>
|
||||
|
||||
fun setDeviceKeysUploaded(uploaded: Boolean)
|
||||
fun getDeviceKeysUploaded(): Boolean
|
||||
fun areDeviceKeysUploaded(): Boolean
|
||||
fun tidyUpDataBase()
|
||||
fun logDbUsageInfo()
|
||||
}
|
||||
|
|
|
@ -937,7 +937,7 @@ internal class RealmCryptoStore @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
override fun getDeviceKeysUploaded(): Boolean {
|
||||
override fun areDeviceKeysUploaded(): Boolean {
|
||||
return doWithRealm(realmConfiguration) {
|
||||
it.where<CryptoMetadataEntity>().findFirst()?.deviceKeysSentToServer
|
||||
} ?: false
|
||||
|
|
|
@ -97,7 +97,7 @@ internal class DefaultInitializeCrossSigningTask @Inject constructor(
|
|||
|
||||
Timber.v("## CrossSigning - sskPublicKey:$sskPublicKey")
|
||||
|
||||
// Sign userSigningKey with master
|
||||
// Sign selfSigningKey with master
|
||||
val signedSSK = CryptoCrossSigningKey.Builder(userId, KeyUsage.SELF_SIGNING)
|
||||
.key(sskPublicKey)
|
||||
.build()
|
||||
|
|
|
@ -68,7 +68,7 @@ internal class VerificationTransportToDevice(
|
|||
contentMap.setObject(otherUserId, it, keyReq)
|
||||
}
|
||||
sendToDeviceTask
|
||||
.configureWith(SendToDeviceTask.Params(MessageType.MSGTYPE_VERIFICATION_REQUEST, contentMap, localId)) {
|
||||
.configureWith(SendToDeviceTask.Params(MessageType.MSGTYPE_VERIFICATION_REQUEST, contentMap)) {
|
||||
this.callback = object : MatrixCallback<Unit> {
|
||||
override fun onSuccess(data: Unit) {
|
||||
Timber.v("## verification [$tx.transactionId] send toDevice request success")
|
||||
|
@ -124,7 +124,7 @@ internal class VerificationTransportToDevice(
|
|||
contentMap.setObject(tx.otherUserId, tx.otherDeviceId, toSendToDeviceObject)
|
||||
|
||||
sendToDeviceTask
|
||||
.configureWith(SendToDeviceTask.Params(type, contentMap, tx.transactionId)) {
|
||||
.configureWith(SendToDeviceTask.Params(type, contentMap)) {
|
||||
this.callback = object : MatrixCallback<Unit> {
|
||||
override fun onSuccess(data: Unit) {
|
||||
Timber.v("## SAS verification [$tx.transactionId] toDevice type '$type' success.")
|
||||
|
@ -155,7 +155,7 @@ internal class VerificationTransportToDevice(
|
|||
val contentMap = MXUsersDevicesMap<Any>()
|
||||
contentMap.setObject(otherUserId, otherUserDeviceId, cancelMessage)
|
||||
sendToDeviceTask
|
||||
.configureWith(SendToDeviceTask.Params(EventType.KEY_VERIFICATION_DONE, contentMap, transactionId)) {
|
||||
.configureWith(SendToDeviceTask.Params(EventType.KEY_VERIFICATION_DONE, contentMap)) {
|
||||
this.callback = object : MatrixCallback<Unit> {
|
||||
override fun onSuccess(data: Unit) {
|
||||
onDone?.invoke()
|
||||
|
@ -176,7 +176,7 @@ internal class VerificationTransportToDevice(
|
|||
val contentMap = MXUsersDevicesMap<Any>()
|
||||
contentMap.setObject(otherUserId, otherUserDeviceId, cancelMessage)
|
||||
sendToDeviceTask
|
||||
.configureWith(SendToDeviceTask.Params(EventType.KEY_VERIFICATION_CANCEL, contentMap, transactionId)) {
|
||||
.configureWith(SendToDeviceTask.Params(EventType.KEY_VERIFICATION_CANCEL, contentMap)) {
|
||||
this.callback = object : MatrixCallback<Unit> {
|
||||
override fun onSuccess(data: Unit) {
|
||||
Timber.v("## SAS verification [$transactionId] canceled for reason ${code.value}")
|
||||
|
|
|
@ -46,7 +46,7 @@ import timber.log.Timber
|
|||
|
||||
internal object RealmSessionStoreMigration : RealmMigration {
|
||||
|
||||
const val SESSION_STORE_SCHEMA_VERSION = 15L
|
||||
const val SESSION_STORE_SCHEMA_VERSION = 16L
|
||||
|
||||
override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
|
||||
Timber.v("Migrating Realm Session from $oldVersion to $newVersion")
|
||||
|
@ -66,6 +66,7 @@ internal object RealmSessionStoreMigration : RealmMigration {
|
|||
if (oldVersion <= 12) migrateTo13(realm)
|
||||
if (oldVersion <= 13) migrateTo14(realm)
|
||||
if (oldVersion <= 14) migrateTo15(realm)
|
||||
if (oldVersion <= 15) migrateTo16(realm)
|
||||
}
|
||||
|
||||
private fun migrateTo1(realm: DynamicRealm) {
|
||||
|
@ -308,6 +309,7 @@ internal object RealmSessionStoreMigration : RealmMigration {
|
|||
}
|
||||
|
||||
private fun migrateTo15(realm: DynamicRealm) {
|
||||
Timber.d("Step 14 -> 15")
|
||||
// fix issue with flattenParentIds on DM that kept growing with duplicate
|
||||
// so we reset it, will be updated next sync
|
||||
realm.where("RoomSummaryEntity")
|
||||
|
@ -318,4 +320,14 @@ internal object RealmSessionStoreMigration : RealmMigration {
|
|||
it.setString(RoomSummaryEntityFields.FLATTEN_PARENT_IDS, null)
|
||||
}
|
||||
}
|
||||
|
||||
private fun migrateTo16(realm: DynamicRealm) {
|
||||
Timber.d("Step 15 -> 16")
|
||||
realm.schema.get("HomeServerCapabilitiesEntity")
|
||||
?.addField(HomeServerCapabilitiesEntityFields.ROOM_VERSIONS_JSON, String::class.java)
|
||||
?.transform { obj ->
|
||||
// Schedule a refresh of the capabilities
|
||||
obj.setLong(HomeServerCapabilitiesEntityFields.LAST_UPDATED_TIMESTAMP, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,8 +16,15 @@
|
|||
|
||||
package org.matrix.android.sdk.internal.database.mapper
|
||||
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
|
||||
import org.matrix.android.sdk.api.session.homeserver.RoomVersionCapabilities
|
||||
import org.matrix.android.sdk.api.session.homeserver.RoomVersionInfo
|
||||
import org.matrix.android.sdk.api.session.homeserver.RoomVersionStatus
|
||||
import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntity
|
||||
import org.matrix.android.sdk.internal.di.MoshiProvider
|
||||
import org.matrix.android.sdk.internal.session.homeserver.RoomVersions
|
||||
import org.matrix.android.sdk.internal.session.room.version.DefaultRoomVersionService
|
||||
|
||||
/**
|
||||
* HomeServerCapabilitiesEntity -> HomeSeverCapabilities
|
||||
|
@ -29,7 +36,30 @@ internal object HomeServerCapabilitiesMapper {
|
|||
canChangePassword = entity.canChangePassword,
|
||||
maxUploadFileSize = entity.maxUploadFileSize,
|
||||
lastVersionIdentityServerSupported = entity.lastVersionIdentityServerSupported,
|
||||
defaultIdentityServerUrl = entity.defaultIdentityServerUrl
|
||||
defaultIdentityServerUrl = entity.defaultIdentityServerUrl,
|
||||
roomVersions = mapRoomVersion(entity.roomVersionsJson)
|
||||
)
|
||||
}
|
||||
|
||||
private fun mapRoomVersion(roomVersionsJson: String?): RoomVersionCapabilities? {
|
||||
roomVersionsJson ?: return null
|
||||
|
||||
return tryOrNull {
|
||||
MoshiProvider.providesMoshi().adapter(RoomVersions::class.java).fromJson(roomVersionsJson)?.let {
|
||||
RoomVersionCapabilities(
|
||||
defaultRoomVersion = it.default ?: DefaultRoomVersionService.DEFAULT_ROOM_VERSION,
|
||||
supportedVersion = it.available.entries.map { entry ->
|
||||
RoomVersionInfo(
|
||||
version = entry.key,
|
||||
status = if (entry.value == "stable") {
|
||||
RoomVersionStatus.STABLE
|
||||
} else {
|
||||
RoomVersionStatus.UNSTABLE
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
|
|||
|
||||
internal open class HomeServerCapabilitiesEntity(
|
||||
var canChangePassword: Boolean = true,
|
||||
var roomVersionsJson: String? = null,
|
||||
var maxUploadFileSize: Long = HomeServerCapabilities.MAX_UPLOAD_FILE_SIZE_UNKNOWN,
|
||||
var lastVersionIdentityServerSupported: Boolean = false,
|
||||
var defaultIdentityServerUrl: String? = null,
|
||||
|
|
|
@ -20,7 +20,7 @@ import io.realm.RealmObject
|
|||
import io.realm.annotations.Index
|
||||
|
||||
/**
|
||||
* Clients can store custom config data for their account on their HomeServer.
|
||||
* Clients can store custom config data for their account on their homeserver.
|
||||
* This account data will be synced between different devices and can persist across installations on a particular device.
|
||||
* Users may only view the account data for their own account.
|
||||
* The account_data may be either global or scoped to a particular rooms.
|
||||
|
|
|
@ -37,7 +37,8 @@ internal abstract class FederationModule {
|
|||
fun providesFederationAPI(@Unauthenticated okHttpClient: Lazy<OkHttpClient>,
|
||||
sessionParams: SessionParams,
|
||||
retrofitFactory: RetrofitFactory): FederationAPI {
|
||||
return retrofitFactory.create(okHttpClient, sessionParams.homeServerUrl).create(FederationAPI::class.java)
|
||||
return retrofitFactory.create(okHttpClient, sessionParams.homeServerUrlBase)
|
||||
.create(FederationAPI::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ public class Credentials {
|
|||
|
||||
public String deviceId;
|
||||
|
||||
// Optional data that may contain info to override home server and/or identity server
|
||||
// Optional data that may contain info to override homeserver and/or identity server
|
||||
public WellKnown wellKnown;
|
||||
|
||||
public JSONObject toJson() throws JSONException {
|
||||
|
|
|
@ -44,7 +44,7 @@ import timber.log.Timber;
|
|||
*/
|
||||
public class HomeServerConnectionConfig {
|
||||
|
||||
// the home server URI
|
||||
// the homeserver URI
|
||||
private Uri mHomeServerUri;
|
||||
// the jitsi server URI. Can be null
|
||||
@Nullable
|
||||
|
@ -82,7 +82,7 @@ public class HomeServerConnectionConfig {
|
|||
}
|
||||
|
||||
/**
|
||||
* Update the home server URI.
|
||||
* Update the homeserver URI.
|
||||
*
|
||||
* @param uri the new HS uri
|
||||
*/
|
||||
|
@ -91,7 +91,7 @@ public class HomeServerConnectionConfig {
|
|||
}
|
||||
|
||||
/**
|
||||
* @return the home server uri
|
||||
* @return the homeserver uri
|
||||
*/
|
||||
public Uri getHomeserverUri() {
|
||||
return mHomeServerUri;
|
||||
|
@ -145,7 +145,7 @@ public class HomeServerConnectionConfig {
|
|||
public void setCredentials(Credentials credentials) {
|
||||
mCredentials = credentials;
|
||||
|
||||
// Override home server url and/or identity server url if provided
|
||||
// Override homeserver url and/or identity server url if provided
|
||||
if (credentials.wellKnown != null) {
|
||||
if (credentials.wellKnown.homeServer != null) {
|
||||
String homeServerUrl = credentials.wellKnown.homeServer.baseURL;
|
||||
|
@ -200,7 +200,7 @@ public class HomeServerConnectionConfig {
|
|||
}
|
||||
|
||||
/**
|
||||
* TLS versions accepted for TLS connections with the home server.
|
||||
* TLS versions accepted for TLS connections with the homeserver.
|
||||
*/
|
||||
@Nullable
|
||||
public List<TlsVersion> getAcceptedTlsVersions() {
|
||||
|
@ -208,7 +208,7 @@ public class HomeServerConnectionConfig {
|
|||
}
|
||||
|
||||
/**
|
||||
* TLS cipher suites accepted for TLS connections with the home server.
|
||||
* TLS cipher suites accepted for TLS connections with the homeserver.
|
||||
*/
|
||||
@Nullable
|
||||
public List<CipherSuite> getAcceptedTlsCipherSuites() {
|
||||
|
@ -426,7 +426,7 @@ public class HomeServerConnectionConfig {
|
|||
*/
|
||||
public Builder withHomeServerUri(final Uri homeServerUri) {
|
||||
if (homeServerUri == null || (!"http".equals(homeServerUri.getScheme()) && !"https".equals(homeServerUri.getScheme()))) {
|
||||
throw new RuntimeException("Invalid home server URI: " + homeServerUri);
|
||||
throw new RuntimeException("Invalid homeserver URI: " + homeServerUri);
|
||||
}
|
||||
|
||||
// remove trailing /
|
||||
|
@ -435,7 +435,7 @@ public class HomeServerConnectionConfig {
|
|||
String url = homeServerUri.toString();
|
||||
mHomeServerConnectionConfig.mHomeServerUri = Uri.parse(url.substring(0, url.length() - 1));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Invalid home server URI: " + homeServerUri);
|
||||
throw new RuntimeException("Invalid homeserver URI: " + homeServerUri);
|
||||
}
|
||||
} else {
|
||||
mHomeServerConnectionConfig.mHomeServerUri = homeServerUri;
|
||||
|
@ -549,7 +549,7 @@ public class HomeServerConnectionConfig {
|
|||
}
|
||||
|
||||
/**
|
||||
* Add an accepted TLS version for TLS connections with the home server.
|
||||
* Add an accepted TLS version for TLS connections with the homeserver.
|
||||
*
|
||||
* @param tlsVersion the tls version to add to the set of TLS versions accepted.
|
||||
* @return this builder
|
||||
|
@ -577,7 +577,7 @@ public class HomeServerConnectionConfig {
|
|||
}
|
||||
|
||||
/**
|
||||
* Add a TLS cipher suite to the list of accepted TLS connections with the home server.
|
||||
* Add a TLS cipher suite to the list of accepted TLS connections with the homeserver.
|
||||
*
|
||||
* @param tlsCipherSuite the tls cipher suite to add.
|
||||
* @return this builder
|
||||
|
@ -666,7 +666,7 @@ public class HomeServerConnectionConfig {
|
|||
public HomeServerConnectionConfig build() {
|
||||
// Check mandatory parameters
|
||||
if (mHomeServerConnectionConfig.mHomeServerUri == null) {
|
||||
throw new RuntimeException("Home server URI not set");
|
||||
throw new RuntimeException("Homeserver URI not set");
|
||||
}
|
||||
|
||||
return mHomeServerConnectionConfig;
|
||||
|
|
|
@ -38,7 +38,7 @@ import timber.log.Timber;
|
|||
public class LoginStorage {
|
||||
private static final String PREFS_LOGIN = "Vector.LoginStorage";
|
||||
|
||||
// multi accounts + home server config
|
||||
// multi accounts + homeserver config
|
||||
private static final String PREFS_KEY_CONNECTION_CONFIGS = "PREFS_KEY_CONNECTION_CONFIGS";
|
||||
|
||||
private final Context mContext;
|
||||
|
@ -49,7 +49,7 @@ public class LoginStorage {
|
|||
}
|
||||
|
||||
/**
|
||||
* @return the list of home server configurations.
|
||||
* @return the list of homeserver configurations.
|
||||
*/
|
||||
public List<HomeServerConnectionConfig> getCredentialsList() {
|
||||
SharedPreferences prefs = mContext.getSharedPreferences(PREFS_LOGIN, Context.MODE_PRIVATE);
|
||||
|
@ -85,7 +85,7 @@ public class LoginStorage {
|
|||
/**
|
||||
* Add a credentials to the credentials list
|
||||
*
|
||||
* @param config the home server config to add.
|
||||
* @param config the homeserver config to add.
|
||||
*/
|
||||
public void addCredentials(HomeServerConnectionConfig config) {
|
||||
if (null != config && config.getCredentials() != null) {
|
||||
|
@ -203,4 +203,4 @@ public class LoginStorage {
|
|||
//Need to commit now because called before forcing an app restart
|
||||
editor.commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -253,7 +253,7 @@ internal object CertUtil {
|
|||
val list = ArrayList<ConnectionSpec>()
|
||||
list.add(builder.build())
|
||||
// TODO: we should display a warning if user enter an http url
|
||||
if (hsConfig.allowHttpExtension || hsConfig.homeServerUri.toString().startsWith("http://")) {
|
||||
if (hsConfig.allowHttpExtension || hsConfig.homeServerUriBase.toString().startsWith("http://")) {
|
||||
list.add(ConnectionSpec.CLEARTEXT)
|
||||
}
|
||||
return list
|
||||
|
|
|
@ -29,10 +29,9 @@ internal class DefaultRawService @Inject constructor(
|
|||
return getUrlTask.execute(GetUrlTask.Params(url, cacheStrategy))
|
||||
}
|
||||
|
||||
override suspend fun getWellknown(userId: String): String {
|
||||
val homeServerDomain = userId.substringAfter(":")
|
||||
override suspend fun getWellknown(domain: String): String {
|
||||
return getUrl(
|
||||
"https://$homeServerDomain/.well-known/matrix/client",
|
||||
"https://$domain/.well-known/matrix/client",
|
||||
CacheStrategy.TtlCache(TimeUnit.HOURS.toMillis(8), false)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.matrix.android.sdk.internal.di.SessionDownloadsDirectory
|
|||
import org.matrix.android.sdk.internal.di.UnauthenticatedWithCertificateWithProgress
|
||||
import org.matrix.android.sdk.internal.session.download.DownloadProgressInterceptor.Companion.DOWNLOAD_PROGRESS_INTERCEPTOR_HEADER
|
||||
import org.matrix.android.sdk.internal.util.MatrixCoroutineDispatchers
|
||||
import org.matrix.android.sdk.internal.util.file.AtomicFileCreator
|
||||
import org.matrix.android.sdk.internal.util.md5
|
||||
import org.matrix.android.sdk.internal.util.writeToFile
|
||||
import timber.log.Timber
|
||||
|
@ -96,6 +97,9 @@ internal class DefaultFileService @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
var atomicFileDownload: AtomicFileCreator? = null
|
||||
var atomicFileDecrypt: AtomicFileCreator? = null
|
||||
|
||||
if (existingDownload != null) {
|
||||
// FIXME If the first downloader cancels then we'll unfortunately be cancelled too.
|
||||
return existingDownload.await()
|
||||
|
@ -131,8 +135,11 @@ internal class DefaultFileService @Inject constructor(
|
|||
Timber.v("Response size ${response.body?.contentLength()} - Stream available: ${!source.exhausted()}")
|
||||
|
||||
// Write the file to cache (encrypted version if the file is encrypted)
|
||||
writeToFile(source.inputStream(), cachedFiles.file)
|
||||
// Write to a part file first, so if we abort before done, we don't have a broken cached file
|
||||
val atomicFileCreator = AtomicFileCreator(cachedFiles.file).also { atomicFileDownload = it }
|
||||
writeToFile(source.inputStream(), atomicFileCreator.partFile)
|
||||
response.close()
|
||||
atomicFileCreator.commit()
|
||||
} else {
|
||||
Timber.v("## FileService: cache hit for $url")
|
||||
}
|
||||
|
@ -145,8 +152,10 @@ internal class DefaultFileService @Inject constructor(
|
|||
Timber.v("## FileService: decrypt file")
|
||||
// Ensure the parent folder exists
|
||||
cachedFiles.decryptedFile.parentFile?.mkdirs()
|
||||
// Write to a part file first, so if we abort before done, we don't have a broken cached file
|
||||
val atomicFileCreator = AtomicFileCreator(cachedFiles.decryptedFile).also { atomicFileDecrypt = it }
|
||||
val decryptSuccess = cachedFiles.file.inputStream().use { inputStream ->
|
||||
cachedFiles.decryptedFile.outputStream().buffered().use { outputStream ->
|
||||
atomicFileCreator.partFile.outputStream().buffered().use { outputStream ->
|
||||
MXEncryptedAttachments.decryptAttachment(
|
||||
inputStream,
|
||||
elementToDecrypt,
|
||||
|
@ -154,6 +163,7 @@ internal class DefaultFileService @Inject constructor(
|
|||
)
|
||||
}
|
||||
}
|
||||
atomicFileCreator.commit()
|
||||
if (!decryptSuccess) {
|
||||
throw IllegalStateException("Decryption error")
|
||||
}
|
||||
|
@ -174,6 +184,11 @@ internal class DefaultFileService @Inject constructor(
|
|||
}
|
||||
toNotify?.completeWith(result)
|
||||
|
||||
result.onFailure {
|
||||
atomicFileDownload?.cancel()
|
||||
atomicFileDecrypt?.cancel()
|
||||
}
|
||||
|
||||
return result.getOrThrow()
|
||||
}
|
||||
|
||||
|
|
|
@ -313,7 +313,7 @@ internal class DefaultSession @Inject constructor(
|
|||
|
||||
override fun getUiaSsoFallbackUrl(authenticationSessionId: String): String {
|
||||
val hsBas = sessionParams.homeServerConnectionConfig
|
||||
.homeServerUri
|
||||
.homeServerUriBase
|
||||
.toString()
|
||||
.trim { it == '/' }
|
||||
return buildString {
|
||||
|
|
|
@ -261,7 +261,7 @@ internal abstract class SessionModule {
|
|||
sessionParams: SessionParams,
|
||||
retrofitFactory: RetrofitFactory): Retrofit {
|
||||
return retrofitFactory
|
||||
.create(okHttpClient, sessionParams.homeServerConnectionConfig.homeServerUri.toString())
|
||||
.create(okHttpClient, sessionParams.homeServerConnectionConfig.homeServerUriBase.toString())
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
|
|
|
@ -20,11 +20,14 @@ import io.realm.Realm
|
|||
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.internal.database.model.EventInsertType
|
||||
import org.matrix.android.sdk.api.logger.LoggerTag
|
||||
import org.matrix.android.sdk.internal.session.EventInsertLiveProcessor
|
||||
import org.matrix.android.sdk.internal.session.SessionScope
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
private val loggerTag = LoggerTag("CallEventProcessor", LoggerTag.VOIP)
|
||||
|
||||
@SessionScope
|
||||
internal class CallEventProcessor @Inject constructor(private val callSignalingHandler: CallSignalingHandler)
|
||||
: EventInsertLiveProcessor {
|
||||
|
@ -71,14 +74,8 @@ internal class CallEventProcessor @Inject constructor(private val callSignalingH
|
|||
}
|
||||
|
||||
private fun dispatchToCallSignalingHandlerIfNeeded(event: Event) {
|
||||
val now = System.currentTimeMillis()
|
||||
event.roomId ?: return Unit.also {
|
||||
Timber.w("Event with no room id ${event.eventId}")
|
||||
}
|
||||
val age = now - (event.ageLocalTs ?: now)
|
||||
if (age > 40_000) {
|
||||
// Too old to ring?
|
||||
return
|
||||
Timber.tag(loggerTag.value).w("Event with no room id ${event.eventId}")
|
||||
}
|
||||
callSignalingHandler.onCallEvent(event)
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package org.matrix.android.sdk.internal.session.call
|
||||
|
||||
import org.matrix.android.sdk.api.logger.LoggerTag
|
||||
import org.matrix.android.sdk.api.session.call.CallListener
|
||||
import org.matrix.android.sdk.api.session.call.CallState
|
||||
import org.matrix.android.sdk.api.session.call.MxCall
|
||||
|
@ -36,6 +37,9 @@ import org.matrix.android.sdk.internal.session.SessionScope
|
|||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
private val loggerTag = LoggerTag("CallSignalingHandler", LoggerTag.VOIP)
|
||||
private const val MAX_AGE_TO_RING = 40_000
|
||||
|
||||
@SessionScope
|
||||
internal class CallSignalingHandler @Inject constructor(private val activeCallHandler: ActiveCallHandler,
|
||||
private val mxCallFactory: MxCallFactory,
|
||||
|
@ -111,12 +115,12 @@ internal class CallSignalingHandler @Inject constructor(private val activeCallHa
|
|||
return
|
||||
}
|
||||
if (call.isOutgoing) {
|
||||
Timber.v("Got selectAnswer for an outbound call: ignoring")
|
||||
Timber.tag(loggerTag.value).v("Got selectAnswer for an outbound call: ignoring")
|
||||
return
|
||||
}
|
||||
val selectedPartyId = content.selectedPartyId
|
||||
if (selectedPartyId == null) {
|
||||
Timber.w("Got nonsensical select_answer with null selected_party_id: ignoring")
|
||||
Timber.tag(loggerTag.value).w("Got nonsensical select_answer with null selected_party_id: ignoring")
|
||||
return
|
||||
}
|
||||
callListenersDispatcher.onCallSelectAnswerReceived(content)
|
||||
|
@ -130,7 +134,7 @@ internal class CallSignalingHandler @Inject constructor(private val activeCallHa
|
|||
return
|
||||
}
|
||||
if (call.opponentPartyId != null && !call.partyIdsMatches(content)) {
|
||||
Timber.v("Ignoring candidates from party ID ${content.partyId} we have chosen party ID ${call.opponentPartyId}")
|
||||
Timber.tag(loggerTag.value).v("Ignoring candidates from party ID ${content.partyId} we have chosen party ID ${call.opponentPartyId}")
|
||||
return
|
||||
}
|
||||
callListenersDispatcher.onCallIceCandidateReceived(call, content)
|
||||
|
@ -163,10 +167,10 @@ internal class CallSignalingHandler @Inject constructor(private val activeCallHa
|
|||
// party ID must match (our chosen partner hanging up the call) or be undefined (we haven't chosen
|
||||
// a partner yet but we're treating the hangup as a reject as per VoIP v0)
|
||||
if (call.opponentPartyId != null && !call.partyIdsMatches(content)) {
|
||||
Timber.v("Ignoring hangup from party ID ${content.partyId} we have chosen party ID ${call.opponentPartyId}")
|
||||
Timber.tag(loggerTag.value).v("Ignoring hangup from party ID ${content.partyId} we have chosen party ID ${call.opponentPartyId}")
|
||||
return
|
||||
}
|
||||
if (call.state != CallState.Terminated) {
|
||||
if (call.state !is CallState.Ended) {
|
||||
activeCallHandler.removeCall(content.callId)
|
||||
callListenersDispatcher.onCallHangupReceived(content)
|
||||
}
|
||||
|
@ -180,12 +184,18 @@ internal class CallSignalingHandler @Inject constructor(private val activeCallHa
|
|||
if (event.roomId == null || event.senderId == null) {
|
||||
return
|
||||
}
|
||||
val now = System.currentTimeMillis()
|
||||
val age = now - (event.ageLocalTs ?: now)
|
||||
if (age > MAX_AGE_TO_RING) {
|
||||
Timber.tag(loggerTag.value).w("Call invite is too old to ring.")
|
||||
return
|
||||
}
|
||||
val content = event.getClearContent().toModel<CallInviteContent>() ?: return
|
||||
|
||||
content.callId ?: return
|
||||
if (invitedCallIds.contains(content.callId)) {
|
||||
// Call is already known, maybe due to fast lane. Ignore
|
||||
Timber.d("Ignoring already known call invite")
|
||||
Timber.tag(loggerTag.value).d("Ignoring already known call invite")
|
||||
return
|
||||
}
|
||||
val incomingCall = mxCallFactory.createIncomingCall(
|
||||
|
@ -214,7 +224,8 @@ internal class CallSignalingHandler @Inject constructor(private val activeCallHa
|
|||
callListenersDispatcher.onCallManagedByOtherSession(content.callId)
|
||||
} else {
|
||||
if (call.opponentPartyId != null) {
|
||||
Timber.v("Ignoring answer from party ID ${content.partyId} we already have an answer from ${call.opponentPartyId}")
|
||||
Timber.tag(loggerTag.value)
|
||||
.v("Ignoring answer from party ID ${content.partyId} we already have an answer from ${call.opponentPartyId}")
|
||||
return
|
||||
}
|
||||
mxCallFactory.updateOutgoingCallWithOpponentData(call, event.senderId, content, content.capabilities)
|
||||
|
@ -231,7 +242,7 @@ internal class CallSignalingHandler @Inject constructor(private val activeCallHa
|
|||
activeCallHandler.getCallWithId(it)
|
||||
}
|
||||
if (currentCall == null) {
|
||||
Timber.v("Call with id $callId is null")
|
||||
Timber.tag(loggerTag.value).v("Call with id $callId is null")
|
||||
}
|
||||
return currentCall
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ import org.matrix.android.sdk.api.session.call.CallSignalingService
|
|||
import org.matrix.android.sdk.api.session.call.MxCall
|
||||
import org.matrix.android.sdk.api.session.call.TurnServerResponse
|
||||
import org.matrix.android.sdk.internal.session.SessionScope
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@SessionScope
|
||||
|
@ -51,7 +50,6 @@ internal class DefaultCallSignalingService @Inject constructor(
|
|||
}
|
||||
|
||||
override fun getCallWithId(callId: String): MxCall? {
|
||||
Timber.v("## VOIP getCallWithId $callId all calls ${activeCallHandler.getActiveCallsLiveData().value?.map { it.callId }}")
|
||||
return activeCallHandler.getCallWithId(callId)
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package org.matrix.android.sdk.internal.session.call.model
|
||||
|
||||
import org.matrix.android.sdk.api.MatrixConfiguration
|
||||
import org.matrix.android.sdk.api.logger.LoggerTag
|
||||
import org.matrix.android.sdk.api.session.call.CallIdGenerator
|
||||
import org.matrix.android.sdk.api.session.call.CallState
|
||||
import org.matrix.android.sdk.api.session.call.MxCall
|
||||
|
@ -38,6 +39,7 @@ import org.matrix.android.sdk.api.session.room.model.call.CallRejectContent
|
|||
import org.matrix.android.sdk.api.session.room.model.call.CallReplacesContent
|
||||
import org.matrix.android.sdk.api.session.room.model.call.CallSelectAnswerContent
|
||||
import org.matrix.android.sdk.api.session.room.model.call.CallSignalingContent
|
||||
import org.matrix.android.sdk.api.session.room.model.call.EndCallReason
|
||||
import org.matrix.android.sdk.api.session.room.model.call.SdpType
|
||||
import org.matrix.android.sdk.api.util.Optional
|
||||
import org.matrix.android.sdk.internal.session.call.DefaultCallSignalingService
|
||||
|
@ -47,6 +49,8 @@ import org.matrix.android.sdk.internal.session.room.send.queue.EventSenderProces
|
|||
import timber.log.Timber
|
||||
import java.math.BigDecimal
|
||||
|
||||
private val loggerTag = LoggerTag("MxCallImpl", LoggerTag.VOIP)
|
||||
|
||||
internal class MxCallImpl(
|
||||
override val callId: String,
|
||||
override val isOutgoing: Boolean,
|
||||
|
@ -93,7 +97,7 @@ internal class MxCallImpl(
|
|||
try {
|
||||
it.onStateUpdate(this)
|
||||
} catch (failure: Throwable) {
|
||||
Timber.d("dispatchStateChange failed for call $callId : ${failure.localizedMessage}")
|
||||
Timber.tag(loggerTag.value).d("dispatchStateChange failed for call $callId : ${failure.localizedMessage}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -109,7 +113,7 @@ internal class MxCallImpl(
|
|||
|
||||
override fun offerSdp(sdpString: String) {
|
||||
if (!isOutgoing) return
|
||||
Timber.v("## VOIP offerSdp $callId")
|
||||
Timber.tag(loggerTag.value).v("offerSdp $callId")
|
||||
state = CallState.Dialing
|
||||
CallInviteContent(
|
||||
callId = callId,
|
||||
|
@ -124,7 +128,7 @@ internal class MxCallImpl(
|
|||
}
|
||||
|
||||
override fun sendLocalCallCandidates(candidates: List<CallCandidate>) {
|
||||
Timber.v("Send local call canditates $callId: $candidates")
|
||||
Timber.tag(loggerTag.value).v("Send local call canditates $callId: $candidates")
|
||||
CallCandidatesContent(
|
||||
callId = callId,
|
||||
partyId = ourPartyId,
|
||||
|
@ -141,11 +145,11 @@ internal class MxCallImpl(
|
|||
|
||||
override fun reject() {
|
||||
if (opponentVersion < 1) {
|
||||
Timber.v("Opponent version is less than 1 ($opponentVersion): sending hangup instead of reject")
|
||||
hangUp()
|
||||
Timber.tag(loggerTag.value).v("Opponent version is less than 1 ($opponentVersion): sending hangup instead of reject")
|
||||
hangUp(EndCallReason.USER_HANGUP)
|
||||
return
|
||||
}
|
||||
Timber.v("## VOIP reject $callId")
|
||||
Timber.tag(loggerTag.value).v("reject $callId")
|
||||
CallRejectContent(
|
||||
callId = callId,
|
||||
partyId = ourPartyId,
|
||||
|
@ -153,24 +157,24 @@ internal class MxCallImpl(
|
|||
)
|
||||
.let { createEventAndLocalEcho(type = EventType.CALL_REJECT, roomId = roomId, content = it.toContent()) }
|
||||
.also { eventSenderProcessor.postEvent(it) }
|
||||
state = CallState.Terminated
|
||||
state = CallState.Ended(reason = EndCallReason.USER_HANGUP)
|
||||
}
|
||||
|
||||
override fun hangUp(reason: CallHangupContent.Reason?) {
|
||||
Timber.v("## VOIP hangup $callId")
|
||||
override fun hangUp(reason: EndCallReason?) {
|
||||
Timber.tag(loggerTag.value).v("hangup $callId")
|
||||
CallHangupContent(
|
||||
callId = callId,
|
||||
partyId = ourPartyId,
|
||||
reason = reason ?: CallHangupContent.Reason.USER_HANGUP,
|
||||
reason = reason,
|
||||
version = MxCall.VOIP_PROTO_VERSION.toString()
|
||||
)
|
||||
.let { createEventAndLocalEcho(type = EventType.CALL_HANGUP, roomId = roomId, content = it.toContent()) }
|
||||
.also { eventSenderProcessor.postEvent(it) }
|
||||
state = CallState.Terminated
|
||||
state = CallState.Ended(reason)
|
||||
}
|
||||
|
||||
override fun accept(sdpString: String) {
|
||||
Timber.v("## VOIP accept $callId")
|
||||
Timber.tag(loggerTag.value).v("accept $callId")
|
||||
if (isOutgoing) return
|
||||
state = CallState.Answering
|
||||
CallAnswerContent(
|
||||
|
@ -185,7 +189,7 @@ internal class MxCallImpl(
|
|||
}
|
||||
|
||||
override fun negotiate(sdpString: String, type: SdpType) {
|
||||
Timber.v("## VOIP negotiate $callId")
|
||||
Timber.tag(loggerTag.value).v("negotiate $callId")
|
||||
CallNegotiateContent(
|
||||
callId = callId,
|
||||
partyId = ourPartyId,
|
||||
|
@ -198,7 +202,7 @@ internal class MxCallImpl(
|
|||
}
|
||||
|
||||
override fun selectAnswer() {
|
||||
Timber.v("## VOIP select answer $callId")
|
||||
Timber.tag(loggerTag.value).v("select answer $callId")
|
||||
if (isOutgoing) return
|
||||
state = CallState.Answering
|
||||
CallSelectAnswerContent(
|
||||
|
@ -219,7 +223,7 @@ internal class MxCallImpl(
|
|||
val profileInfo = try {
|
||||
getProfileInfoTask.execute(profileInfoParams)
|
||||
} catch (failure: Throwable) {
|
||||
Timber.v("Fail fetching profile info of $targetUserId while transferring call")
|
||||
Timber.tag(loggerTag.value).v("Fail fetching profile info of $targetUserId while transferring call")
|
||||
null
|
||||
}
|
||||
CallReplacesContent(
|
||||
|
|
|
@ -26,7 +26,7 @@ private const val MATRIX_CONTENT_URI_SCHEME = "mxc://"
|
|||
|
||||
internal class DefaultContentUrlResolver @Inject constructor(homeServerConnectionConfig: HomeServerConnectionConfig) : ContentUrlResolver {
|
||||
|
||||
private val baseUrl = homeServerConnectionConfig.homeServerUri.toString().ensureTrailingSlash()
|
||||
private val baseUrl = homeServerConnectionConfig.homeServerUriBase.toString().ensureTrailingSlash()
|
||||
|
||||
override val uploadUrl = baseUrl + NetworkConstants.URI_API_MEDIA_PREFIX_PATH_R0 + "upload"
|
||||
|
||||
|
|
|
@ -16,18 +16,12 @@
|
|||
|
||||
package org.matrix.android.sdk.internal.session.homeserver
|
||||
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import io.realm.Realm
|
||||
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
|
||||
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilitiesService
|
||||
import org.matrix.android.sdk.internal.database.mapper.HomeServerCapabilitiesMapper
|
||||
import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntity
|
||||
import org.matrix.android.sdk.internal.database.query.get
|
||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class DefaultHomeServerCapabilitiesService @Inject constructor(
|
||||
@SessionDatabase private val monarchy: Monarchy,
|
||||
private val homeServerCapabilitiesDataSource: HomeServerCapabilitiesDataSource,
|
||||
private val getHomeServerCapabilitiesTask: GetHomeServerCapabilitiesTask
|
||||
) : HomeServerCapabilitiesService {
|
||||
|
||||
|
@ -36,11 +30,7 @@ internal class DefaultHomeServerCapabilitiesService @Inject constructor(
|
|||
}
|
||||
|
||||
override fun getHomeServerCapabilities(): HomeServerCapabilities {
|
||||
return Realm.getInstance(monarchy.realmConfiguration).use { realm ->
|
||||
HomeServerCapabilitiesEntity.get(realm)?.let {
|
||||
HomeServerCapabilitiesMapper.map(it)
|
||||
}
|
||||
}
|
||||
return homeServerCapabilitiesDataSource.getHomeServerCapabilities()
|
||||
?: HomeServerCapabilities()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ package org.matrix.android.sdk.internal.session.homeserver
|
|||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import org.matrix.android.sdk.api.extensions.orTrue
|
||||
import org.matrix.android.sdk.api.util.JsonDict
|
||||
|
||||
/**
|
||||
* Ref: https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-capabilities
|
||||
|
@ -38,9 +39,14 @@ internal data class Capabilities(
|
|||
* Capability to indicate if the user can change their password.
|
||||
*/
|
||||
@Json(name = "m.change_password")
|
||||
val changePassword: ChangePassword? = null
|
||||
val changePassword: ChangePassword? = null,
|
||||
|
||||
// No need for m.room_versions for the moment
|
||||
/**
|
||||
* This capability describes the default and available room versions a server supports, and at what level of stability.
|
||||
* Clients should make use of this capability to determine if users need to be encouraged to upgrade their rooms.
|
||||
*/
|
||||
@Json(name = "m.room_versions")
|
||||
val roomVersions: RoomVersions? = null
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
|
@ -52,6 +58,21 @@ internal data class ChangePassword(
|
|||
val enabled: Boolean?
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal data class RoomVersions(
|
||||
/**
|
||||
* Required. The default room version the server is using for new rooms.
|
||||
*/
|
||||
@Json(name = "default")
|
||||
val default: String?,
|
||||
|
||||
/**
|
||||
* Required. A detailed description of the room versions the server supports.
|
||||
*/
|
||||
@Json(name = "available")
|
||||
val available: JsonDict
|
||||
)
|
||||
|
||||
// The spec says: If not present, the client should assume that password changes are possible via the API
|
||||
internal fun GetCapabilitiesResult.canChangePassword(): Boolean {
|
||||
return capabilities?.changePassword?.enabled.orTrue()
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package org.matrix.android.sdk.internal.session.homeserver
|
||||
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import org.matrix.android.sdk.api.MatrixPatterns.getDomain
|
||||
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
|
||||
import org.matrix.android.sdk.api.auth.wellknown.WellknownResult
|
||||
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
|
||||
|
@ -24,6 +25,7 @@ import org.matrix.android.sdk.internal.auth.version.Versions
|
|||
import org.matrix.android.sdk.internal.auth.version.isLoginAndRegistrationSupportedBySdk
|
||||
import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntity
|
||||
import org.matrix.android.sdk.internal.database.query.getOrCreate
|
||||
import org.matrix.android.sdk.internal.di.MoshiProvider
|
||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||
import org.matrix.android.sdk.internal.di.UserId
|
||||
import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
|
||||
|
@ -89,7 +91,10 @@ internal class DefaultGetHomeServerCapabilitiesTask @Inject constructor(
|
|||
}.getOrNull()
|
||||
|
||||
val wellknownResult = runCatching {
|
||||
getWellknownTask.execute(GetWellknownTask.Params(userId, homeServerConnectionConfig))
|
||||
getWellknownTask.execute(GetWellknownTask.Params(
|
||||
domain = userId.getDomain(),
|
||||
homeServerConnectionConfig = homeServerConnectionConfig
|
||||
))
|
||||
}.getOrNull()
|
||||
|
||||
insertInDb(capabilities, mediaConfig, versions, wellknownResult)
|
||||
|
@ -104,6 +109,10 @@ internal class DefaultGetHomeServerCapabilitiesTask @Inject constructor(
|
|||
|
||||
if (getCapabilitiesResult != null) {
|
||||
homeServerCapabilitiesEntity.canChangePassword = getCapabilitiesResult.canChangePassword()
|
||||
|
||||
homeServerCapabilitiesEntity.roomVersionsJson = getCapabilitiesResult.capabilities?.roomVersions?.let {
|
||||
MoshiProvider.providesMoshi().adapter(RoomVersions::class.java).toJson(it)
|
||||
}
|
||||
}
|
||||
|
||||
if (getMediaConfigResult != null) {
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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.internal.session.homeserver
|
||||
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import io.realm.Realm
|
||||
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
|
||||
import org.matrix.android.sdk.internal.database.mapper.HomeServerCapabilitiesMapper
|
||||
import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntity
|
||||
import org.matrix.android.sdk.internal.database.query.get
|
||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class HomeServerCapabilitiesDataSource @Inject constructor(
|
||||
@SessionDatabase private val monarchy: Monarchy
|
||||
) {
|
||||
fun getHomeServerCapabilities(): HomeServerCapabilities? {
|
||||
return Realm.getInstance(monarchy.realmConfiguration).use { realm ->
|
||||
HomeServerCapabilitiesEntity.get(realm)?.let {
|
||||
HomeServerCapabilitiesMapper.map(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -191,7 +191,7 @@ internal class DefaultIdentityService @Inject constructor(
|
|||
} else {
|
||||
// Disconnect previous one if any, first, because the token will change.
|
||||
// In case of error when configuring the new identity server, this is not a big deal,
|
||||
// we will ask for a new token on the previous Identity server
|
||||
// we will ask for a new token on the previous identity server
|
||||
runCatching { identityDisconnectTask.execute(Unit) }
|
||||
.onFailure { Timber.w(it, "Unable to disconnect identity server") }
|
||||
|
||||
|
@ -241,7 +241,7 @@ internal class DefaultIdentityService @Inject constructor(
|
|||
|
||||
override suspend fun getShareStatus(threePids: List<ThreePid>): Map<ThreePid, SharedState> {
|
||||
// Note: we do not require user consent here, because it is used for emails and phone numbers that the user has already sent
|
||||
// to the home server, and not emails and phone numbers from the contact book of the user
|
||||
// to the homeserver, and not emails and phone numbers from the contact book of the user
|
||||
|
||||
if (threePids.isEmpty()) {
|
||||
return emptyMap()
|
||||
|
|
|
@ -42,7 +42,7 @@ internal interface IdentityAuthAPI {
|
|||
suspend fun ping()
|
||||
|
||||
/**
|
||||
* Ping v1 will be used to check outdated Identity server
|
||||
* Ping v1 will be used to check outdated identity server
|
||||
*/
|
||||
@GET("_matrix/identity/api/v1")
|
||||
suspend fun pingV1()
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue