Skip to content

Commit 8aeb580

Browse files
@W-20161958: [MSDK 13.1][Android] Cannot login GUS using Welcome endpoint (loginViewModel_applyPendingLoginServer Tests)
1 parent fd1c55a commit 8aeb580

4 files changed

Lines changed: 244 additions & 123 deletions

File tree

libs/SalesforceSDK/src/com/salesforce/androidsdk/ui/LoginActivity.kt

Lines changed: 6 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,6 @@ import com.salesforce.androidsdk.util.UriFragmentParser
148148
import kotlinx.coroutines.CoroutineScope
149149
import kotlinx.coroutines.Dispatchers.Default
150150
import kotlinx.coroutines.Dispatchers.IO
151-
import kotlinx.coroutines.Job
152151
import kotlinx.coroutines.launch
153152
import org.json.JSONObject
154153
import java.lang.String.format
@@ -185,6 +184,7 @@ open class LoginActivity : FragmentActivity() {
185184
// Webview and Clients
186185
@VisibleForTesting(otherwise = PROTECTED)
187186
open val webViewClient = AuthWebViewClient()
187+
188188
@VisibleForTesting(otherwise = PROTECTED)
189189
open val webChromeClient = WebChromeClient()
190190
open val webView: WebView by lazy {
@@ -337,7 +337,7 @@ open class LoginActivity : FragmentActivity() {
337337
// Store the new intent and apply it to the activity.
338338
setIntent(intent)
339339
applyIntent()
340-
viewModel.pendingServer.value?.let { applyPendingServer(it) }
340+
viewModel.applyPendingServer(pendingLoginServer = viewModel.pendingServer.value)
341341
}
342342

343343
private fun clearWebView(showServerPicker: Boolean = true) {
@@ -905,13 +905,6 @@ open class LoginActivity : FragmentActivity() {
905905
// endregion
906906
// region Salesforce Welcome Login Private Implementation
907907

908-
/** The Kotlin Coroutine Job fetching the pending login server's authentication configuration */
909-
private var authenticationConfigurationFetchJob: Job? = null
910-
911-
/** The previously observed pending login server for use in switching between default and Salesforce Welcome Discovery log in */
912-
@VisibleForTesting
913-
internal var previousPendingLoginServer: String? = null
914-
915908
/**
916909
* If the intent is for Salesforce Welcome Discovery, apply it to the activity.
917910
* @param intent The intent
@@ -971,20 +964,6 @@ open class LoginActivity : FragmentActivity() {
971964
)
972965
.build()
973966

974-
/**
975-
* Determines if the provided pending login server URL is a switch from
976-
* Salesforce Welcome Discovery back to default log in.
977-
* @param pendingLoginServerUri The pending login server URL
978-
* @return Boolean true if the provided pending login server URL is a
979-
* switch from Salesforce Welcome Discovery back to the default log in,
980-
* false otherwise.
981-
* */
982-
private fun isSwitchFromSalesforceWelcomeDiscoveryToDefaultLogin(
983-
pendingLoginServerUri: Uri
984-
) = previousPendingLoginServer?.toUri()?.let { previousPendingLoginServerUri ->
985-
isSalesforceWelcomeDiscoveryUrlPath(previousPendingLoginServerUri) && !(isSalesforceWelcomeDiscoveryMobileUrl(this, pendingLoginServerUri))
986-
} ?: false
987-
988967
/**
989968
* Switches between default or Salesforce Welcome Discovery log in as needed
990969
* using the provided pending login server URL.
@@ -1011,7 +990,7 @@ open class LoginActivity : FragmentActivity() {
1011990
}
1012991

1013992
// If the pending login server isn't a Salesforce Welcome Discovery URL but the previous was...
1014-
else if (isSwitchFromSalesforceWelcomeDiscoveryToDefaultLogin(pendingLoginServerUri)) {
993+
else if (viewModel.isSwitchFromSalesforceWelcomeDiscoveryToDefaultLogin(pendingLoginServerUri)) {
1015994

1016995
// Navigate to default login.
1017996
startActivity(
@@ -1087,33 +1066,6 @@ open class LoginActivity : FragmentActivity() {
10871066
applyUiBridgeApiFrontDoorUrl(intent)
10881067
}
10891068

1090-
/**
1091-
* Applies a new pending login server. The decision to authenticate in a
1092-
* web browser-custom tab will be made, which may require fetching the
1093-
* authentication configuration. The selected server and login URL (OAuth
1094-
* authorization URL) will set to continue the flow.
1095-
*/
1096-
@VisibleForTesting
1097-
internal fun applyPendingServer(pendingLoginServer: String) {
1098-
val sdkManager = SalesforceSDKManager.getInstance()
1099-
1100-
// Recall this pending login server for reference by future updates.
1101-
previousPendingLoginServer = pendingLoginServer
1102-
1103-
// When authorization via a single-server, custom tab activity is requested skip fetching the authorization configuration and immediately set the selected login server to generate the OAuth authorization URL.
1104-
if (viewModel.singleServerCustomTabActivity) {
1105-
viewModel.selectedServer.postValue(pendingLoginServer)
1106-
}
1107-
// Fetch the pending login server's authentication configuration to set the selected login server and OAuth authorization URL.
1108-
else {
1109-
authenticationConfigurationFetchJob?.cancel()
1110-
authenticationConfigurationFetchJob = sdkManager.fetchAuthenticationConfiguration {
1111-
viewModel.selectedServer.postValue(pendingLoginServer)
1112-
authenticationConfigurationFetchJob = null
1113-
}
1114-
}
1115-
}
1116-
11171069
/**
11181070
* Starts a browser custom tab for the OAuth authorization URL according to
11191071
* the authentication configuration. The activity only takes action when
@@ -1636,17 +1588,17 @@ open class LoginActivity : FragmentActivity() {
16361588
// Guard against observing a pending login server already provided by the intent data, such as a Salesforce Welcome Discovery mobile URL.
16371589
val pendingServerUri = value.toUri()
16381590
if (activity.intent.data?.host == pendingServerUri.host) {
1639-
activity.previousPendingLoginServer = value
1591+
activity.viewModel.previousPendingLoginServer = value
16401592
return
16411593
}
16421594

16431595
// Use the URL to switch between default or Salesforce Welcome Discovery log in, if applicable.
16441596
if (activity.switchDefaultOrSalesforceWelcomeDiscoveryLogin(pendingServerUri)) {
1645-
activity.previousPendingLoginServer = value
1597+
activity.viewModel.previousPendingLoginServer = value
16461598
return
16471599
}
16481600

1649-
activity.applyPendingServer(value)
1601+
activity.viewModel.applyPendingServer(pendingLoginServer = value)
16501602
}
16511603
}
16521604

libs/SalesforceSDK/src/com/salesforce/androidsdk/ui/LoginViewModel.kt

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
package com.salesforce.androidsdk.ui
2828

2929
import android.annotation.SuppressLint
30+
import android.net.Uri
3031
import android.webkit.CookieManager
3132
import android.webkit.URLUtil
3233
import android.webkit.WebView
@@ -39,6 +40,7 @@ import androidx.compose.ui.graphics.Color
3940
import androidx.compose.ui.graphics.Color.Companion.Black
4041
import androidx.compose.ui.graphics.Color.Companion.White
4142
import androidx.compose.ui.graphics.luminance
43+
import androidx.core.net.toUri
4244
import androidx.lifecycle.MediatorLiveData
4345
import androidx.lifecycle.ViewModel
4446
import androidx.lifecycle.ViewModelProvider
@@ -63,9 +65,12 @@ import com.salesforce.androidsdk.config.OAuthConfig
6365
import com.salesforce.androidsdk.security.SalesforceKeyGenerator.getRandom128ByteKey
6466
import com.salesforce.androidsdk.security.SalesforceKeyGenerator.getSHA256Hash
6567
import com.salesforce.androidsdk.ui.LoginActivity.Companion.ABOUT_BLANK
68+
import com.salesforce.androidsdk.ui.LoginActivity.Companion.isSalesforceWelcomeDiscoveryMobileUrl
69+
import com.salesforce.androidsdk.ui.LoginActivity.Companion.isSalesforceWelcomeDiscoveryUrlPath
6670
import com.salesforce.androidsdk.util.SalesforceSDKLogger.e
6771
import kotlinx.coroutines.CoroutineScope
6872
import kotlinx.coroutines.Dispatchers.IO
73+
import kotlinx.coroutines.Job
6974
import kotlinx.coroutines.launch
7075
import kotlinx.coroutines.withContext
7176
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
@@ -122,8 +127,18 @@ open class LoginViewModel(val bootConfig: BootConfig) : ViewModel() {
122127
var loading = mutableStateOf(false)
123128

124129
// Internal LiveData
130+
131+
/** The Kotlin Coroutine Job fetching the pending login server's authentication configuration */
132+
@VisibleForTesting
133+
internal var authenticationConfigurationFetchJob: Job? = null
134+
125135
/** The login server that is pending authentication configuration before becoming the selected login server */
126136
internal val pendingServer = MediatorLiveData<String>()
137+
138+
/** The previously observed pending login server for use in switching between default and Salesforce Welcome Discovery log in */
139+
@VisibleForTesting
140+
internal var previousPendingLoginServer: String? = null
141+
127142
internal val authFinished = mutableStateOf(false)
128143
internal val isIDPLoginFlowEnabled = derivedStateOf {
129144
SalesforceSDKManager.getInstance().isIDPLoginFlowEnabled
@@ -312,6 +327,40 @@ open class LoginViewModel(val bootConfig: BootConfig) : ViewModel() {
312327
instanceServer: String?,
313328
) = defaultBuildAccountName(username, instanceServer)
314329

330+
/**
331+
* Applies a new pending login server. The decision to authenticate in a
332+
* web browser-custom tab will be made, which may require fetching the
333+
* authentication configuration. The selected server and login URL (OAuth
334+
* authorization URL) will set to continue the flow.
335+
* @param sdkManager The Salesforce SDK manager. This parameter is intended
336+
* for testing purposes only. Defaults to the shared instance.
337+
* @param pendingLoginServer The new pending login server value
338+
*/
339+
internal fun applyPendingServer(
340+
sdkManager: SalesforceSDKManager = SalesforceSDKManager.getInstance(),
341+
pendingLoginServer: String?
342+
) {
343+
if (pendingLoginServer == null) {
344+
return
345+
}
346+
347+
// Recall this pending login server for reference by future updates.
348+
previousPendingLoginServer = pendingLoginServer
349+
350+
// When authorization via a single-server, custom tab activity is requested skip fetching the authorization configuration and immediately set the selected login server to generate the OAuth authorization URL.
351+
if (singleServerCustomTabActivity) {
352+
selectedServer.postValue(pendingLoginServer)
353+
}
354+
// Fetch the pending login server's authentication configuration to set the selected login server and OAuth authorization URL.
355+
else {
356+
authenticationConfigurationFetchJob?.cancel()
357+
authenticationConfigurationFetchJob = sdkManager.fetchAuthenticationConfiguration {
358+
selectedServer.postValue(pendingLoginServer)
359+
authenticationConfigurationFetchJob = null
360+
}
361+
}
362+
}
363+
315364
/**
316365
* Called when the webview portion of the Web Server flow is finished. Code exchange
317366
* passes the result to [onAuthFlowComplete] on success, which handles user creation.
@@ -453,6 +502,24 @@ open class LoginViewModel(val bootConfig: BootConfig) : ViewModel() {
453502
}
454503
}
455504

505+
// region Salesforce Welcome Discovery
506+
507+
/**
508+
* Determines if the provided pending login server URL is a switch from
509+
* Salesforce Welcome Discovery back to default log in.
510+
* @param pendingLoginServerUri The pending login server URL
511+
* @return Boolean true if the provided pending login server URL is a
512+
* switch from Salesforce Welcome Discovery back to the default log in,
513+
* false otherwise.
514+
* */
515+
internal fun isSwitchFromSalesforceWelcomeDiscoveryToDefaultLogin(
516+
pendingLoginServerUri: Uri
517+
) = previousPendingLoginServer?.toUri()?.let { previousPendingLoginServerUri ->
518+
isSalesforceWelcomeDiscoveryUrlPath(previousPendingLoginServerUri) && !(isSalesforceWelcomeDiscoveryMobileUrl(pendingLoginServerUri))
519+
} ?: false
520+
521+
// endregion
522+
456523
companion object {
457524

458525
val Factory: ViewModelProvider.Factory = object : ViewModelProvider.Factory {

0 commit comments

Comments
 (0)