mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-26 19:36:08 +03:00
Merge pull request #92 from vector-im/feature/user-agent
User agent and log of request in debug mode
This commit is contained in:
commit
289c820b48
12 changed files with 449 additions and 8 deletions
|
@ -23,7 +23,7 @@ import com.facebook.stetho.Stetho
|
||||||
import com.github.piasy.biv.BigImageViewer
|
import com.github.piasy.biv.BigImageViewer
|
||||||
import com.github.piasy.biv.loader.glide.GlideImageLoader
|
import com.github.piasy.biv.loader.glide.GlideImageLoader
|
||||||
import com.jakewharton.threetenabp.AndroidThreeTen
|
import com.jakewharton.threetenabp.AndroidThreeTen
|
||||||
import im.vector.matrix.android.BuildConfig
|
import im.vector.matrix.android.api.Matrix
|
||||||
import im.vector.riotredesign.core.di.AppModule
|
import im.vector.riotredesign.core.di.AppModule
|
||||||
import im.vector.riotredesign.features.home.HomeModule
|
import im.vector.riotredesign.features.home.HomeModule
|
||||||
import org.koin.log.EmptyLogger
|
import org.koin.log.EmptyLogger
|
||||||
|
@ -44,6 +44,8 @@ class Riot : Application() {
|
||||||
val appModule = AppModule(applicationContext).definition
|
val appModule = AppModule(applicationContext).definition
|
||||||
val homeModule = HomeModule().definition
|
val homeModule = HomeModule().definition
|
||||||
startKoin(listOf(appModule, homeModule), logger = EmptyLogger())
|
startKoin(listOf(appModule, homeModule), logger = EmptyLogger())
|
||||||
|
|
||||||
|
Matrix.getInstance().setApplicationFlavor(BuildConfig.FLAVOR_DESCRIPTION)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun attachBaseContext(base: Context) {
|
override fun attachBaseContext(base: Context) {
|
||||||
|
|
|
@ -30,10 +30,25 @@ android {
|
||||||
versionName "1.0"
|
versionName "1.0"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
||||||
|
resValue "string", "git_sdk_revision", "\"${gitRevision()}\""
|
||||||
|
resValue "string", "git_sdk_revision_unix_date", "\"${gitRevisionUnixDate()}\""
|
||||||
|
resValue "string", "git_sdk_revision_date", "\"${gitRevisionDate()}\""
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
|
|
||||||
|
debug {
|
||||||
|
// Set to true to log privacy or sensible data, such as token
|
||||||
|
buildConfigField "boolean", "LOG_PRIVATE_DATA", "false"
|
||||||
|
|
||||||
|
// Set to BODY instead of NONE to enable logging
|
||||||
|
buildConfigField "okhttp3.logging.HttpLoggingInterceptor.Level", "OKHTTP_LOGGING_LEVEL", "okhttp3.logging.HttpLoggingInterceptor.Level.NONE"
|
||||||
|
}
|
||||||
|
|
||||||
release {
|
release {
|
||||||
|
buildConfigField "boolean", "LOG_PRIVATE_DATA", "false"
|
||||||
|
buildConfigField "okhttp3.logging.HttpLoggingInterceptor.Level", "OKHTTP_LOGGING_LEVEL", "okhttp3.logging.HttpLoggingInterceptor.Level.NONE"
|
||||||
|
|
||||||
minifyEnabled false
|
minifyEnabled false
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
|
@ -44,6 +59,21 @@ android {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static def gitRevision() {
|
||||||
|
def cmd = "git rev-parse --short HEAD"
|
||||||
|
return cmd.execute().text.trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
static def gitRevisionUnixDate() {
|
||||||
|
def cmd = "git show -s --format=%ct HEAD^{commit}"
|
||||||
|
return cmd.execute().text.trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
static def gitRevisionDate() {
|
||||||
|
def cmd = "git show -s --format=%ci HEAD^{commit}"
|
||||||
|
return cmd.execute().text.trim()
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
def arrow_version = "0.8.0"
|
def arrow_version = "0.8.0"
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Jeff Gilfelt.
|
||||||
|
* 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.matrix.android.internal.network.interceptors
|
||||||
|
|
||||||
|
import okhttp3.Interceptor
|
||||||
|
import okhttp3.Response
|
||||||
|
import okhttp3.logging.HttpLoggingInterceptor
|
||||||
|
import okio.Buffer
|
||||||
|
import java.io.IOException
|
||||||
|
import java.nio.charset.Charset
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An OkHttp interceptor that logs requests as curl shell commands. They can then
|
||||||
|
* be copied, pasted and executed inside a terminal environment. This might be
|
||||||
|
* useful for troubleshooting client/server API interaction during development,
|
||||||
|
* making it easy to isolate and share requests made by the app. <p> Warning: The
|
||||||
|
* logs generated by this interceptor have the potential to leak sensitive
|
||||||
|
* information. It should only be used in a controlled manner or in a
|
||||||
|
* non-production environment.
|
||||||
|
*/
|
||||||
|
internal class CurlLoggingInterceptor(private val logger: HttpLoggingInterceptor.Logger = HttpLoggingInterceptor.Logger.DEFAULT)
|
||||||
|
: Interceptor {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set any additional curl command options (see 'curl --help').
|
||||||
|
*/
|
||||||
|
var curlOptions: String? = null
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
override fun intercept(chain: Interceptor.Chain): Response {
|
||||||
|
val request = chain.request()
|
||||||
|
|
||||||
|
var compressed = false
|
||||||
|
|
||||||
|
var curlCmd = "curl"
|
||||||
|
if (curlOptions != null) {
|
||||||
|
curlCmd += " " + curlOptions!!
|
||||||
|
}
|
||||||
|
curlCmd += " -X " + request.method()
|
||||||
|
|
||||||
|
val requestBody = request.body()
|
||||||
|
if (requestBody != null) {
|
||||||
|
val buffer = Buffer()
|
||||||
|
requestBody.writeTo(buffer)
|
||||||
|
var charset: Charset? = UTF8
|
||||||
|
val contentType = requestBody.contentType()
|
||||||
|
if (contentType != null) {
|
||||||
|
charset = contentType.charset(UTF8)
|
||||||
|
}
|
||||||
|
// try to keep to a single line and use a subshell to preserve any line breaks
|
||||||
|
curlCmd += " --data $'" + buffer.readString(charset!!).replace("\n", "\\n") + "'"
|
||||||
|
}
|
||||||
|
|
||||||
|
val headers = request.headers()
|
||||||
|
var i = 0
|
||||||
|
val count = headers.size()
|
||||||
|
while (i < count) {
|
||||||
|
val name = headers.name(i)
|
||||||
|
val value = headers.value(i)
|
||||||
|
if ("Accept-Encoding".equals(name, ignoreCase = true) && "gzip".equals(value, ignoreCase = true)) {
|
||||||
|
compressed = true
|
||||||
|
}
|
||||||
|
curlCmd += " -H \"$name: $value\""
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
curlCmd += ((if (compressed) " --compressed " else " ") + "'" + request.url().toString()
|
||||||
|
// Replace localhost for emulator by localhost for shell
|
||||||
|
.replace("://10.0.2.2:8080/".toRegex(), "://127.0.0.1:8080/")
|
||||||
|
+ "'")
|
||||||
|
|
||||||
|
// Add Json formatting
|
||||||
|
curlCmd += " | python -m json.tool"
|
||||||
|
|
||||||
|
logger.log("--- cURL (" + request.url() + ")")
|
||||||
|
logger.log(curlCmd)
|
||||||
|
|
||||||
|
return chain.proceed(request)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val UTF8 = Charset.forName("UTF-8")
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* 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.matrix.android.internal.network.interceptors
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull
|
||||||
|
import im.vector.matrix.android.BuildConfig
|
||||||
|
import okhttp3.logging.HttpLoggingInterceptor
|
||||||
|
import org.json.JSONArray
|
||||||
|
import org.json.JSONException
|
||||||
|
import org.json.JSONObject
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
|
class FormattedJsonHttpLogger : HttpLoggingInterceptor.Logger {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val INDENT_SPACE = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log the message and try to log it again as a JSON formatted string
|
||||||
|
* Note: it can consume a lot of memory but it is only in DEBUG mode
|
||||||
|
*
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
|
@Synchronized
|
||||||
|
override fun log(@NonNull message: String) {
|
||||||
|
// In RELEASE there is no log, but for sure, test again BuildConfig.DEBUG
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
Timber.v(message)
|
||||||
|
|
||||||
|
if (message.startsWith("{")) {
|
||||||
|
// JSON Detected
|
||||||
|
try {
|
||||||
|
val o = JSONObject(message)
|
||||||
|
logJson(o.toString(INDENT_SPACE))
|
||||||
|
} catch (e: JSONException) {
|
||||||
|
// Finally this is not a JSON string...
|
||||||
|
Timber.e(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (message.startsWith("[")) {
|
||||||
|
// JSON Array detected
|
||||||
|
try {
|
||||||
|
val o = JSONArray(message)
|
||||||
|
logJson(o.toString(INDENT_SPACE))
|
||||||
|
} catch (e: JSONException) {
|
||||||
|
// Finally not JSON...
|
||||||
|
Timber.e(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// Else not a json string to log
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun logJson(formattedJson: String) {
|
||||||
|
val arr = formattedJson.split("\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||||
|
for (s in arr) {
|
||||||
|
Timber.v(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ import im.vector.matrix.android.internal.di.MatrixKoinComponent
|
||||||
import im.vector.matrix.android.internal.di.MatrixKoinHolder
|
import im.vector.matrix.android.internal.di.MatrixKoinHolder
|
||||||
import im.vector.matrix.android.internal.di.MatrixModule
|
import im.vector.matrix.android.internal.di.MatrixModule
|
||||||
import im.vector.matrix.android.internal.di.NetworkModule
|
import im.vector.matrix.android.internal.di.NetworkModule
|
||||||
|
import im.vector.matrix.android.internal.network.UserAgentHolder
|
||||||
import im.vector.matrix.android.internal.util.BackgroundDetectionObserver
|
import im.vector.matrix.android.internal.util.BackgroundDetectionObserver
|
||||||
import org.koin.standalone.inject
|
import org.koin.standalone.inject
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
@ -38,6 +39,7 @@ import java.util.concurrent.atomic.AtomicBoolean
|
||||||
class Matrix private constructor(context: Context) : MatrixKoinComponent {
|
class Matrix private constructor(context: Context) : MatrixKoinComponent {
|
||||||
|
|
||||||
private val authenticator by inject<Authenticator>()
|
private val authenticator by inject<Authenticator>()
|
||||||
|
private val userAgent by inject<UserAgentHolder>()
|
||||||
private val backgroundDetectionObserver by inject<BackgroundDetectionObserver>()
|
private val backgroundDetectionObserver by inject<BackgroundDetectionObserver>()
|
||||||
lateinit var currentSession: Session
|
lateinit var currentSession: Session
|
||||||
|
|
||||||
|
@ -59,6 +61,13 @@ class Matrix private constructor(context: Context) : MatrixKoinComponent {
|
||||||
return authenticator
|
return authenticator
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set application flavor, to alter user agent.
|
||||||
|
*/
|
||||||
|
fun setApplicationFlavor(flavor: String) {
|
||||||
|
userAgent.setApplicationFlavor(flavor)
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private lateinit var instance: Matrix
|
private lateinit var instance: Matrix
|
||||||
private val isInit = AtomicBoolean(false)
|
private val isInit = AtomicBoolean(false)
|
||||||
|
|
|
@ -17,33 +17,45 @@
|
||||||
package im.vector.matrix.android.internal.di
|
package im.vector.matrix.android.internal.di
|
||||||
|
|
||||||
import com.facebook.stetho.okhttp3.StethoInterceptor
|
import com.facebook.stetho.okhttp3.StethoInterceptor
|
||||||
import im.vector.matrix.android.internal.network.AccessTokenInterceptor
|
import im.vector.matrix.android.BuildConfig
|
||||||
import im.vector.matrix.android.internal.network.NetworkConnectivityChecker
|
import im.vector.matrix.android.internal.network.*
|
||||||
import im.vector.matrix.android.internal.network.UnitConverterFactory
|
import im.vector.matrix.android.internal.network.interceptors.CurlLoggingInterceptor
|
||||||
|
import im.vector.matrix.android.internal.network.interceptors.FormattedJsonHttpLogger
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.logging.HttpLoggingInterceptor
|
import okhttp3.logging.HttpLoggingInterceptor
|
||||||
import okreplay.OkReplayInterceptor
|
import okreplay.OkReplayInterceptor
|
||||||
import org.koin.dsl.module.module
|
import org.koin.dsl.module.module
|
||||||
import retrofit2.Retrofit
|
import retrofit2.Retrofit
|
||||||
import retrofit2.converter.moshi.MoshiConverterFactory
|
import retrofit2.converter.moshi.MoshiConverterFactory
|
||||||
import timber.log.Timber
|
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
class NetworkModule {
|
class NetworkModule {
|
||||||
|
|
||||||
val definition = module {
|
val definition = module {
|
||||||
|
|
||||||
|
single {
|
||||||
|
UserAgentHolder(get())
|
||||||
|
}
|
||||||
|
|
||||||
|
single {
|
||||||
|
UserAgentInterceptor(get())
|
||||||
|
}
|
||||||
|
|
||||||
single {
|
single {
|
||||||
AccessTokenInterceptor(get())
|
AccessTokenInterceptor(get())
|
||||||
}
|
}
|
||||||
|
|
||||||
single {
|
single {
|
||||||
val logger = HttpLoggingInterceptor.Logger { message -> Timber.v(message) }
|
val logger = FormattedJsonHttpLogger()
|
||||||
val interceptor = HttpLoggingInterceptor(logger)
|
val interceptor = HttpLoggingInterceptor(logger)
|
||||||
interceptor.level = HttpLoggingInterceptor.Level.BASIC
|
interceptor.level = BuildConfig.OKHTTP_LOGGING_LEVEL
|
||||||
interceptor
|
interceptor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
single {
|
||||||
|
CurlLoggingInterceptor()
|
||||||
|
}
|
||||||
|
|
||||||
single {
|
single {
|
||||||
OkReplayInterceptor()
|
OkReplayInterceptor()
|
||||||
}
|
}
|
||||||
|
@ -58,8 +70,14 @@ class NetworkModule {
|
||||||
.readTimeout(30, TimeUnit.SECONDS)
|
.readTimeout(30, TimeUnit.SECONDS)
|
||||||
.writeTimeout(30, TimeUnit.SECONDS)
|
.writeTimeout(30, TimeUnit.SECONDS)
|
||||||
.addNetworkInterceptor(get<StethoInterceptor>())
|
.addNetworkInterceptor(get<StethoInterceptor>())
|
||||||
|
.addInterceptor(get<UserAgentInterceptor>())
|
||||||
.addInterceptor(get<AccessTokenInterceptor>())
|
.addInterceptor(get<AccessTokenInterceptor>())
|
||||||
.addInterceptor(get<HttpLoggingInterceptor>())
|
.addInterceptor(get<HttpLoggingInterceptor>())
|
||||||
|
.apply {
|
||||||
|
if (BuildConfig.LOG_PRIVATE_DATA) {
|
||||||
|
addInterceptor(get<CurlLoggingInterceptor>())
|
||||||
|
}
|
||||||
|
}
|
||||||
.addInterceptor(get<OkReplayInterceptor>())
|
.addInterceptor(get<OkReplayInterceptor>())
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ internal class AccessTokenInterceptor(private val sessionParamsStore: SessionPar
|
||||||
// Add the access token to all requests if it is set
|
// Add the access token to all requests if it is set
|
||||||
val sessionParams = sessionParamsStore.get()
|
val sessionParams = sessionParamsStore.get()
|
||||||
sessionParams?.let {
|
sessionParams?.let {
|
||||||
newRequestBuilder.addHeader("Authorization", "Bearer " + it.credentials.accessToken)
|
newRequestBuilder.addHeader(HttpHeaders.Authorization, "Bearer " + it.credentials.accessToken)
|
||||||
}
|
}
|
||||||
request = newRequestBuilder.build()
|
request = newRequestBuilder.build()
|
||||||
return chain.proceed(request)
|
return chain.proceed(request)
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* 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.matrix.android.internal.network
|
||||||
|
|
||||||
|
object HttpHeaders {
|
||||||
|
|
||||||
|
const val Authorization = "Authorization"
|
||||||
|
const val UserAgent = "User-Agent"
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* 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.matrix.android.internal.network
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.text.TextUtils
|
||||||
|
import im.vector.matrix.android.BuildConfig
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
|
internal class UserAgentHolder(val context: Context) {
|
||||||
|
|
||||||
|
var userAgent: String = ""
|
||||||
|
private set
|
||||||
|
|
||||||
|
init {
|
||||||
|
setApplicationFlavor("NoFlavor")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an user agent with the application version.
|
||||||
|
* Ex: RiotX/1.0.0 (Linux; U; Android 6.0.1; SM-A510F Build/MMB29; Flavour GPlay; MatrixAndroidSDK_X 1.0)
|
||||||
|
*
|
||||||
|
* @param flavorDescription the flavor description
|
||||||
|
*/
|
||||||
|
fun setApplicationFlavor(flavorDescription: String) {
|
||||||
|
var appName = ""
|
||||||
|
var appVersion = ""
|
||||||
|
|
||||||
|
try {
|
||||||
|
val appPackageName = context.applicationContext.packageName
|
||||||
|
val pm = context.packageManager
|
||||||
|
val appInfo = pm.getApplicationInfo(appPackageName, 0)
|
||||||
|
appName = pm.getApplicationLabel(appInfo).toString()
|
||||||
|
|
||||||
|
val pkgInfo = pm.getPackageInfo(context.applicationContext.packageName, 0)
|
||||||
|
appVersion = pkgInfo.versionName
|
||||||
|
|
||||||
|
// Use appPackageName instead of appName if appName contains any non-ASCII character
|
||||||
|
if (!appName.matches("\\A\\p{ASCII}*\\z".toRegex())) {
|
||||||
|
appName = appPackageName
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Timber.e(e, "## initUserAgent() : failed " + e.message)
|
||||||
|
}
|
||||||
|
|
||||||
|
var systemUserAgent = System.getProperty("http.agent")
|
||||||
|
|
||||||
|
// cannot retrieve the application version
|
||||||
|
if (TextUtils.isEmpty(appName) || TextUtils.isEmpty(appVersion)) {
|
||||||
|
if (null == systemUserAgent) {
|
||||||
|
userAgent = "Java" + System.getProperty("java.version")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there is no user agent or cannot parse it
|
||||||
|
if (null == systemUserAgent || systemUserAgent.lastIndexOf(")") == -1 || !systemUserAgent.contains("(")) {
|
||||||
|
userAgent = (appName + "/" + appVersion + " ( Flavour " + flavorDescription
|
||||||
|
+ "; MatrixAndroidSDK_X " + BuildConfig.VERSION_NAME + ")")
|
||||||
|
} else {
|
||||||
|
// update
|
||||||
|
userAgent = appName + "/" + appVersion + " " +
|
||||||
|
systemUserAgent.substring(systemUserAgent.indexOf("("), systemUserAgent.lastIndexOf(")") - 1) +
|
||||||
|
"; Flavour " + flavorDescription +
|
||||||
|
"; MatrixAndroidSDK_X " + BuildConfig.VERSION_NAME + ")"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* 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.matrix.android.internal.network
|
||||||
|
|
||||||
|
import okhttp3.Interceptor
|
||||||
|
import okhttp3.Response
|
||||||
|
|
||||||
|
internal class UserAgentInterceptor(private val userAgentHolder: UserAgentHolder) : Interceptor {
|
||||||
|
|
||||||
|
override fun intercept(chain: Interceptor.Chain): Response {
|
||||||
|
var request = chain.request()
|
||||||
|
val newRequestBuilder = request.newBuilder()
|
||||||
|
// Add the user agent to all requests if it is set
|
||||||
|
userAgentHolder.userAgent
|
||||||
|
.takeIf { it.isNotBlank() }
|
||||||
|
?.let {
|
||||||
|
newRequestBuilder.addHeader(HttpHeaders.UserAgent, it)
|
||||||
|
}
|
||||||
|
request = newRequestBuilder.build()
|
||||||
|
return chain.proceed(request)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Jeff Gilfelt.
|
||||||
|
* 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.matrix.android.internal.network.interceptors
|
||||||
|
|
||||||
|
import okhttp3.Interceptor
|
||||||
|
import okhttp3.Response
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No op interceptor
|
||||||
|
*/
|
||||||
|
internal class CurlLoggingInterceptor : Interceptor {
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
override fun intercept(chain: Interceptor.Chain): Response {
|
||||||
|
return chain.proceed(chain.request())
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* 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.matrix.android.internal.network.interceptors
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull
|
||||||
|
import okhttp3.logging.HttpLoggingInterceptor
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No op logger
|
||||||
|
*/
|
||||||
|
internal class FormattedJsonHttpLogger : HttpLoggingInterceptor.Logger {
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
override fun log(@NonNull message: String) {
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue