Skip to content

Commit

Permalink
updated definition of AppDiscovering and SsoLink interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
lalwani committed Mar 20, 2024
1 parent a741d8a commit a8f9739
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@
package com.uber.sdk2.auth.api

import android.net.Uri
import com.uber.sdk2.auth.api.request.CrossApp

/** Provides a way to discover the app to authenticate the user. */
interface AppDiscovering {
fun interface AppDiscovering {

/**
* Finds the best application to handle a given [Uri].
Expand All @@ -29,8 +30,8 @@ interface AppDiscovering {
* @param uri The [Uri] for which the best application needs to be found. The [Uri] should be
* well-formed and include a scheme (e.g., http, https) that applications can recognize and
* handle.
* @return A set of package names of the best applications to handle the URI. If no suitable
* application is found, it returns an empty set.
* @return The package name of the best application to handle the given [Uri], or `null` if no app
* is found.
*/
fun findAppForSso(uri: Uri): Set<String>
fun findAppForSso(uri: Uri, appPriority: List<CrossApp>): String?
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ interface SsoLink {
/** Executes the SSO link with the given optional query parameters. */
suspend fun execute(optionalQueryParams: Map<String, String>): String

/** Handles the authentication code received from the SSO flow via deeplink. */
fun handleAuthCode(authCode: String)
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,14 @@ import android.content.Context
import android.content.Intent
import android.net.Uri
import com.uber.sdk2.auth.api.AppDiscovering
import com.uber.sdk2.auth.api.request.CrossApp

/**
* Default implementation of [AppDiscovering]. This implementation uses the [PackageManager] to find
* the best app to handle the given [Uri].
*/
class AppDiscovery(val context: Context) : AppDiscovering {
override fun findAppForSso(uri: Uri): Set<String> {
override fun findAppForSso(uri: Uri, appPriority: List<CrossApp>): String? {
val intent = Intent(Intent.ACTION_VIEW, uri)

// Use PackageManager to find activities that can handle the Intent
Expand All @@ -31,6 +36,15 @@ class AppDiscovery(val context: Context) : AppDiscovering {
// Extract the package names from the ResolveInfo objects and return them
val packageNames = appsList.map { resolveInfo -> resolveInfo.activityInfo.packageName }

return packageNames.toSet()
appPriority.forEach { app ->
// Iterate through all package names associated with the current app
app.packages.forEach { packageName ->
if (packageNames.contains(packageName)) {
// If a match is found, return the matching package name
return packageName
}
}
}
return null
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import com.uber.sdk2.auth.api.AppDiscovering
import com.uber.sdk2.auth.api.exception.AuthException
import com.uber.sdk2.auth.api.request.AuthContext
import com.uber.sdk2.auth.api.request.AuthDestination
import com.uber.sdk2.auth.api.request.CrossApp
import com.uber.sdk2.auth.api.request.SsoConfig
import com.uber.sdk2.auth.api.sso.CustomTabsLauncher
import com.uber.sdk2.auth.api.sso.SsoLink
Expand Down Expand Up @@ -74,10 +73,10 @@ internal class UniversalSsoLink(
uri.buildUpon().appendQueryParameter(entry.key, entry.value).build()
}
withContext(Dispatchers.Main) {
val packageNames = appDiscovering.findAppForSso(uri)
when (authContext.authDestination) {
is AuthDestination.CrossAppSso -> {
val packageName = findBestPackage(authContext.authDestination.appPriority, packageNames)
val packageName =
appDiscovering.findAppForSso(uri, authContext.authDestination.appPriority)
packageName?.let {
val intent = Intent()
intent.`package` = packageName
Expand Down Expand Up @@ -119,19 +118,6 @@ internal class UniversalSsoLink(
}
}

private fun findBestPackage(appPriority: List<CrossApp>, packageNames: Set<String>): String? {
appPriority.forEach { app ->
// Iterate through all package names associated with the current app
app.packages.forEach { packageName ->
if (packageNames.contains(packageName)) {
// If a match is found, return the matching package name
return packageName
}
}
}
return null
}

private fun loadCustomtab(uri: Uri) {
customTabsLauncher.launch(uri)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import com.uber.sdk2.auth.api.request.PrefillInfo
import com.uber.sdk2.auth.api.request.SsoConfig
import com.uber.sdk2.auth.api.sso.CustomTabsLauncher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
Expand Down Expand Up @@ -72,10 +73,11 @@ class UniversalSsoLinkTest : RobolectricTestBase() {

private val testDispatcher = StandardTestDispatcher()

@OptIn(ExperimentalCoroutinesApi::class)
@Before
fun setup() {
Dispatchers.setMain(testDispatcher)
whenever(appDiscovering.findAppForSso(any())).thenReturn(CrossApp.Rider.packages.toSet())
whenever(appDiscovering.findAppForSso(any(), any())).thenReturn("com.uber")
}

@Test
Expand Down Expand Up @@ -106,14 +108,27 @@ class UniversalSsoLinkTest : RobolectricTestBase() {
@Test
fun `execute should use inApp authentication when apps are not present`() =
runTest(testDispatcher) {
whenever(appDiscovering.findAppForSso(any())).thenReturn(emptySet())
whenever(appDiscovering.findAppForSso(any(), any())).thenReturn(null)

doNothing().whenever(customTabsLauncher).launch(any())
universalSsoLink.resultDeferred.complete("SuccessResult")

// Simulate calling execute and handle outcomes.
val result = universalSsoLink.execute(mapOf("param1" to "value1"))
val result = universalSsoLink.execute(mapOf())

assertNotNull(result)
assertEquals("SuccessResult", result)

verify(customTabsLauncher).launch(any())
}

@Test
fun `handleAuthCode when called should complete`() =
runTest(testDispatcher) {
universalSsoLink.handleAuthCode("authCode")
val result = universalSsoLink.execute(mapOf())

assertNotNull(result)
assertEquals("authCode", result)
}
}

0 comments on commit a8f9739

Please sign in to comment.