From a807c29540e7264ea2a5457c8a807ddf8c950a1a Mon Sep 17 00:00:00 2001 From: Julian Raufelder Date: Sun, 24 Oct 2021 21:18:48 +0200 Subject: [PATCH] Fix sometimes unable to add a pCloud connection which fixes #368 Problem occurs due to a race condition between onNewIntent and onActivityResult: If the browser is closed and Cryptomator resumed before the redirection call is processed by the intent framework of Android which in return calls the AuthenticatePCloudActivity again in the onNewIntent, it finishes in onActivityResult but should wait until onNewIntent is called to process the OAuth result. --- .../ui/activity/AuthenticatePCloudActivity.kt | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/presentation/src/main/java/org/cryptomator/presentation/ui/activity/AuthenticatePCloudActivity.kt b/presentation/src/main/java/org/cryptomator/presentation/ui/activity/AuthenticatePCloudActivity.kt index 0ec79514..59b610ee 100644 --- a/presentation/src/main/java/org/cryptomator/presentation/ui/activity/AuthenticatePCloudActivity.kt +++ b/presentation/src/main/java/org/cryptomator/presentation/ui/activity/AuthenticatePCloudActivity.kt @@ -2,6 +2,7 @@ package org.cryptomator.presentation.ui.activity import android.content.Intent import android.net.Uri +import android.os.Handler import android.widget.Toast import org.cryptomator.generator.Activity import org.cryptomator.presentation.BuildConfig @@ -13,6 +14,12 @@ import timber.log.Timber @Activity class AuthenticatePCloudActivity : BaseActivity() { + private val startAuthenticationRequestCode = 1232 + private val redirectTimeoutAfterAuthenticationAndResumed = 1000L + + private var cancelAuthenticationHandler: Handler = Handler() + private var oAuthResultReceived = false + override fun setupView() { val uri = Uri.parse("https://my.pcloud.com/oauth2/authorize") .buildUpon() @@ -21,18 +28,27 @@ class AuthenticatePCloudActivity : BaseActivity() { .appendQueryParameter("redirect_uri", "pcloudoauth://redirect") .build() - startActivityForResult(Intent(Intent.ACTION_VIEW, uri), 25) + startActivityForResult(Intent(Intent.ACTION_VIEW, uri), startAuthenticationRequestCode) } override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) { super.onActivityResult(requestCode, resultCode, intent) - finish() + if (requestCode == startAuthenticationRequestCode) { + cancelAuthenticationHandler.postDelayed({ + if (!oAuthResultReceived) { + Timber.tag("AuthenticatePCloudActivity").i("Authentication canceled or no redirect received after resuming Cryptomator since 1.5s") + Toast.makeText(context(), R.string.error_authentication_failed, Toast.LENGTH_SHORT).show() + finish() + } + }, redirectTimeoutAfterAuthenticationAndResumed) + } } override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) intent.data?.let { - if(it.host == "redirect" && it.scheme == "pcloudoauth") { + if (it.host == "redirect" && it.scheme == "pcloudoauth") { + oAuthResultReceived = true val parameters = parseUrlFragmentParameters(it) val accessToken = parameters["access_token"] val hostname = parameters["hostname"] @@ -41,10 +57,11 @@ class AuthenticatePCloudActivity : BaseActivity() { result.putExtra(CloudConnectionListPresenter.PCLOUD_OAUTH_AUTH_CODE, accessToken) result.putExtra(CloudConnectionListPresenter.PCLOUD_HOSTNAME, hostname) setResult(android.app.Activity.RESULT_OK, result) - finish() } else { Toast.makeText(this, R.string.error_authentication_failed, Toast.LENGTH_LONG).show() + Timber.tag("AuthenticatePCloudActivity").i("Authentication failed as the access token or hostname is null") } + finish() } else { Timber.tag("AuthenticatePCloudActivity").e("Tried to call activity using a different redirect scheme") } @@ -63,4 +80,9 @@ class AuthenticatePCloudActivity : BaseActivity() { } return emptyMap() } + + override fun onDestroy() { + super.onDestroy() + cancelAuthenticationHandler.removeCallbacksAndMessages(null) + } }