Remove LegacySessionImporter, and the dialog which explains that Riot is now Element.
This commit is contained in:
parent
e6bfb14a9c
commit
622aa88f86
|
@ -0,0 +1 @@
|
||||||
|
Remove ability to migrate session from Riot to Element.
|
|
@ -28,7 +28,6 @@ import org.matrix.android.sdk.BuildConfig
|
||||||
import org.matrix.android.sdk.api.MatrixConfiguration
|
import org.matrix.android.sdk.api.MatrixConfiguration
|
||||||
import org.matrix.android.sdk.api.auth.AuthenticationService
|
import org.matrix.android.sdk.api.auth.AuthenticationService
|
||||||
import org.matrix.android.sdk.api.auth.HomeServerHistoryService
|
import org.matrix.android.sdk.api.auth.HomeServerHistoryService
|
||||||
import org.matrix.android.sdk.api.legacy.LegacySessionImporter
|
|
||||||
import org.matrix.android.sdk.api.network.ApiInterceptorListener
|
import org.matrix.android.sdk.api.network.ApiInterceptorListener
|
||||||
import org.matrix.android.sdk.api.network.ApiPath
|
import org.matrix.android.sdk.api.network.ApiPath
|
||||||
import org.matrix.android.sdk.api.raw.RawService
|
import org.matrix.android.sdk.api.raw.RawService
|
||||||
|
@ -46,7 +45,6 @@ import javax.inject.Inject
|
||||||
*/
|
*/
|
||||||
internal class TestMatrix(context: Context, matrixConfiguration: MatrixConfiguration) {
|
internal class TestMatrix(context: Context, matrixConfiguration: MatrixConfiguration) {
|
||||||
|
|
||||||
@Inject internal lateinit var legacySessionImporter: LegacySessionImporter
|
|
||||||
@Inject internal lateinit var authenticationService: AuthenticationService
|
@Inject internal lateinit var authenticationService: AuthenticationService
|
||||||
@Inject internal lateinit var rawService: RawService
|
@Inject internal lateinit var rawService: RawService
|
||||||
@Inject internal lateinit var userAgentHolder: UserAgentHolder
|
@Inject internal lateinit var userAgentHolder: UserAgentHolder
|
||||||
|
@ -88,10 +86,6 @@ internal class TestMatrix(context: Context, matrixConfiguration: MatrixConfigura
|
||||||
|
|
||||||
fun homeServerHistoryService() = homeServerHistoryService
|
fun homeServerHistoryService() = homeServerHistoryService
|
||||||
|
|
||||||
fun legacySessionImporter(): LegacySessionImporter {
|
|
||||||
return legacySessionImporter
|
|
||||||
}
|
|
||||||
|
|
||||||
fun registerApiInterceptorListener(path: ApiPath, listener: ApiInterceptorListener) {
|
fun registerApiInterceptorListener(path: ApiPath, listener: ApiInterceptorListener) {
|
||||||
apiInterceptor.addListener(path, listener)
|
apiInterceptor.addListener(path, listener)
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,6 @@ import org.matrix.android.sdk.BuildConfig
|
||||||
import org.matrix.android.sdk.api.auth.AuthenticationService
|
import org.matrix.android.sdk.api.auth.AuthenticationService
|
||||||
import org.matrix.android.sdk.api.auth.HomeServerHistoryService
|
import org.matrix.android.sdk.api.auth.HomeServerHistoryService
|
||||||
import org.matrix.android.sdk.api.debug.DebugService
|
import org.matrix.android.sdk.api.debug.DebugService
|
||||||
import org.matrix.android.sdk.api.legacy.LegacySessionImporter
|
|
||||||
import org.matrix.android.sdk.api.network.ApiInterceptorListener
|
import org.matrix.android.sdk.api.network.ApiInterceptorListener
|
||||||
import org.matrix.android.sdk.api.network.ApiPath
|
import org.matrix.android.sdk.api.network.ApiPath
|
||||||
import org.matrix.android.sdk.api.raw.RawService
|
import org.matrix.android.sdk.api.raw.RawService
|
||||||
|
@ -55,7 +54,6 @@ import javax.inject.Inject
|
||||||
*/
|
*/
|
||||||
class Matrix(context: Context, matrixConfiguration: MatrixConfiguration) {
|
class Matrix(context: Context, matrixConfiguration: MatrixConfiguration) {
|
||||||
|
|
||||||
@Inject internal lateinit var legacySessionImporter: LegacySessionImporter
|
|
||||||
@Inject internal lateinit var authenticationService: AuthenticationService
|
@Inject internal lateinit var authenticationService: AuthenticationService
|
||||||
@Inject internal lateinit var rawService: RawService
|
@Inject internal lateinit var rawService: RawService
|
||||||
@Inject internal lateinit var debugService: DebugService
|
@Inject internal lateinit var debugService: DebugService
|
||||||
|
@ -118,11 +116,6 @@ class Matrix(context: Context, matrixConfiguration: MatrixConfiguration) {
|
||||||
*/
|
*/
|
||||||
fun homeServerHistoryService() = homeServerHistoryService
|
fun homeServerHistoryService() = homeServerHistoryService
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the legacy session importer, useful if you want to migrate an app, which was using the legacy Matrix Android Sdk.
|
|
||||||
*/
|
|
||||||
fun legacySessionImporter() = legacySessionImporter
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the SecureStorageService used to encrypt and decrypt sensitive data.
|
* Returns the SecureStorageService used to encrypt and decrypt sensitive data.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.matrix.android.sdk.api.legacy
|
|
||||||
|
|
||||||
interface LegacySessionImporter {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Will eventually import a session created by the legacy app.
|
|
||||||
* @return true if a session has been imported
|
|
||||||
*/
|
|
||||||
fun process(): Boolean
|
|
||||||
}
|
|
|
@ -23,7 +23,6 @@ import dagger.Provides
|
||||||
import io.realm.RealmConfiguration
|
import io.realm.RealmConfiguration
|
||||||
import org.matrix.android.sdk.api.auth.AuthenticationService
|
import org.matrix.android.sdk.api.auth.AuthenticationService
|
||||||
import org.matrix.android.sdk.api.auth.HomeServerHistoryService
|
import org.matrix.android.sdk.api.auth.HomeServerHistoryService
|
||||||
import org.matrix.android.sdk.api.legacy.LegacySessionImporter
|
|
||||||
import org.matrix.android.sdk.internal.auth.db.AuthRealmMigration
|
import org.matrix.android.sdk.internal.auth.db.AuthRealmMigration
|
||||||
import org.matrix.android.sdk.internal.auth.db.AuthRealmModule
|
import org.matrix.android.sdk.internal.auth.db.AuthRealmModule
|
||||||
import org.matrix.android.sdk.internal.auth.db.RealmPendingSessionStore
|
import org.matrix.android.sdk.internal.auth.db.RealmPendingSessionStore
|
||||||
|
@ -34,7 +33,6 @@ import org.matrix.android.sdk.internal.auth.login.DirectLoginTask
|
||||||
import org.matrix.android.sdk.internal.auth.login.QrLoginTokenTask
|
import org.matrix.android.sdk.internal.auth.login.QrLoginTokenTask
|
||||||
import org.matrix.android.sdk.internal.database.RealmKeysUtils
|
import org.matrix.android.sdk.internal.database.RealmKeysUtils
|
||||||
import org.matrix.android.sdk.internal.di.AuthDatabase
|
import org.matrix.android.sdk.internal.di.AuthDatabase
|
||||||
import org.matrix.android.sdk.internal.legacy.DefaultLegacySessionImporter
|
|
||||||
import org.matrix.android.sdk.internal.wellknown.WellknownModule
|
import org.matrix.android.sdk.internal.wellknown.WellknownModule
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
@ -70,9 +68,6 @@ internal abstract class AuthModule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Binds
|
|
||||||
abstract fun bindLegacySessionImporter(importer: DefaultLegacySessionImporter): LegacySessionImporter
|
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun bindSessionParamsStore(store: RealmSessionParamsStore): SessionParamsStore
|
abstract fun bindSessionParamsStore(store: RealmSessionParamsStore): SessionParamsStore
|
||||||
|
|
||||||
|
|
|
@ -1,231 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.matrix.android.sdk.internal.legacy
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import io.realm.Realm
|
|
||||||
import io.realm.RealmConfiguration
|
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
import org.matrix.android.sdk.api.auth.LoginType
|
|
||||||
import org.matrix.android.sdk.api.auth.data.Credentials
|
|
||||||
import org.matrix.android.sdk.api.auth.data.DiscoveryInformation
|
|
||||||
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
|
|
||||||
import org.matrix.android.sdk.api.auth.data.SessionParams
|
|
||||||
import org.matrix.android.sdk.api.auth.data.WellKnownBaseConfig
|
|
||||||
import org.matrix.android.sdk.api.legacy.LegacySessionImporter
|
|
||||||
import org.matrix.android.sdk.api.network.ssl.Fingerprint
|
|
||||||
import org.matrix.android.sdk.api.util.md5
|
|
||||||
import org.matrix.android.sdk.internal.auth.SessionParamsStore
|
|
||||||
import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStoreMigration
|
|
||||||
import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStoreModule
|
|
||||||
import org.matrix.android.sdk.internal.database.RealmKeysUtils
|
|
||||||
import org.matrix.android.sdk.internal.legacy.riot.LoginStorage
|
|
||||||
import org.matrix.android.sdk.internal.util.time.Clock
|
|
||||||
import timber.log.Timber
|
|
||||||
import java.io.File
|
|
||||||
import javax.inject.Inject
|
|
||||||
import org.matrix.android.sdk.internal.legacy.riot.Fingerprint as LegacyFingerprint
|
|
||||||
import org.matrix.android.sdk.internal.legacy.riot.HomeServerConnectionConfig as LegacyHomeServerConnectionConfig
|
|
||||||
|
|
||||||
internal class DefaultLegacySessionImporter @Inject constructor(
|
|
||||||
private val context: Context,
|
|
||||||
private val sessionParamsStore: SessionParamsStore,
|
|
||||||
private val realmKeysUtils: RealmKeysUtils,
|
|
||||||
private val clock: Clock,
|
|
||||||
) : LegacySessionImporter {
|
|
||||||
|
|
||||||
private val loginStorage = LoginStorage(context)
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
// During development, set to false to play several times the migration
|
|
||||||
private var DELETE_PREVIOUS_DATA = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun process(): Boolean {
|
|
||||||
Timber.d("Migration: Importing legacy session")
|
|
||||||
|
|
||||||
val list = loginStorage.credentialsList
|
|
||||||
|
|
||||||
Timber.d("Migration: found ${list.size} session(s).")
|
|
||||||
|
|
||||||
val legacyConfig = list.firstOrNull() ?: return false
|
|
||||||
|
|
||||||
runBlocking {
|
|
||||||
Timber.d("Migration: importing a session")
|
|
||||||
try {
|
|
||||||
importCredentials(legacyConfig)
|
|
||||||
} catch (t: Throwable) {
|
|
||||||
// It can happen in case of partial migration. To test, do not return
|
|
||||||
Timber.e(t, "Migration: Error importing credential")
|
|
||||||
}
|
|
||||||
|
|
||||||
Timber.d("Migration: importing crypto DB")
|
|
||||||
try {
|
|
||||||
importCryptoDb(legacyConfig)
|
|
||||||
} catch (t: Throwable) {
|
|
||||||
// It can happen in case of partial migration. To test, do not return
|
|
||||||
Timber.e(t, "Migration: Error importing crypto DB")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DELETE_PREVIOUS_DATA) {
|
|
||||||
try {
|
|
||||||
Timber.d("Migration: clear file system")
|
|
||||||
clearFileSystem(legacyConfig)
|
|
||||||
} catch (t: Throwable) {
|
|
||||||
Timber.e(t, "Migration: Error clearing filesystem")
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
Timber.d("Migration: clear shared prefs")
|
|
||||||
clearSharedPrefs()
|
|
||||||
} catch (t: Throwable) {
|
|
||||||
Timber.e(t, "Migration: Error clearing shared prefs")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Timber.d("Migration: clear file system - DEACTIVATED")
|
|
||||||
Timber.d("Migration: clear shared prefs - DEACTIVATED")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A session has been imported
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun importCredentials(legacyConfig: LegacyHomeServerConnectionConfig) {
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
val sessionParams = SessionParams(
|
|
||||||
credentials = Credentials(
|
|
||||||
userId = legacyConfig.credentials.userId,
|
|
||||||
accessToken = legacyConfig.credentials.accessToken,
|
|
||||||
refreshToken = legacyConfig.credentials.refreshToken,
|
|
||||||
homeServer = legacyConfig.credentials.homeServer,
|
|
||||||
deviceId = legacyConfig.credentials.deviceId,
|
|
||||||
discoveryInformation = legacyConfig.credentials.wellKnown?.let { wellKnown ->
|
|
||||||
// Note credentials.wellKnown is not serialized in the LoginStorage, so this code is a bit useless...
|
|
||||||
if (wellKnown.homeServer?.baseURL != null || wellKnown.identityServer?.baseURL != null) {
|
|
||||||
DiscoveryInformation(
|
|
||||||
homeServer = wellKnown.homeServer?.baseURL?.let { WellKnownBaseConfig(baseURL = it) },
|
|
||||||
identityServer = wellKnown.identityServer?.baseURL?.let { WellKnownBaseConfig(baseURL = it) }
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
),
|
|
||||||
homeServerConnectionConfig = HomeServerConnectionConfig(
|
|
||||||
homeServerUri = legacyConfig.homeserverUri,
|
|
||||||
identityServerUri = legacyConfig.identityServerUri,
|
|
||||||
antiVirusServerUri = legacyConfig.antiVirusServerUri,
|
|
||||||
allowedFingerprints = legacyConfig.allowedFingerprints.map {
|
|
||||||
Fingerprint(
|
|
||||||
bytes = it.bytes,
|
|
||||||
hashType = when (it.type) {
|
|
||||||
LegacyFingerprint.HashType.SHA1,
|
|
||||||
null -> Fingerprint.HashType.SHA1
|
|
||||||
LegacyFingerprint.HashType.SHA256 -> Fingerprint.HashType.SHA256
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
shouldPin = legacyConfig.shouldPin(),
|
|
||||||
tlsVersions = legacyConfig.acceptedTlsVersions,
|
|
||||||
tlsCipherSuites = legacyConfig.acceptedTlsCipherSuites,
|
|
||||||
shouldAcceptTlsExtensions = legacyConfig.shouldAcceptTlsExtensions(),
|
|
||||||
allowHttpExtension = false, // TODO
|
|
||||||
forceUsageTlsVersions = legacyConfig.forceUsageOfTlsVersions()
|
|
||||||
),
|
|
||||||
// If token is not valid, this boolean will be updated later
|
|
||||||
isTokenValid = true,
|
|
||||||
loginType = LoginType.UNKNOWN,
|
|
||||||
)
|
|
||||||
|
|
||||||
Timber.d("Migration: save session")
|
|
||||||
sessionParamsStore.save(sessionParams)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun importCryptoDb(legacyConfig: LegacyHomeServerConnectionConfig) {
|
|
||||||
// Here we migrate the DB, we copy the crypto DB to the location specific to Matrix SDK2, and we encrypt it.
|
|
||||||
val userMd5 = legacyConfig.credentials.userId.md5()
|
|
||||||
|
|
||||||
val sessionId = legacyConfig.credentials.let { (if (it.deviceId.isNullOrBlank()) it.userId else "${it.userId}|${it.deviceId}").md5() }
|
|
||||||
val newLocation = File(context.filesDir, sessionId)
|
|
||||||
|
|
||||||
val keyAlias = "crypto_module_$userMd5"
|
|
||||||
|
|
||||||
// Ensure newLocation does not exist (can happen in case of partial migration)
|
|
||||||
newLocation.deleteRecursively()
|
|
||||||
newLocation.mkdirs()
|
|
||||||
|
|
||||||
val realmCryptoStoreMigration = RealmCryptoStoreMigration(clock)
|
|
||||||
|
|
||||||
Timber.d("Migration: create legacy realm configuration")
|
|
||||||
|
|
||||||
val realmConfiguration = RealmConfiguration.Builder()
|
|
||||||
.directory(File(context.filesDir, userMd5))
|
|
||||||
.name("crypto_store.realm")
|
|
||||||
.modules(RealmCryptoStoreModule())
|
|
||||||
.schemaVersion(realmCryptoStoreMigration.schemaVersion)
|
|
||||||
.migration(realmCryptoStoreMigration)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
Timber.d("Migration: copy DB to encrypted DB")
|
|
||||||
Realm.getInstance(realmConfiguration).use {
|
|
||||||
// Move the DB to the new location, handled by Matrix SDK2
|
|
||||||
it.writeEncryptedCopyTo(File(newLocation, realmConfiguration.realmFileName), realmKeysUtils.getRealmEncryptionKey(keyAlias))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete all the files created by Riot Android which will not be used anymore by Element
|
|
||||||
private fun clearFileSystem(legacyConfig: LegacyHomeServerConnectionConfig) {
|
|
||||||
val cryptoFolder = legacyConfig.credentials.userId.md5()
|
|
||||||
|
|
||||||
listOf(
|
|
||||||
// Where session store was saved (we do not care about migrating that, an initial sync will be performed)
|
|
||||||
File(context.filesDir, "MXFileStore"),
|
|
||||||
// Previous (and very old) file crypto store
|
|
||||||
File(context.filesDir, "MXFileCryptoStore"),
|
|
||||||
// Draft. They will be lost, this is sad but we assume it
|
|
||||||
File(context.filesDir, "MXLatestMessagesStore"),
|
|
||||||
// Media storage
|
|
||||||
File(context.filesDir, "MXMediaStore"),
|
|
||||||
File(context.filesDir, "MXMediaStore2"),
|
|
||||||
File(context.filesDir, "MXMediaStore3"),
|
|
||||||
// Ext folder
|
|
||||||
File(context.filesDir, "ext_share"),
|
|
||||||
// Crypto store
|
|
||||||
File(context.filesDir, cryptoFolder)
|
|
||||||
).forEach { file ->
|
|
||||||
try {
|
|
||||||
file.deleteRecursively()
|
|
||||||
} catch (t: Throwable) {
|
|
||||||
Timber.e(t, "Migration: unable to delete $file")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun clearSharedPrefs() {
|
|
||||||
// Shared Pref. Note that we do not delete the default preferences, as it should be nearly the same (TODO check that)
|
|
||||||
listOf(
|
|
||||||
"Vector.LoginStorage",
|
|
||||||
"GcmRegistrationManager",
|
|
||||||
"IntegrationManager.Storage"
|
|
||||||
).forEach { prefName ->
|
|
||||||
context.getSharedPreferences(prefName, Context.MODE_PRIVATE)
|
|
||||||
.edit()
|
|
||||||
.clear()
|
|
||||||
.apply()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,110 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.matrix.android.sdk.internal.legacy.riot;
|
|
||||||
|
|
||||||
import android.text.TextUtils;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <b>IMPORTANT:</b> This class is imported from Riot-Android to be able to perform a migration. Do not use it for any other purpose
|
|
||||||
*
|
|
||||||
* The user's credentials.
|
|
||||||
*/
|
|
||||||
public class Credentials {
|
|
||||||
public String userId;
|
|
||||||
|
|
||||||
// This is the server name and not a URI, e.g. "matrix.org". Spec says it's now deprecated
|
|
||||||
@Deprecated
|
|
||||||
public String homeServer;
|
|
||||||
|
|
||||||
public String accessToken;
|
|
||||||
|
|
||||||
public String refreshToken;
|
|
||||||
|
|
||||||
public String deviceId;
|
|
||||||
|
|
||||||
// Optional data that may contain info to override homeserver and/or identity server
|
|
||||||
public WellKnown wellKnown;
|
|
||||||
|
|
||||||
public JSONObject toJson() throws JSONException {
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
|
|
||||||
json.put("user_id", userId);
|
|
||||||
json.put("home_server", homeServer);
|
|
||||||
json.put("access_token", accessToken);
|
|
||||||
json.put("refresh_token", TextUtils.isEmpty(refreshToken) ? JSONObject.NULL : refreshToken);
|
|
||||||
json.put("device_id", deviceId);
|
|
||||||
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Credentials fromJson(JSONObject obj) throws JSONException {
|
|
||||||
Credentials creds = new Credentials();
|
|
||||||
creds.userId = obj.getString("user_id");
|
|
||||||
creds.homeServer = obj.getString("home_server");
|
|
||||||
creds.accessToken = obj.getString("access_token");
|
|
||||||
|
|
||||||
if (obj.has("device_id")) {
|
|
||||||
creds.deviceId = obj.getString("device_id");
|
|
||||||
}
|
|
||||||
|
|
||||||
// refresh_token is mandatory
|
|
||||||
if (obj.has("refresh_token")) {
|
|
||||||
try {
|
|
||||||
creds.refreshToken = obj.getString("refresh_token");
|
|
||||||
} catch (Exception e) {
|
|
||||||
creds.refreshToken = null;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new RuntimeException("refresh_token is required.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return creds;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Credentials{" +
|
|
||||||
"userId='" + userId + '\'' +
|
|
||||||
", homeServer='" + homeServer + '\'' +
|
|
||||||
", refreshToken.length='" + (refreshToken != null ? refreshToken.length() : "null") + '\'' +
|
|
||||||
", accessToken.length='" + (accessToken != null ? accessToken.length() : "null") + '\'' +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public String getUserId() {
|
|
||||||
return userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public String getHomeServer() {
|
|
||||||
return homeServer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public String getAccessToken() {
|
|
||||||
return accessToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public String getDeviceId() {
|
|
||||||
return deviceId;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,94 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.matrix.android.sdk.internal.legacy.riot;
|
|
||||||
|
|
||||||
import android.util.Base64;
|
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <b>IMPORTANT:</b> This class is imported from Riot-Android to be able to perform a migration. Do not use it for any other purpose
|
|
||||||
*
|
|
||||||
* Represents a X509 Certificate fingerprint.
|
|
||||||
*/
|
|
||||||
public class Fingerprint {
|
|
||||||
public enum HashType {
|
|
||||||
SHA1,
|
|
||||||
SHA256
|
|
||||||
}
|
|
||||||
|
|
||||||
private final HashType mHashType;
|
|
||||||
private final byte[] mBytes;
|
|
||||||
|
|
||||||
public Fingerprint(HashType hashType, byte[] bytes) {
|
|
||||||
mHashType = hashType;
|
|
||||||
mBytes = bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HashType getType() {
|
|
||||||
return mHashType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getBytes() {
|
|
||||||
return mBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JSONObject toJson() throws JSONException {
|
|
||||||
JSONObject obj = new JSONObject();
|
|
||||||
obj.put("bytes", Base64.encodeToString(getBytes(), Base64.DEFAULT));
|
|
||||||
obj.put("hash_type", mHashType.toString());
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Fingerprint fromJson(JSONObject obj) throws JSONException {
|
|
||||||
String hashTypeStr = obj.getString("hash_type");
|
|
||||||
byte[] fingerprintBytes = Base64.decode(obj.getString("bytes"), Base64.DEFAULT);
|
|
||||||
|
|
||||||
final HashType hashType;
|
|
||||||
if ("SHA256".equalsIgnoreCase(hashTypeStr)) {
|
|
||||||
hashType = HashType.SHA256;
|
|
||||||
} else if ("SHA1".equalsIgnoreCase(hashTypeStr)) {
|
|
||||||
hashType = HashType.SHA1;
|
|
||||||
} else {
|
|
||||||
throw new JSONException("Unrecognized hash type: " + hashTypeStr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Fingerprint(hashType, fingerprintBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
|
|
||||||
Fingerprint that = (Fingerprint) o;
|
|
||||||
|
|
||||||
if (!Arrays.equals(mBytes, that.mBytes)) return false;
|
|
||||||
return mHashType == that.mHashType;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int result = mBytes != null ? Arrays.hashCode(mBytes) : 0;
|
|
||||||
result = 31 * result + (mHashType != null ? mHashType.hashCode() : 0);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,674 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.matrix.android.sdk.internal.legacy.riot;
|
|
||||||
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.json.JSONArray;
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.net.Proxy;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import okhttp3.CipherSuite;
|
|
||||||
import okhttp3.TlsVersion;
|
|
||||||
import timber.log.Timber;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <b>IMPORTANT:</b> This class is imported from Riot-Android to be able to perform a migration. Do not use it for any other purpose
|
|
||||||
*
|
|
||||||
* Represents how to connect to a specific Homeserver, may include credentials to use.
|
|
||||||
*/
|
|
||||||
public class HomeServerConnectionConfig {
|
|
||||||
|
|
||||||
// the homeserver URI
|
|
||||||
private Uri mHomeServerUri;
|
|
||||||
// the jitsi server URI. Can be null
|
|
||||||
@Nullable
|
|
||||||
private Uri mJitsiServerUri;
|
|
||||||
// the identity server URI. Can be null
|
|
||||||
@Nullable
|
|
||||||
private Uri mIdentityServerUri;
|
|
||||||
// the anti-virus server URI
|
|
||||||
private Uri mAntiVirusServerUri;
|
|
||||||
// allowed fingerprints
|
|
||||||
private List<Fingerprint> mAllowedFingerprints = new ArrayList<>();
|
|
||||||
// the credentials
|
|
||||||
private Credentials mCredentials;
|
|
||||||
// tell whether we should reject X509 certs that were issued by trusts CAs and only trustcerts with matching fingerprints.
|
|
||||||
private boolean mPin;
|
|
||||||
// the accepted TLS versions
|
|
||||||
private List<TlsVersion> mTlsVersions;
|
|
||||||
// the accepted TLS cipher suites
|
|
||||||
private List<CipherSuite> mTlsCipherSuites;
|
|
||||||
// should accept TLS extensions
|
|
||||||
private boolean mShouldAcceptTlsExtensions = true;
|
|
||||||
// Force usage of TLS versions
|
|
||||||
private boolean mForceUsageTlsVersions;
|
|
||||||
// the proxy hostname
|
|
||||||
private String mProxyHostname;
|
|
||||||
// the proxy port
|
|
||||||
private int mProxyPort = -1;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private constructor. Please use the Builder
|
|
||||||
*/
|
|
||||||
private HomeServerConnectionConfig() {
|
|
||||||
// Private constructor
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the homeserver URI.
|
|
||||||
*
|
|
||||||
* @param uri the new HS uri
|
|
||||||
*/
|
|
||||||
public void setHomeserverUri(Uri uri) {
|
|
||||||
mHomeServerUri = uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the homeserver uri
|
|
||||||
*/
|
|
||||||
public Uri getHomeserverUri() {
|
|
||||||
return mHomeServerUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the jitsi server uri
|
|
||||||
*/
|
|
||||||
public Uri getJitsiServerUri() {
|
|
||||||
return mJitsiServerUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the identity server uri, or null if not defined
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public Uri getIdentityServerUri() {
|
|
||||||
return mIdentityServerUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the anti-virus server uri
|
|
||||||
*/
|
|
||||||
public Uri getAntiVirusServerUri() {
|
|
||||||
if (null != mAntiVirusServerUri) {
|
|
||||||
return mAntiVirusServerUri;
|
|
||||||
}
|
|
||||||
// Else consider the HS uri by default.
|
|
||||||
return mHomeServerUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the allowed fingerprints.
|
|
||||||
*/
|
|
||||||
public List<Fingerprint> getAllowedFingerprints() {
|
|
||||||
return mAllowedFingerprints;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the credentials
|
|
||||||
*/
|
|
||||||
public Credentials getCredentials() {
|
|
||||||
return mCredentials;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the credentials.
|
|
||||||
*
|
|
||||||
* @param credentials the new credentials
|
|
||||||
*/
|
|
||||||
public void setCredentials(Credentials credentials) {
|
|
||||||
mCredentials = credentials;
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(homeServerUrl)) {
|
|
||||||
// remove trailing "/"
|
|
||||||
if (homeServerUrl.endsWith("/")) {
|
|
||||||
homeServerUrl = homeServerUrl.substring(0, homeServerUrl.length() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Timber.d("Overriding homeserver url to " + homeServerUrl);
|
|
||||||
mHomeServerUri = Uri.parse(homeServerUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (credentials.wellKnown.identityServer != null) {
|
|
||||||
String identityServerUrl = credentials.wellKnown.identityServer.baseURL;
|
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(identityServerUrl)) {
|
|
||||||
// remove trailing "/"
|
|
||||||
if (identityServerUrl.endsWith("/")) {
|
|
||||||
identityServerUrl = identityServerUrl.substring(0, identityServerUrl.length() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Timber.d("Overriding identity server url to " + identityServerUrl);
|
|
||||||
mIdentityServerUri = Uri.parse(identityServerUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (credentials.wellKnown.jitsiServer != null) {
|
|
||||||
String jitsiServerUrl = credentials.wellKnown.jitsiServer.preferredDomain;
|
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(jitsiServerUrl)) {
|
|
||||||
// add trailing "/"
|
|
||||||
if (!jitsiServerUrl.endsWith("/")) {
|
|
||||||
jitsiServerUrl = jitsiServerUrl + "/";
|
|
||||||
}
|
|
||||||
|
|
||||||
Timber.d("Overriding jitsi server url to " + jitsiServerUrl);
|
|
||||||
mJitsiServerUri = Uri.parse(jitsiServerUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return whether we should reject X509 certs that were issued by trusts CAs and only trust
|
|
||||||
* certs with matching fingerprints.
|
|
||||||
*/
|
|
||||||
public boolean shouldPin() {
|
|
||||||
return mPin;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TLS versions accepted for TLS connections with the homeserver.
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public List<TlsVersion> getAcceptedTlsVersions() {
|
|
||||||
return mTlsVersions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TLS cipher suites accepted for TLS connections with the homeserver.
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public List<CipherSuite> getAcceptedTlsCipherSuites() {
|
|
||||||
return mTlsCipherSuites;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return whether we should accept TLS extensions.
|
|
||||||
*/
|
|
||||||
public boolean shouldAcceptTlsExtensions() {
|
|
||||||
return mShouldAcceptTlsExtensions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if the usage of TlsVersions has to be forced
|
|
||||||
*/
|
|
||||||
public boolean forceUsageOfTlsVersions() {
|
|
||||||
return mForceUsageTlsVersions;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return proxy config if available
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public Proxy getProxyConfig() {
|
|
||||||
if (mProxyHostname == null || mProxyHostname.length() == 0 || mProxyPort == -1) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Proxy(Proxy.Type.HTTP,
|
|
||||||
new InetSocketAddress(mProxyHostname, mProxyPort));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "HomeserverConnectionConfig{" +
|
|
||||||
"mHomeServerUri=" + mHomeServerUri +
|
|
||||||
", mJitsiServerUri=" + mJitsiServerUri +
|
|
||||||
", mIdentityServerUri=" + mIdentityServerUri +
|
|
||||||
", mAntiVirusServerUri=" + mAntiVirusServerUri +
|
|
||||||
", mAllowedFingerprints size=" + mAllowedFingerprints.size() +
|
|
||||||
", mCredentials=" + mCredentials +
|
|
||||||
", mPin=" + mPin +
|
|
||||||
", mShouldAcceptTlsExtensions=" + mShouldAcceptTlsExtensions +
|
|
||||||
", mProxyHostname=" + (null == mProxyHostname ? "" : mProxyHostname) +
|
|
||||||
", mProxyPort=" + (-1 == mProxyPort ? "" : mProxyPort) +
|
|
||||||
", mTlsVersions=" + (null == mTlsVersions ? "" : mTlsVersions.size()) +
|
|
||||||
", mTlsCipherSuites=" + (null == mTlsCipherSuites ? "" : mTlsCipherSuites.size()) +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert the object instance into a JSon object
|
|
||||||
*
|
|
||||||
* @return the JSon representation
|
|
||||||
* @throws JSONException the JSON conversion failure reason
|
|
||||||
*/
|
|
||||||
public JSONObject toJson() throws JSONException {
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
|
|
||||||
json.put("home_server_url", mHomeServerUri.toString());
|
|
||||||
Uri jitsiServerUri = getJitsiServerUri();
|
|
||||||
if (jitsiServerUri != null) {
|
|
||||||
json.put("jitsi_server_url", jitsiServerUri.toString());
|
|
||||||
}
|
|
||||||
Uri identityServerUri = getIdentityServerUri();
|
|
||||||
if (identityServerUri != null) {
|
|
||||||
json.put("identity_server_url", identityServerUri.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mAntiVirusServerUri != null) {
|
|
||||||
json.put("antivirus_server_url", mAntiVirusServerUri.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
json.put("pin", mPin);
|
|
||||||
|
|
||||||
if (mCredentials != null) json.put("credentials", mCredentials.toJson());
|
|
||||||
if (mAllowedFingerprints != null) {
|
|
||||||
List<JSONObject> fingerprints = new ArrayList<>(mAllowedFingerprints.size());
|
|
||||||
|
|
||||||
for (Fingerprint fingerprint : mAllowedFingerprints) {
|
|
||||||
fingerprints.add(fingerprint.toJson());
|
|
||||||
}
|
|
||||||
|
|
||||||
json.put("fingerprints", new JSONArray(fingerprints));
|
|
||||||
}
|
|
||||||
|
|
||||||
json.put("tls_extensions", mShouldAcceptTlsExtensions);
|
|
||||||
|
|
||||||
if (mTlsVersions != null) {
|
|
||||||
List<String> tlsVersions = new ArrayList<>(mTlsVersions.size());
|
|
||||||
|
|
||||||
for (TlsVersion tlsVersion : mTlsVersions) {
|
|
||||||
tlsVersions.add(tlsVersion.javaName());
|
|
||||||
}
|
|
||||||
|
|
||||||
json.put("tls_versions", new JSONArray(tlsVersions));
|
|
||||||
}
|
|
||||||
|
|
||||||
json.put("force_usage_of_tls_versions", mForceUsageTlsVersions);
|
|
||||||
|
|
||||||
if (mTlsCipherSuites != null) {
|
|
||||||
List<String> tlsCipherSuites = new ArrayList<>(mTlsCipherSuites.size());
|
|
||||||
|
|
||||||
for (CipherSuite tlsCipherSuite : mTlsCipherSuites) {
|
|
||||||
tlsCipherSuites.add(tlsCipherSuite.javaName());
|
|
||||||
}
|
|
||||||
|
|
||||||
json.put("tls_cipher_suites", new JSONArray(tlsCipherSuites));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mProxyPort != -1) {
|
|
||||||
json.put("proxy_port", mProxyPort);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mProxyHostname != null && mProxyHostname.length() > 0) {
|
|
||||||
json.put("proxy_hostname", mProxyHostname);
|
|
||||||
}
|
|
||||||
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an object instance from the json object.
|
|
||||||
*
|
|
||||||
* @param jsonObject the json object
|
|
||||||
* @return a HomeServerConnectionConfig instance
|
|
||||||
* @throws JSONException the conversion failure reason
|
|
||||||
*/
|
|
||||||
public static HomeServerConnectionConfig fromJson(JSONObject jsonObject) throws JSONException {
|
|
||||||
JSONObject credentialsObj = jsonObject.optJSONObject("credentials");
|
|
||||||
Credentials creds = credentialsObj != null ? Credentials.fromJson(credentialsObj) : null;
|
|
||||||
|
|
||||||
Builder builder = new Builder()
|
|
||||||
.withHomeServerUri(Uri.parse(jsonObject.getString("home_server_url")))
|
|
||||||
.withJitsiServerUri(jsonObject.has("jitsi_server_url") ? Uri.parse(jsonObject.getString("jitsi_server_url")) : null)
|
|
||||||
.withIdentityServerUri(jsonObject.has("identity_server_url") ? Uri.parse(jsonObject.getString("identity_server_url")) : null)
|
|
||||||
.withCredentials(creds)
|
|
||||||
.withPin(jsonObject.optBoolean("pin", false));
|
|
||||||
|
|
||||||
JSONArray fingerprintArray = jsonObject.optJSONArray("fingerprints");
|
|
||||||
if (fingerprintArray != null) {
|
|
||||||
for (int i = 0; i < fingerprintArray.length(); i++) {
|
|
||||||
builder.addAllowedFingerPrint(Fingerprint.fromJson(fingerprintArray.getJSONObject(i)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the anti-virus server uri if any
|
|
||||||
if (jsonObject.has("antivirus_server_url")) {
|
|
||||||
builder.withAntiVirusServerUri(Uri.parse(jsonObject.getString("antivirus_server_url")));
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.withShouldAcceptTlsExtensions(jsonObject.optBoolean("tls_extensions", true));
|
|
||||||
|
|
||||||
// Set the TLS versions if any
|
|
||||||
if (jsonObject.has("tls_versions")) {
|
|
||||||
JSONArray tlsVersionsArray = jsonObject.optJSONArray("tls_versions");
|
|
||||||
if (tlsVersionsArray != null) {
|
|
||||||
for (int i = 0; i < tlsVersionsArray.length(); i++) {
|
|
||||||
builder.addAcceptedTlsVersion(TlsVersion.forJavaName(tlsVersionsArray.getString(i)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.forceUsageOfTlsVersions(jsonObject.optBoolean("force_usage_of_tls_versions", false));
|
|
||||||
|
|
||||||
// Set the TLS cipher suites if any
|
|
||||||
if (jsonObject.has("tls_cipher_suites")) {
|
|
||||||
JSONArray tlsCipherSuitesArray = jsonObject.optJSONArray("tls_cipher_suites");
|
|
||||||
if (tlsCipherSuitesArray != null) {
|
|
||||||
for (int i = 0; i < tlsCipherSuitesArray.length(); i++) {
|
|
||||||
builder.addAcceptedTlsCipherSuite(CipherSuite.forJavaName(tlsCipherSuitesArray.getString(i)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the proxy options right if any
|
|
||||||
if (jsonObject.has("proxy_hostname") && jsonObject.has("proxy_port")) {
|
|
||||||
builder.withProxy(jsonObject.getString("proxy_hostname"), jsonObject.getInt("proxy_port"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builder
|
|
||||||
*/
|
|
||||||
public static class Builder {
|
|
||||||
private HomeServerConnectionConfig mHomeServerConnectionConfig;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builder constructor
|
|
||||||
*/
|
|
||||||
public Builder() {
|
|
||||||
mHomeServerConnectionConfig = new HomeServerConnectionConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* create a Builder from an existing HomeServerConnectionConfig
|
|
||||||
*/
|
|
||||||
public Builder(HomeServerConnectionConfig from) {
|
|
||||||
try {
|
|
||||||
mHomeServerConnectionConfig = HomeServerConnectionConfig.fromJson(from.toJson());
|
|
||||||
} catch (JSONException e) {
|
|
||||||
// Should not happen
|
|
||||||
throw new RuntimeException("Unable to create a HomeServerConnectionConfig", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param homeServerUri The URI to use to connect to the homeserver. Cannot be null
|
|
||||||
* @return this builder
|
|
||||||
*/
|
|
||||||
public Builder withHomeServerUri(final Uri homeServerUri) {
|
|
||||||
if (homeServerUri == null || (!"http".equals(homeServerUri.getScheme()) && !"https".equals(homeServerUri.getScheme()))) {
|
|
||||||
throw new RuntimeException("Invalid homeserver URI: " + homeServerUri);
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove trailing /
|
|
||||||
if (homeServerUri.toString().endsWith("/")) {
|
|
||||||
try {
|
|
||||||
String url = homeServerUri.toString();
|
|
||||||
mHomeServerConnectionConfig.mHomeServerUri = Uri.parse(url.substring(0, url.length() - 1));
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("Invalid homeserver URI: " + homeServerUri);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mHomeServerConnectionConfig.mHomeServerUri = homeServerUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param jitsiServerUri The URI to use to manage identity. Can be null
|
|
||||||
* @return this builder
|
|
||||||
*/
|
|
||||||
public Builder withJitsiServerUri(@Nullable final Uri jitsiServerUri) {
|
|
||||||
if (jitsiServerUri != null
|
|
||||||
&& !jitsiServerUri.toString().isEmpty()
|
|
||||||
&& !"http".equals(jitsiServerUri.getScheme())
|
|
||||||
&& !"https".equals(jitsiServerUri.getScheme())) {
|
|
||||||
throw new RuntimeException("Invalid jitsi server URI: " + jitsiServerUri);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add trailing /
|
|
||||||
if ((null != jitsiServerUri) && !jitsiServerUri.toString().endsWith("/")) {
|
|
||||||
try {
|
|
||||||
String url = jitsiServerUri.toString();
|
|
||||||
mHomeServerConnectionConfig.mJitsiServerUri = Uri.parse(url + "/");
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("Invalid jitsi server URI: " + jitsiServerUri);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (jitsiServerUri != null && jitsiServerUri.toString().isEmpty()) {
|
|
||||||
mHomeServerConnectionConfig.mJitsiServerUri = null;
|
|
||||||
} else {
|
|
||||||
mHomeServerConnectionConfig.mJitsiServerUri = jitsiServerUri;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param identityServerUri The URI to use to manage identity. Can be null
|
|
||||||
* @return this builder
|
|
||||||
*/
|
|
||||||
public Builder withIdentityServerUri(@Nullable final Uri identityServerUri) {
|
|
||||||
if (identityServerUri != null
|
|
||||||
&& !identityServerUri.toString().isEmpty()
|
|
||||||
&& !"http".equals(identityServerUri.getScheme())
|
|
||||||
&& !"https".equals(identityServerUri.getScheme())) {
|
|
||||||
throw new RuntimeException("Invalid identity server URI: " + identityServerUri);
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove trailing /
|
|
||||||
if ((null != identityServerUri) && identityServerUri.toString().endsWith("/")) {
|
|
||||||
try {
|
|
||||||
String url = identityServerUri.toString();
|
|
||||||
mHomeServerConnectionConfig.mIdentityServerUri = Uri.parse(url.substring(0, url.length() - 1));
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("Invalid identity server URI: " + identityServerUri);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (identityServerUri != null && identityServerUri.toString().isEmpty()) {
|
|
||||||
mHomeServerConnectionConfig.mIdentityServerUri = null;
|
|
||||||
} else {
|
|
||||||
mHomeServerConnectionConfig.mIdentityServerUri = identityServerUri;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param credentials The credentials to use, if needed. Can be null.
|
|
||||||
* @return this builder
|
|
||||||
*/
|
|
||||||
public Builder withCredentials(@Nullable Credentials credentials) {
|
|
||||||
mHomeServerConnectionConfig.mCredentials = credentials;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param allowedFingerprint If using SSL, allow server certs that match this fingerprint.
|
|
||||||
* @return this builder
|
|
||||||
*/
|
|
||||||
public Builder addAllowedFingerPrint(@Nullable Fingerprint allowedFingerprint) {
|
|
||||||
if (allowedFingerprint != null) {
|
|
||||||
mHomeServerConnectionConfig.mAllowedFingerprints.add(allowedFingerprint);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param pin If true only allow certs matching given fingerprints, otherwise fallback to
|
|
||||||
* standard X509 checks.
|
|
||||||
* @return this builder
|
|
||||||
*/
|
|
||||||
public Builder withPin(boolean pin) {
|
|
||||||
mHomeServerConnectionConfig.mPin = pin;
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param shouldAcceptTlsExtension
|
|
||||||
* @return this builder
|
|
||||||
*/
|
|
||||||
public Builder withShouldAcceptTlsExtensions(boolean shouldAcceptTlsExtension) {
|
|
||||||
mHomeServerConnectionConfig.mShouldAcceptTlsExtensions = shouldAcceptTlsExtension;
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
public Builder addAcceptedTlsVersion(@NonNull TlsVersion tlsVersion) {
|
|
||||||
if (mHomeServerConnectionConfig.mTlsVersions == null) {
|
|
||||||
mHomeServerConnectionConfig.mTlsVersions = new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
mHomeServerConnectionConfig.mTlsVersions.add(tlsVersion);
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Force the usage of TlsVersion. This can be usefull for device on Android version < 20
|
|
||||||
*
|
|
||||||
* @param forceUsageOfTlsVersions set to true to force the usage of specified TlsVersions (with {@link #addAcceptedTlsVersion(TlsVersion)}
|
|
||||||
* @return this builder
|
|
||||||
*/
|
|
||||||
public Builder forceUsageOfTlsVersions(boolean forceUsageOfTlsVersions) {
|
|
||||||
mHomeServerConnectionConfig.mForceUsageTlsVersions = forceUsageOfTlsVersions;
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
public Builder addAcceptedTlsCipherSuite(@NonNull CipherSuite tlsCipherSuite) {
|
|
||||||
if (mHomeServerConnectionConfig.mTlsCipherSuites == null) {
|
|
||||||
mHomeServerConnectionConfig.mTlsCipherSuites = new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
mHomeServerConnectionConfig.mTlsCipherSuites.add(tlsCipherSuite);
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the anti-virus server URI.
|
|
||||||
*
|
|
||||||
* @param antivirusServerUri the new anti-virus uri. Can be null
|
|
||||||
* @return this builder
|
|
||||||
*/
|
|
||||||
public Builder withAntiVirusServerUri(@Nullable Uri antivirusServerUri) {
|
|
||||||
if ((null != antivirusServerUri) && (!"http".equals(antivirusServerUri.getScheme()) && !"https".equals(antivirusServerUri.getScheme()))) {
|
|
||||||
throw new RuntimeException("Invalid antivirus server URI: " + antivirusServerUri);
|
|
||||||
}
|
|
||||||
|
|
||||||
mHomeServerConnectionConfig.mAntiVirusServerUri = antivirusServerUri;
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenient method to limit the TLS versions and cipher suites for this Builder
|
|
||||||
* Ref:
|
|
||||||
* - https://www.ssi.gouv.fr/uploads/2017/02/security-recommendations-for-tls_v1.1.pdf
|
|
||||||
* - https://developer.android.com/reference/javax/net/ssl/SSLEngine
|
|
||||||
*
|
|
||||||
* @param tlsLimitations true to use Tls limitations
|
|
||||||
* @param enableCompatibilityMode set to true for Android < 20
|
|
||||||
* @return this builder
|
|
||||||
*/
|
|
||||||
public Builder withTlsLimitations(boolean tlsLimitations, boolean enableCompatibilityMode) {
|
|
||||||
if (tlsLimitations) {
|
|
||||||
withShouldAcceptTlsExtensions(false);
|
|
||||||
|
|
||||||
// Tls versions
|
|
||||||
addAcceptedTlsVersion(TlsVersion.TLS_1_2);
|
|
||||||
addAcceptedTlsVersion(TlsVersion.TLS_1_3);
|
|
||||||
|
|
||||||
forceUsageOfTlsVersions(enableCompatibilityMode);
|
|
||||||
|
|
||||||
// Cipher suites
|
|
||||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256);
|
|
||||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256);
|
|
||||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256);
|
|
||||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256);
|
|
||||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384);
|
|
||||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384);
|
|
||||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256);
|
|
||||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256);
|
|
||||||
|
|
||||||
if (enableCompatibilityMode) {
|
|
||||||
// Adopt some preceding cipher suites for Android < 20 to be able to negotiate
|
|
||||||
// a TLS session.
|
|
||||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA);
|
|
||||||
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param proxyHostname Proxy Hostname
|
|
||||||
* @param proxyPort Proxy Port
|
|
||||||
* @return this builder
|
|
||||||
*/
|
|
||||||
public Builder withProxy(@Nullable String proxyHostname, int proxyPort) {
|
|
||||||
mHomeServerConnectionConfig.mProxyHostname = proxyHostname;
|
|
||||||
mHomeServerConnectionConfig.mProxyPort = proxyPort;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the {@link HomeServerConnectionConfig}
|
|
||||||
*/
|
|
||||||
public HomeServerConnectionConfig build() {
|
|
||||||
// Check mandatory parameters
|
|
||||||
if (mHomeServerConnectionConfig.mHomeServerUri == null) {
|
|
||||||
throw new RuntimeException("Homeserver URI not set");
|
|
||||||
}
|
|
||||||
|
|
||||||
return mHomeServerConnectionConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,206 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.matrix.android.sdk.internal.legacy.riot;
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
|
|
||||||
import org.json.JSONArray;
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import timber.log.Timber;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <b>IMPORTANT:</b> This class is imported from Riot-Android to be able to perform a migration. Do not use it for any other purpose
|
|
||||||
*
|
|
||||||
* Stores login credentials in SharedPreferences.
|
|
||||||
*/
|
|
||||||
public class LoginStorage {
|
|
||||||
private static final String PREFS_LOGIN = "Vector.LoginStorage";
|
|
||||||
|
|
||||||
// multi accounts + homeserver config
|
|
||||||
private static final String PREFS_KEY_CONNECTION_CONFIGS = "PREFS_KEY_CONNECTION_CONFIGS";
|
|
||||||
|
|
||||||
private final Context mContext;
|
|
||||||
|
|
||||||
public LoginStorage(Context appContext) {
|
|
||||||
mContext = appContext.getApplicationContext();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the list of homeserver configurations.
|
|
||||||
*/
|
|
||||||
public List<HomeServerConnectionConfig> getCredentialsList() {
|
|
||||||
SharedPreferences prefs = mContext.getSharedPreferences(PREFS_LOGIN, Context.MODE_PRIVATE);
|
|
||||||
|
|
||||||
String connectionConfigsString = prefs.getString(PREFS_KEY_CONNECTION_CONFIGS, null);
|
|
||||||
|
|
||||||
Timber.d("Got connection json: ");
|
|
||||||
|
|
||||||
if (connectionConfigsString == null) {
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
JSONArray connectionConfigsStrings = new JSONArray(connectionConfigsString);
|
|
||||||
|
|
||||||
List<HomeServerConnectionConfig> configList = new ArrayList<>(
|
|
||||||
connectionConfigsStrings.length()
|
|
||||||
);
|
|
||||||
|
|
||||||
for (int i = 0; i < connectionConfigsStrings.length(); i++) {
|
|
||||||
configList.add(
|
|
||||||
HomeServerConnectionConfig.fromJson(connectionConfigsStrings.getJSONObject(i))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return configList;
|
|
||||||
} catch (JSONException e) {
|
|
||||||
Timber.e(e, "Failed to deserialize accounts");
|
|
||||||
throw new RuntimeException("Failed to deserialize accounts");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a credentials to the credentials list
|
|
||||||
*
|
|
||||||
* @param config the homeserver config to add.
|
|
||||||
*/
|
|
||||||
public void addCredentials(HomeServerConnectionConfig config) {
|
|
||||||
if (null != config && config.getCredentials() != null) {
|
|
||||||
SharedPreferences prefs = mContext.getSharedPreferences(PREFS_LOGIN, Context.MODE_PRIVATE);
|
|
||||||
SharedPreferences.Editor editor = prefs.edit();
|
|
||||||
|
|
||||||
List<HomeServerConnectionConfig> configs = getCredentialsList();
|
|
||||||
|
|
||||||
configs.add(config);
|
|
||||||
|
|
||||||
List<JSONObject> serialized = new ArrayList<>(configs.size());
|
|
||||||
|
|
||||||
try {
|
|
||||||
for (HomeServerConnectionConfig c : configs) {
|
|
||||||
serialized.add(c.toJson());
|
|
||||||
}
|
|
||||||
} catch (JSONException e) {
|
|
||||||
throw new RuntimeException("Failed to serialize connection config");
|
|
||||||
}
|
|
||||||
|
|
||||||
String ser = new JSONArray(serialized).toString();
|
|
||||||
|
|
||||||
Timber.d("Storing " + serialized.size() + " credentials");
|
|
||||||
|
|
||||||
editor.putString(PREFS_KEY_CONNECTION_CONFIGS, ser);
|
|
||||||
editor.apply();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the credentials from credentials list
|
|
||||||
*
|
|
||||||
* @param config the credentials to remove
|
|
||||||
*/
|
|
||||||
public void removeCredentials(HomeServerConnectionConfig config) {
|
|
||||||
if (null != config && config.getCredentials() != null) {
|
|
||||||
Timber.d("Removing account: " + config.getCredentials().userId);
|
|
||||||
|
|
||||||
SharedPreferences prefs = mContext.getSharedPreferences(PREFS_LOGIN, Context.MODE_PRIVATE);
|
|
||||||
SharedPreferences.Editor editor = prefs.edit();
|
|
||||||
|
|
||||||
List<HomeServerConnectionConfig> configs = getCredentialsList();
|
|
||||||
List<JSONObject> serialized = new ArrayList<>(configs.size());
|
|
||||||
|
|
||||||
boolean found = false;
|
|
||||||
try {
|
|
||||||
for (HomeServerConnectionConfig c : configs) {
|
|
||||||
if (c.getCredentials().userId.equals(config.getCredentials().userId)) {
|
|
||||||
found = true;
|
|
||||||
} else {
|
|
||||||
serialized.add(c.toJson());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (JSONException e) {
|
|
||||||
throw new RuntimeException("Failed to serialize connection config");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) return;
|
|
||||||
|
|
||||||
String ser = new JSONArray(serialized).toString();
|
|
||||||
|
|
||||||
Timber.d("Storing " + serialized.size() + " credentials");
|
|
||||||
|
|
||||||
editor.putString(PREFS_KEY_CONNECTION_CONFIGS, ser);
|
|
||||||
editor.apply();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replace the credential from credentials list, based on credentials.userId.
|
|
||||||
* If it does not match an existing credential it does *not* insert the new credentials.
|
|
||||||
*
|
|
||||||
* @param config the credentials to insert
|
|
||||||
*/
|
|
||||||
public void replaceCredentials(HomeServerConnectionConfig config) {
|
|
||||||
if (null != config && config.getCredentials() != null) {
|
|
||||||
SharedPreferences prefs = mContext.getSharedPreferences(PREFS_LOGIN, Context.MODE_PRIVATE);
|
|
||||||
SharedPreferences.Editor editor = prefs.edit();
|
|
||||||
|
|
||||||
List<HomeServerConnectionConfig> configs = getCredentialsList();
|
|
||||||
List<JSONObject> serialized = new ArrayList<>(configs.size());
|
|
||||||
|
|
||||||
boolean found = false;
|
|
||||||
try {
|
|
||||||
for (HomeServerConnectionConfig c : configs) {
|
|
||||||
if (c.getCredentials().userId.equals(config.getCredentials().userId)) {
|
|
||||||
serialized.add(config.toJson());
|
|
||||||
found = true;
|
|
||||||
} else {
|
|
||||||
serialized.add(c.toJson());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (JSONException e) {
|
|
||||||
throw new RuntimeException("Failed to serialize connection config");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) return;
|
|
||||||
|
|
||||||
String ser = new JSONArray(serialized).toString();
|
|
||||||
|
|
||||||
Timber.d("Storing " + serialized.size() + " credentials");
|
|
||||||
|
|
||||||
editor.putString(PREFS_KEY_CONNECTION_CONFIGS, ser);
|
|
||||||
editor.apply();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear the stored values
|
|
||||||
*/
|
|
||||||
@SuppressLint("ApplySharedPref")
|
|
||||||
public void clear() {
|
|
||||||
SharedPreferences prefs = mContext.getSharedPreferences(PREFS_LOGIN, Context.MODE_PRIVATE);
|
|
||||||
SharedPreferences.Editor editor = prefs.edit();
|
|
||||||
editor.remove(PREFS_KEY_CONNECTION_CONFIGS);
|
|
||||||
//Need to commit now because called before forcing an app restart
|
|
||||||
editor.commit();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,96 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.matrix.android.sdk.internal.legacy.riot
|
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
|
||||||
import com.squareup.moshi.JsonClass
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <b>IMPORTANT:</b> This class is imported from Riot-Android to be able to perform a migration. Do not use it for any other purpose
|
|
||||||
*
|
|
||||||
* https://matrix.org/docs/spec/client_server/r0.4.0.html#server-discovery
|
|
||||||
* <pre>
|
|
||||||
* {
|
|
||||||
* "m.homeserver": {
|
|
||||||
* "base_url": "https://matrix.org"
|
|
||||||
* },
|
|
||||||
* "m.identity_server": {
|
|
||||||
* "base_url": "https://vector.im"
|
|
||||||
* }
|
|
||||||
* "m.integrations": {
|
|
||||||
* "managers": [
|
|
||||||
* {
|
|
||||||
* "api_url": "https://integrations.example.org",
|
|
||||||
* "ui_url": "https://integrations.example.org/ui"
|
|
||||||
* },
|
|
||||||
* {
|
|
||||||
* "api_url": "https://bots.example.org"
|
|
||||||
* }
|
|
||||||
* ]
|
|
||||||
* }
|
|
||||||
* "im.vector.riot.jitsi": {
|
|
||||||
* "preferredDomain": "https://jitsi.riot.im/"
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
@JsonClass(generateAdapter = true)
|
|
||||||
class WellKnown {
|
|
||||||
|
|
||||||
@JvmField
|
|
||||||
@Json(name = "m.homeserver")
|
|
||||||
var homeServer: WellKnownBaseConfig? = null
|
|
||||||
|
|
||||||
@JvmField
|
|
||||||
@Json(name = "m.identity_server")
|
|
||||||
var identityServer: WellKnownBaseConfig? = null
|
|
||||||
|
|
||||||
@JvmField
|
|
||||||
@Json(name = "m.integrations")
|
|
||||||
var integrations: Map<String, *>? = null
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the list of integration managers proposed.
|
|
||||||
*/
|
|
||||||
fun getIntegrationManagers(): List<WellKnownManagerConfig> {
|
|
||||||
val managers = ArrayList<WellKnownManagerConfig>()
|
|
||||||
integrations?.get("managers")?.let {
|
|
||||||
(it as? ArrayList<*>)?.let { configs ->
|
|
||||||
configs.forEach { config ->
|
|
||||||
(config as? Map<*, *>)?.let { map ->
|
|
||||||
val apiUrl = map["api_url"] as? String
|
|
||||||
val uiUrl = map["ui_url"] as? String ?: apiUrl
|
|
||||||
if (apiUrl != null &&
|
|
||||||
apiUrl.startsWith("https://") &&
|
|
||||||
uiUrl!!.startsWith("https://")) {
|
|
||||||
managers.add(
|
|
||||||
WellKnownManagerConfig(
|
|
||||||
apiUrl = apiUrl,
|
|
||||||
uiUrl = uiUrl
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return managers
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmField
|
|
||||||
@Json(name = "im.vector.riot.jitsi")
|
|
||||||
var jitsiServer: WellKnownPreferredConfig? = null
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.matrix.android.sdk.internal.legacy.riot
|
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
|
||||||
import com.squareup.moshi.JsonClass
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <b>IMPORTANT:</b> This class is imported from Riot-Android to be able to perform a migration. Do not use it for any other purpose
|
|
||||||
*
|
|
||||||
* https://matrix.org/docs/spec/client_server/r0.4.0.html#server-discovery
|
|
||||||
* <pre>
|
|
||||||
* {
|
|
||||||
* "base_url": "https://vector.im"
|
|
||||||
* }
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
@JsonClass(generateAdapter = true)
|
|
||||||
class WellKnownBaseConfig {
|
|
||||||
|
|
||||||
@JvmField
|
|
||||||
@Json(name = "base_url")
|
|
||||||
var baseURL: String? = null
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.matrix.android.sdk.internal.legacy.riot
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <b>IMPORTANT:</b> This class is imported from Riot-Android to be able to perform a migration. Do not use it for any other purpose
|
|
||||||
*/
|
|
||||||
data class WellKnownManagerConfig(
|
|
||||||
val apiUrl: String,
|
|
||||||
val uiUrl: String
|
|
||||||
)
|
|
|
@ -1,37 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.matrix.android.sdk.internal.legacy.riot
|
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
|
||||||
import com.squareup.moshi.JsonClass
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <b>IMPORTANT:</b> This class is imported from Riot-Android to be able to perform a migration. Do not use it for any other purpose
|
|
||||||
*
|
|
||||||
* https://matrix.org/docs/spec/client_server/r0.4.0.html#server-discovery
|
|
||||||
* <pre>
|
|
||||||
* {
|
|
||||||
* "preferredDomain": "https://jitsi.riot.im/"
|
|
||||||
* }
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
@JsonClass(generateAdapter = true)
|
|
||||||
class WellKnownPreferredConfig {
|
|
||||||
|
|
||||||
@JvmField
|
|
||||||
@Json(name = "preferredDomain")
|
|
||||||
var preferredDomain: String? = null
|
|
||||||
}
|
|
|
@ -54,7 +54,6 @@ import im.vector.app.core.resources.BuildMeta
|
||||||
import im.vector.app.features.analytics.VectorAnalytics
|
import im.vector.app.features.analytics.VectorAnalytics
|
||||||
import im.vector.app.features.call.webrtc.WebRtcCallManager
|
import im.vector.app.features.call.webrtc.WebRtcCallManager
|
||||||
import im.vector.app.features.configuration.VectorConfiguration
|
import im.vector.app.features.configuration.VectorConfiguration
|
||||||
import im.vector.app.features.disclaimer.DisclaimerDialog
|
|
||||||
import im.vector.app.features.invite.InvitesAcceptor
|
import im.vector.app.features.invite.InvitesAcceptor
|
||||||
import im.vector.app.features.lifecycle.VectorActivityLifecycleCallbacks
|
import im.vector.app.features.lifecycle.VectorActivityLifecycleCallbacks
|
||||||
import im.vector.app.features.notifications.NotificationDrawerManager
|
import im.vector.app.features.notifications.NotificationDrawerManager
|
||||||
|
@ -71,7 +70,6 @@ import im.vector.application.R
|
||||||
import org.jitsi.meet.sdk.log.JitsiMeetDefaultLogHandler
|
import org.jitsi.meet.sdk.log.JitsiMeetDefaultLogHandler
|
||||||
import org.matrix.android.sdk.api.Matrix
|
import org.matrix.android.sdk.api.Matrix
|
||||||
import org.matrix.android.sdk.api.auth.AuthenticationService
|
import org.matrix.android.sdk.api.auth.AuthenticationService
|
||||||
import org.matrix.android.sdk.api.legacy.LegacySessionImporter
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
@ -86,7 +84,6 @@ class VectorApplication :
|
||||||
WorkConfiguration.Provider {
|
WorkConfiguration.Provider {
|
||||||
|
|
||||||
lateinit var appContext: Context
|
lateinit var appContext: Context
|
||||||
@Inject lateinit var legacySessionImporter: LegacySessionImporter
|
|
||||||
@Inject lateinit var authenticationService: AuthenticationService
|
@Inject lateinit var authenticationService: AuthenticationService
|
||||||
@Inject lateinit var vectorConfiguration: VectorConfiguration
|
@Inject lateinit var vectorConfiguration: VectorConfiguration
|
||||||
@Inject lateinit var emojiCompatFontProvider: EmojiCompatFontProvider
|
@Inject lateinit var emojiCompatFontProvider: EmojiCompatFontProvider
|
||||||
|
@ -111,7 +108,6 @@ class VectorApplication :
|
||||||
@Inject lateinit var buildMeta: BuildMeta
|
@Inject lateinit var buildMeta: BuildMeta
|
||||||
@Inject lateinit var leakDetector: LeakDetector
|
@Inject lateinit var leakDetector: LeakDetector
|
||||||
@Inject lateinit var vectorLocale: VectorLocale
|
@Inject lateinit var vectorLocale: VectorLocale
|
||||||
@Inject lateinit var disclaimerDialog: DisclaimerDialog
|
|
||||||
|
|
||||||
// font thread handler
|
// font thread handler
|
||||||
private var fontThreadHandler: Handler? = null
|
private var fontThreadHandler: Handler? = null
|
||||||
|
@ -170,13 +166,6 @@ class VectorApplication :
|
||||||
|
|
||||||
notificationUtils.createNotificationChannels()
|
notificationUtils.createNotificationChannels()
|
||||||
|
|
||||||
// It can takes time, but do we care?
|
|
||||||
val sessionImported = legacySessionImporter.process()
|
|
||||||
if (!sessionImported) {
|
|
||||||
// Do not display the name change popup
|
|
||||||
disclaimerDialog.doNotShowDisclaimerDialog()
|
|
||||||
}
|
|
||||||
|
|
||||||
ProcessLifecycleOwner.get().lifecycle.addObserver(object : DefaultLifecycleObserver {
|
ProcessLifecycleOwner.get().lifecycle.addObserver(object : DefaultLifecycleObserver {
|
||||||
override fun onResume(owner: LifecycleOwner) {
|
override fun onResume(owner: LifecycleOwner) {
|
||||||
Timber.i("App entered foreground")
|
Timber.i("App entered foreground")
|
||||||
|
|
|
@ -73,7 +73,6 @@ import org.matrix.android.sdk.api.MatrixConfiguration
|
||||||
import org.matrix.android.sdk.api.SyncConfig
|
import org.matrix.android.sdk.api.SyncConfig
|
||||||
import org.matrix.android.sdk.api.auth.AuthenticationService
|
import org.matrix.android.sdk.api.auth.AuthenticationService
|
||||||
import org.matrix.android.sdk.api.auth.HomeServerHistoryService
|
import org.matrix.android.sdk.api.auth.HomeServerHistoryService
|
||||||
import org.matrix.android.sdk.api.legacy.LegacySessionImporter
|
|
||||||
import org.matrix.android.sdk.api.raw.RawService
|
import org.matrix.android.sdk.api.raw.RawService
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.api.session.sync.filter.SyncFilterParams
|
import org.matrix.android.sdk.api.session.sync.filter.SyncFilterParams
|
||||||
|
@ -176,11 +175,6 @@ import javax.inject.Singleton
|
||||||
return activeSessionHolder.getActiveSession()
|
return activeSessionHolder.getActiveSession()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun providesLegacySessionImporter(matrix: Matrix): LegacySessionImporter {
|
|
||||||
return matrix.legacySessionImporter()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
fun providesAuthenticationService(matrix: Matrix): AuthenticationService {
|
fun providesAuthenticationService(matrix: Matrix): AuthenticationService {
|
||||||
return matrix.authenticationService()
|
return matrix.authenticationService()
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2019 New Vector Ltd
|
|
||||||
*
|
|
||||||
* 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 im.vector.app.features.disclaimer
|
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.SharedPreferences
|
|
||||||
import androidx.core.content.edit
|
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|
||||||
import im.vector.app.R
|
|
||||||
import im.vector.app.core.di.DefaultPreferences
|
|
||||||
import im.vector.app.core.utils.openUrlInChromeCustomTab
|
|
||||||
import im.vector.app.features.settings.VectorSettingsUrls
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
// Increase this value to show again the disclaimer dialog after an upgrade of the application
|
|
||||||
private const val CURRENT_DISCLAIMER_VALUE = 2
|
|
||||||
|
|
||||||
const val SHARED_PREF_KEY = "LAST_DISCLAIMER_VERSION_VALUE"
|
|
||||||
|
|
||||||
class DisclaimerDialog @Inject constructor(
|
|
||||||
@DefaultPreferences
|
|
||||||
private val sharedPrefs: SharedPreferences,
|
|
||||||
) {
|
|
||||||
fun showDisclaimerDialog(activity: Activity) {
|
|
||||||
if (sharedPrefs.getInt(SHARED_PREF_KEY, 0) < CURRENT_DISCLAIMER_VALUE) {
|
|
||||||
sharedPrefs.edit {
|
|
||||||
putInt(SHARED_PREF_KEY, CURRENT_DISCLAIMER_VALUE)
|
|
||||||
}
|
|
||||||
|
|
||||||
val dialogLayout = activity.layoutInflater.inflate(R.layout.dialog_disclaimer_content, null)
|
|
||||||
|
|
||||||
MaterialAlertDialogBuilder(activity)
|
|
||||||
.setView(dialogLayout)
|
|
||||||
.setCancelable(false)
|
|
||||||
.setNegativeButton(R.string.disclaimer_negative_button, null)
|
|
||||||
.setPositiveButton(R.string.disclaimer_positive_button) { _, _ ->
|
|
||||||
openUrlInChromeCustomTab(activity, null, VectorSettingsUrls.DISCLAIMER_URL)
|
|
||||||
}
|
|
||||||
.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun doNotShowDisclaimerDialog() {
|
|
||||||
sharedPrefs.edit {
|
|
||||||
putInt(SHARED_PREF_KEY, CURRENT_DISCLAIMER_VALUE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -56,7 +56,6 @@ import im.vector.app.features.analytics.accountdata.AnalyticsAccountDataViewMode
|
||||||
import im.vector.app.features.analytics.plan.MobileScreen
|
import im.vector.app.features.analytics.plan.MobileScreen
|
||||||
import im.vector.app.features.analytics.plan.ViewRoom
|
import im.vector.app.features.analytics.plan.ViewRoom
|
||||||
import im.vector.app.features.crypto.recover.SetupMode
|
import im.vector.app.features.crypto.recover.SetupMode
|
||||||
import im.vector.app.features.disclaimer.DisclaimerDialog
|
|
||||||
import im.vector.app.features.home.room.list.actions.RoomListSharedAction
|
import im.vector.app.features.home.room.list.actions.RoomListSharedAction
|
||||||
import im.vector.app.features.home.room.list.actions.RoomListSharedActionViewModel
|
import im.vector.app.features.home.room.list.actions.RoomListSharedActionViewModel
|
||||||
import im.vector.app.features.home.room.list.home.layout.HomeLayoutSettingBottomDialogFragment
|
import im.vector.app.features.home.room.list.home.layout.HomeLayoutSettingBottomDialogFragment
|
||||||
|
@ -140,7 +139,6 @@ class HomeActivity :
|
||||||
@Inject lateinit var spaceStateHandler: SpaceStateHandler
|
@Inject lateinit var spaceStateHandler: SpaceStateHandler
|
||||||
@Inject lateinit var unifiedPushHelper: UnifiedPushHelper
|
@Inject lateinit var unifiedPushHelper: UnifiedPushHelper
|
||||||
@Inject lateinit var nightlyProxy: NightlyProxy
|
@Inject lateinit var nightlyProxy: NightlyProxy
|
||||||
@Inject lateinit var disclaimerDialog: DisclaimerDialog
|
|
||||||
@Inject lateinit var notificationPermissionManager: NotificationPermissionManager
|
@Inject lateinit var notificationPermissionManager: NotificationPermissionManager
|
||||||
|
|
||||||
private var isNewAppLayoutEnabled: Boolean = false // delete once old app layout is removed
|
private var isNewAppLayoutEnabled: Boolean = false // delete once old app layout is removed
|
||||||
|
@ -588,8 +586,6 @@ class HomeActivity :
|
||||||
.setPositiveButton(R.string.yes) { _, _ -> bugReporter.openBugReportScreen(this) }
|
.setPositiveButton(R.string.yes) { _, _ -> bugReporter.openBugReportScreen(this) }
|
||||||
.setNegativeButton(R.string.no) { _, _ -> bugReporter.deleteCrashFile() }
|
.setNegativeButton(R.string.no) { _, _ -> bugReporter.deleteCrashFile() }
|
||||||
.show()
|
.show()
|
||||||
} else {
|
|
||||||
disclaimerDialog.showDisclaimerDialog(this)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Force remote backup state update to update the banner if needed
|
// Force remote backup state update to update the banner if needed
|
||||||
|
|
|
@ -28,7 +28,6 @@ import im.vector.app.core.di.DefaultPreferences
|
||||||
import im.vector.app.core.resources.BuildMeta
|
import im.vector.app.core.resources.BuildMeta
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
import im.vector.app.features.VectorFeatures
|
import im.vector.app.features.VectorFeatures
|
||||||
import im.vector.app.features.disclaimer.SHARED_PREF_KEY
|
|
||||||
import im.vector.app.features.home.ShortcutsHandler
|
import im.vector.app.features.home.ShortcutsHandler
|
||||||
import im.vector.app.features.homeserver.ServerUrlsRepository
|
import im.vector.app.features.homeserver.ServerUrlsRepository
|
||||||
import im.vector.app.features.themes.ThemeUtils
|
import im.vector.app.features.themes.ThemeUtils
|
||||||
|
@ -334,9 +333,6 @@ class VectorPreferences @Inject constructor(
|
||||||
// theme
|
// theme
|
||||||
keysToKeep.add(ThemeUtils.APPLICATION_THEME_KEY)
|
keysToKeep.add(ThemeUtils.APPLICATION_THEME_KEY)
|
||||||
|
|
||||||
// Disclaimer dialog
|
|
||||||
keysToKeep.add(SHARED_PREF_KEY)
|
|
||||||
|
|
||||||
// get all the existing keys
|
// get all the existing keys
|
||||||
val keys = defaultPrefs.all.keys
|
val keys = defaultPrefs.all.keys
|
||||||
|
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="50dp"
|
|
||||||
android:height="61dp"
|
|
||||||
android:viewportWidth="50"
|
|
||||||
android:viewportHeight="61">
|
|
||||||
<path
|
|
||||||
android:pathData="M18.3955,17.8083V26.3699L27.1656,26.3609C27.277,26.3609 27.3786,26.3579 27.4797,26.3515C29.7857,26.2008 31.5882,24.3266 31.5882,22.0849C31.5882,19.7263 29.6086,17.8083 27.1744,17.8083H18.3955ZM9.7219,60.0954C4.9319,60.0954 1.0483,56.3331 1.0483,51.6915V35.6749C1.017,35.3844 1,35.0891 1,34.7902C0.9995,34.4859 1.0159,34.1855 1.0483,33.8891V9.4044C1.0483,4.7629 4.9319,1 9.7219,1H27.1744C39.1737,1 48.9359,10.4586 48.9359,22.0849C48.9359,33.1388 40.0252,42.3786 28.6499,43.1205C28.1664,43.1529 27.6681,43.1693 27.1744,43.1693L18.3955,43.1777V51.6915C18.3955,56.3331 14.5124,60.0954 9.7219,60.0954Z"
|
|
||||||
android:fillColor="#A2DDEF"
|
|
||||||
android:fillType="evenOdd"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M18.3954,17.8083V26.3699L27.1655,26.3609C27.2768,26.3609 27.3785,26.3579 27.4796,26.3515C29.7855,26.2008 31.588,24.3266 31.588,22.0849C31.588,19.7263 29.6085,17.8083 27.1742,17.8083H18.3954ZM9.7217,60.0954C4.9317,60.0954 1.0481,56.3331 1.0481,51.6915V9.4044C1.0481,4.7629 4.9317,1 9.7217,1H27.1742C39.1736,1 48.9358,10.4586 48.9358,22.0849C48.9358,33.1388 40.025,42.3786 28.6497,43.1205C28.1663,43.1529 27.6679,43.1693 27.1742,43.1693L18.3954,43.1777V51.6915C18.3954,56.3331 14.5122,60.0954 9.7217,60.0954Z"
|
|
||||||
android:strokeWidth="1.51616"
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:fillType="evenOdd"
|
|
||||||
android:strokeColor="#368BD6"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M9.7219,51.6914V9.4043H27.1744C34.4022,9.4043 40.2618,15.0817 40.2618,22.0848C40.2618,28.7975 34.8785,34.2918 28.0674,34.7359C27.7718,34.7553 27.4746,34.7652 27.1744,34.7652C20.3726,34.7718 15.2712,34.7768 11.8703,34.78C11.3929,34.7805 10.6767,34.7812 9.7219,34.7821"
|
|
||||||
android:strokeWidth="1.51616"
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:strokeColor="#368BD6"
|
|
||||||
android:strokeLineCap="round"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M16.8692,4.5845C18.1989,6.4229 18.7096,8.6537 18.3072,10.8631C17.9044,13.074 16.6367,14.9999 14.7377,16.2873C10.8171,18.9453 5.3938,18.0198 2.6485,14.2242C1.3187,12.3857 0.8081,10.1555 1.211,7.9451C1.6133,5.7347 2.881,3.8083 4.7805,2.5213C8.7011,-0.1366 14.1239,0.7888 16.8692,4.5845ZM40.3333,60.0907C37.5998,60.0907 34.9105,58.8425 33.2225,56.5088L20.9639,39.5588C18.215,35.7576 19.1671,30.5169 23.0897,27.854C27.0123,25.1891 32.4213,26.112 35.1702,29.9132L47.4287,46.8632C50.1781,50.6644 49.2261,55.9051 45.3034,58.568C43.7884,59.5969 42.0521,60.0907 40.3333,60.0907Z"
|
|
||||||
android:fillColor="#368BD6"
|
|
||||||
android:fillType="evenOdd"/>
|
|
||||||
</vector>
|
|
|
@ -1,69 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/disclaimerIconsLayout"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:padding="32dp"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:importantForAccessibility="no"
|
|
||||||
android:src="@drawable/ic_riot_icon" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="32dp"
|
|
||||||
android:importantForAccessibility="no"
|
|
||||||
android:src="@drawable/ic_arrow_right"
|
|
||||||
app:tint="?vctr_content_secondary"
|
|
||||||
tools:ignore="MissingPrefix" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:importantForAccessibility="no"
|
|
||||||
android:src="@drawable/element_logo_green" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/disclaimerTextView"
|
|
||||||
style="@style/Widget.Vector.TextView.Title"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/disclaimer_title"
|
|
||||||
android:textColor="?vctr_content_primary"
|
|
||||||
android:textStyle="bold"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/disclaimerIconsLayout" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
style="@style/Widget.Vector.TextView.Subtitle"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="24dp"
|
|
||||||
android:layout_marginTop="32dp"
|
|
||||||
android:layout_marginEnd="24dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingBottom="32dp"
|
|
||||||
android:text="@string/disclaimer_content"
|
|
||||||
android:textColor="?vctr_content_secondary"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/disclaimerTextView" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
Loading…
Reference in New Issue