Skip to content

Commit

Permalink
move location permissions to use site permissions manager
Browse files Browse the repository at this point in the history
  • Loading branch information
malmstein committed Nov 4, 2024
1 parent af6f231 commit aa054f0
Show file tree
Hide file tree
Showing 17 changed files with 177 additions and 91 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import org.junit.Rule
import org.junit.Test
import org.mockito.kotlin.mock

class GeoLocationPermissionsTest {
class GeoLocationPermissionsTestRequest {

@get:Rule
var instantTaskExecutorRule = InstantTaskExecutorRule()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import org.mockito.MockitoAnnotations
import org.mockito.kotlin.mock
import org.mockito.kotlin.verify

class LocationPermissionsRepositoryImplTest {
class LocationPermissionsRepositoryImplTestRequest {

@get:Rule
@Suppress("unused")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import com.duckduckgo.appbuildconfig.api.AppBuildConfig
import com.duckduckgo.common.utils.DefaultDispatcherProvider
import com.duckduckgo.common.utils.DispatcherProvider
import com.duckduckgo.site.permissions.api.SitePermissionsManager
import com.duckduckgo.site.permissions.api.SitePermissionsManager.LocationPermissionRequest
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
Expand Down Expand Up @@ -144,7 +145,7 @@ class BrowserChromeClient @Inject constructor(
}

override fun onPermissionRequest(request: PermissionRequest) {
Timber.d("Permissions: permission requested $request")
Timber.d("Permissions: permission requested ${request.resources.asList()}")
webViewClientListener?.getCurrentTabId()?.let { tabId ->
appCoroutineScope.launch(coroutineDispatcher.io()) {
val permissionsAllowedToAsk = sitePermissionsManager.getSitePermissions(tabId, request)
Expand All @@ -156,6 +157,16 @@ class BrowserChromeClient @Inject constructor(
}
}

override fun onGeolocationPermissionsShowPrompt(
origin: String,
callback: GeolocationPermissions.Callback,
) {
Timber.d("Permissions: location permission requested $origin")
onPermissionRequest(LocationPermissionRequest(origin, callback))

// webViewClientListener?.onSiteLocationPermissionRequested(origin, callback)
}

override fun onCloseWindow(window: WebView?) {
webViewClientListener?.closeCurrentTab()
}
Expand Down Expand Up @@ -210,13 +221,6 @@ class BrowserChromeClient @Inject constructor(
return true
}

override fun onGeolocationPermissionsShowPrompt(
origin: String,
callback: GeolocationPermissions.Callback,
) {
webViewClientListener?.onSiteLocationPermissionRequested(origin, callback)
}

override fun getDefaultVideoPoster(): Bitmap {
return Bitmap.createBitmap(intArrayOf(Color.TRANSPARENT), 1, 1, ARGB_8888)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ import com.duckduckgo.savedsites.impl.bookmarks.FaviconPromptSheet
import com.duckduckgo.savedsites.impl.dialogs.EditSavedSiteDialogFragment
import com.duckduckgo.site.permissions.api.SitePermissionsDialogLauncher
import com.duckduckgo.site.permissions.api.SitePermissionsGrantedListener
import com.duckduckgo.site.permissions.api.SitePermissionsManager.LocationPermission
import com.duckduckgo.site.permissions.api.SitePermissionsManager.LocationPermissionRequest
import com.duckduckgo.site.permissions.api.SitePermissionsManager.SitePermissions
import com.duckduckgo.subscriptions.api.Subscriptions
import com.duckduckgo.user.agent.api.ClientBrandHintProvider
Expand Down Expand Up @@ -1664,7 +1664,7 @@ class BrowserTabFragment :
is Command.ShowWebContent -> webView?.show()
is Command.CheckSystemLocationPermission -> checkSystemLocationPermission(it.domain, it.deniedForever)
is Command.RequestSystemLocationPermission -> requestLocationPermissions()
is Command.AskDomainLocationPermission -> askSiteLocationPermission(it.locationPermission)
is Command.AskDomainLocationPermission -> askSiteLocationPermission(it.locationPermissionRequest)
is Command.RefreshUserAgent -> refreshUserAgent(it.url, it.isDesktop)
is Command.AskToFireproofWebsite -> askToFireproofWebsite(requireContext(), it.fireproofWebsite)
is Command.AskToAutomateFireproofWebsite -> askToAutomateFireproofWebsite(requireContext(), it.fireproofWebsite)
Expand Down Expand Up @@ -1972,16 +1972,14 @@ class BrowserTabFragment :
)
}

private fun askSiteLocationPermission(locationPermission: LocationPermission) {
private fun askSiteLocationPermission(locationPermissionRequest: LocationPermissionRequest) {
if (!isActiveCustomTab() && !isActiveTab) {
Timber.v("Will not launch a dialog for an inactive tab")
return
}

val domain = locationPermission.origin

activity?.let {
sitePermissionsDialogLauncher.askForLocationPermission(it, locationPermission, tabId)
sitePermissionsDialogLauncher.showSiteLocationPermissionDialog(it, locationPermissionRequest, tabId)
}

// val binding = ContentSiteLocationPermissionDialogBinding.inflate(layoutInflater)
Expand Down
20 changes: 10 additions & 10 deletions app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ import com.duckduckgo.savedsites.impl.SavedSitesPixelName
import com.duckduckgo.savedsites.impl.dialogs.EditSavedSiteDialogFragment.DeleteBookmarkListener
import com.duckduckgo.savedsites.impl.dialogs.EditSavedSiteDialogFragment.EditSavedSiteListener
import com.duckduckgo.site.permissions.api.SitePermissionsManager
import com.duckduckgo.site.permissions.api.SitePermissionsManager.LocationPermission
import com.duckduckgo.site.permissions.api.SitePermissionsManager.LocationPermissionRequest
import com.duckduckgo.site.permissions.api.SitePermissionsManager.SitePermissionQueryResponse
import com.duckduckgo.site.permissions.api.SitePermissionsManager.SitePermissions
import com.duckduckgo.subscriptions.api.Subscriptions
Expand Down Expand Up @@ -492,7 +492,7 @@ class BrowserTabViewModel @Inject constructor(
val title: String?
get() = site?.title

private var locationPermission: LocationPermission? = null
private var locationPermissionRequest: LocationPermissionRequest? = null
private val locationPermissionMessages: MutableMap<String, Boolean> = mutableMapOf()
private val locationPermissionSession: MutableMap<String, LocationPermissionType> = mutableMapOf()

Expand Down Expand Up @@ -1740,7 +1740,7 @@ class BrowserTabViewModel @Inject constructor(
origin: String,
callback: GeolocationPermissions.Callback,
) {
locationPermission = LocationPermission(origin, callback)
locationPermissionRequest = LocationPermissionRequest(origin, callback)

Timber.d("Permissions: onSiteLocationPermissionRequested $origin")
if (!geoLocationPermissions.isDeviceLocationEnabled()) {
Expand Down Expand Up @@ -1802,7 +1802,7 @@ class BrowserTabViewModel @Inject constructor(
domain: String,
permission: LocationPermissionType,
) {
locationPermission?.let { locationPermission ->
locationPermissionRequest?.let { locationPermission ->
when (permission) {
LocationPermissionType.ALLOW_ALWAYS -> {
onSiteLocationPermissionAlwaysAllowed()
Expand Down Expand Up @@ -1839,14 +1839,14 @@ class BrowserTabViewModel @Inject constructor(
}

private fun onSiteLocationPermissionAlwaysAllowed() {
locationPermission?.let { locationPermission ->
locationPermissionRequest?.let { locationPermission ->
geoLocationPermissions.allow(locationPermission.origin)
locationPermission.callback.invoke(locationPermission.origin, true, false)
}
}

fun onSiteLocationPermissionAlwaysDenied() {
locationPermission?.let { locationPermission ->
locationPermissionRequest?.let { locationPermission ->
geoLocationPermissions.clear(locationPermission.origin)
locationPermission.callback.invoke(locationPermission.origin, false, false)
}
Expand All @@ -1857,7 +1857,7 @@ class BrowserTabViewModel @Inject constructor(
}

private fun reactToSitePermission(permission: LocationPermissionType) {
locationPermission?.let { locationPermission ->
locationPermissionRequest?.let { locationPermission ->
when (permission) {
LocationPermissionType.ALLOW_ALWAYS -> {
onSiteLocationPermissionAlwaysAllowed()
Expand All @@ -1879,7 +1879,7 @@ class BrowserTabViewModel @Inject constructor(
}

private fun reactToSiteSessionPermission(permission: LocationPermissionType) {
locationPermission?.let { locationPermission ->
locationPermissionRequest?.let { locationPermission ->
if (permission == LocationPermissionType.ALLOW_ONCE) {
locationPermission.callback.invoke(locationPermission.origin, true, false)
} else {
Expand All @@ -1899,14 +1899,14 @@ class BrowserTabViewModel @Inject constructor(
}

fun onSystemLocationPermissionNeverAllowed() {
locationPermission?.let { locationPermission ->
locationPermissionRequest?.let { locationPermission ->
onSiteLocationPermissionSelected(locationPermission.origin, LocationPermissionType.DENY_ALWAYS)
pixel.fire(AppPixelName.PRECISE_LOCATION_SYSTEM_DIALOG_NEVER)
}
}

fun onSystemLocationPermissionGranted() {
locationPermission?.let { locationPermission ->
locationPermissionRequest?.let { locationPermission ->
appSettingsPreferencesStore.appLocationPermissionDeniedForever = false
appSettingsPreferencesStore.appLocationPermission = true
pixel.fire(AppPixelName.PRECISE_LOCATION_SETTINGS_LOCATION_PERMISSION_ENABLE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import com.duckduckgo.browser.api.brokensite.BrokenSiteData
import com.duckduckgo.js.messaging.api.JsCallbackData
import com.duckduckgo.js.messaging.api.SubscriptionEventData
import com.duckduckgo.savedsites.api.models.SavedSite
import com.duckduckgo.site.permissions.api.SitePermissionsManager.LocationPermission
import com.duckduckgo.site.permissions.api.SitePermissionsManager.LocationPermissionRequest
import com.duckduckgo.site.permissions.api.SitePermissionsManager.SitePermissions

sealed class Command {
Expand Down Expand Up @@ -165,7 +165,7 @@ sealed class Command {
val deniedForever: Boolean,
) : Command()

class AskDomainLocationPermission(val locationPermission: LocationPermission) : Command()
class AskDomainLocationPermission(val locationPermissionRequest: LocationPermissionRequest) : Command()
object RequestSystemLocationPermission : Command()
class RefreshUserAgent(
val url: String?,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import com.duckduckgo.common.utils.extensions.asLocationPermissionOrigin
import org.junit.Assert
import org.junit.Test

class LocationPermissionEntityTest {
class LocationPermissionRequestEntityTest {

@Test
fun whenDomainStartsWithHttpsThenDropPrefix() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package com.duckduckgo.site.permissions.api
import android.app.Activity
import android.webkit.PermissionRequest
import androidx.activity.result.ActivityResultCaller
import com.duckduckgo.site.permissions.api.SitePermissionsManager.LocationPermission
import com.duckduckgo.site.permissions.api.SitePermissionsManager.LocationPermissionRequest
import com.duckduckgo.site.permissions.api.SitePermissionsManager.SitePermissions

/** Public interface for requesting microphone and/or camera permissions when website requests it */
Expand Down Expand Up @@ -41,12 +41,12 @@ interface SitePermissionsDialogLauncher {
* This method should be called if website requests site permissions (audio or video). It will launch dialogs flow for asking the user.
*
* @param activity where this method is called from
* @param locationPermission information about the origin of the location permission
* @param locationPermissionRequest information about the origin of the location permission
* @param tabId id from the tab where this method is called from
*/
fun askForLocationPermission(
fun showSiteLocationPermissionDialog(
activity: Activity,
locationPermission: LocationPermission,
locationPermissionRequest: LocationPermissionRequest,
tabId: String,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@

package com.duckduckgo.site.permissions.api

import android.net.Uri
import android.webkit.GeolocationPermissions
import android.webkit.PermissionRequest
import androidx.core.net.toUri

/** Public interface for managing site permissions data */
interface SitePermissionsManager {
Expand Down Expand Up @@ -67,8 +69,29 @@ interface SitePermissionsManager {
* Class that represents a location permission asked
* callback is used to interact with the site that requested the permission
*/
data class LocationPermission(
data class LocationPermissionRequest(
val origin: String,
val callback: GeolocationPermissions.Callback,
)
) : PermissionRequest() {

override fun getOrigin(): Uri {
return origin.toUri()
}

override fun getResources(): Array<String> {
return listOf(RESOURCE_LOCATION_PERMISSION).toTypedArray()
}

override fun grant(p0: Array<out String>?) {
callback.invoke(origin, true, false)
}

override fun deny() {
callback.invoke(origin, false, false)
}

companion object {
const val RESOURCE_LOCATION_PERMISSION: String = "com.duckduckgo.permissions.resource.LOCATION_PERMISSION"
}
}
}
Loading

0 comments on commit aa054f0

Please sign in to comment.