Skip to content
Snippets Groups Projects
Commit 5802293c authored by clairehurst's avatar clairehurst Committed by morgan
Browse files

Bug 42089: [android] Remove ability to submit site support requests

parent 946776bb
Branches
Tags
2 merge requests!1202Bug_43099: 2024 YEC Strings,!1136Bug 43085: Rebased alpha onto 128.2.0esr
Showing
with 293 additions and 245 deletions
......@@ -21,7 +21,7 @@ import org.mozilla.geckoview.StorageController
*/
class GeckoCookieBannersStorage(
runtime: GeckoRuntime,
private val reportSiteDomainsRepository: ReportSiteDomainsRepository,
// private val reportSiteDomainsRepository: ReportSiteDomainsRepository,
) : CookieBannersStorage {
private val geckoStorage: StorageController = runtime.storageController
......@@ -34,13 +34,13 @@ class GeckoCookieBannersStorage(
setGeckoException(uri, DISABLED, privateBrowsing)
}
override suspend fun isSiteDomainReported(siteDomain: String): Boolean {
return reportSiteDomainsRepository.isSiteDomainReported(siteDomain)
}
override suspend fun saveSiteDomain(siteDomain: String) {
reportSiteDomainsRepository.saveSiteDomain(siteDomain)
}
// override suspend fun isSiteDomainReported(siteDomain: String): Boolean {
// return reportSiteDomainsRepository.isSiteDomainReported(siteDomain)
// }
//
// override suspend fun saveSiteDomain(siteDomain: String) {
// reportSiteDomainsRepository.saveSiteDomain(siteDomain)
// }
override suspend fun addPersistentExceptionInPrivateMode(uri: String) {
setPersistentPrivateGeckoException(uri, DISABLED)
......
......@@ -12,64 +12,64 @@ import androidx.datastore.preferences.core.stringPreferencesKey
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import mozilla.components.browser.engine.gecko.cookiebanners.ReportSiteDomainsRepository.PreferencesKeys.REPORT_SITE_DOMAINS
//import mozilla.components.browser.engine.gecko.cookiebanners.ReportSiteDomainsRepository.PreferencesKeys.REPORT_SITE_DOMAINS
import mozilla.components.support.base.log.logger.Logger
import java.io.IOException
/**
* A repository to save reported site domains with the datastore API.
*/
class ReportSiteDomainsRepository(
private val dataStore: DataStore<Preferences>,
) {
companion object {
const val SEPARATOR = "@<;>@"
const val REPORT_SITE_DOMAINS_REPOSITORY_NAME = "report_site_domains_preferences"
const val PREFERENCE_KEY_NAME = "report_site_domains"
}
private object PreferencesKeys {
val REPORT_SITE_DOMAINS = stringPreferencesKey(PREFERENCE_KEY_NAME)
}
/**
* Check if the given site's domain url is saved locally.
* @param siteDomain the [siteDomain] that will be checked.
*/
suspend fun isSiteDomainReported(siteDomain: String): Boolean {
return dataStore.data
.catch { exception ->
if (exception is IOException) {
Logger.error("Error reading preferences.", exception)
emit(emptyPreferences())
} else {
throw exception
}
}.map { preferences ->
val reportSiteDomainsString = preferences[REPORT_SITE_DOMAINS] ?: ""
val reportSiteDomainsList =
reportSiteDomainsString.split(SEPARATOR).filter { it.isNotEmpty() }
reportSiteDomainsList.contains(siteDomain)
}.first()
}
/**
* Save the given site's domain url in datastore to keep it persistent locally.
* This method gets called after the site domain was reported with Nimbus.
* @param siteDomain the [siteDomain] that will be saved.
*/
suspend fun saveSiteDomain(siteDomain: String) {
dataStore.edit { preferences ->
val siteDomainsPreferences = preferences[REPORT_SITE_DOMAINS] ?: ""
val siteDomainsList = siteDomainsPreferences.split(SEPARATOR).filter { it.isNotEmpty() }
if (siteDomainsList.contains(siteDomain)) {
return@edit
}
val domains = mutableListOf<String>()
domains.addAll(siteDomainsList)
domains.add(siteDomain)
preferences[REPORT_SITE_DOMAINS] = domains.joinToString(SEPARATOR)
}
}
}
//class ReportSiteDomainsRepository(
// private val dataStore: DataStore<Preferences>,
//) {
//
// companion object {
// const val SEPARATOR = "@<;>@"
// const val REPORT_SITE_DOMAINS_REPOSITORY_NAME = "report_site_domains_preferences"
// const val PREFERENCE_KEY_NAME = "report_site_domains"
// }
//
// private object PreferencesKeys {
// val REPORT_SITE_DOMAINS = stringPreferencesKey(PREFERENCE_KEY_NAME)
// }
//
// /**
// * Check if the given site's domain url is saved locally.
// * @param siteDomain the [siteDomain] that will be checked.
// */
// suspend fun isSiteDomainReported(siteDomain: String): Boolean {
// return dataStore.data
// .catch { exception ->
// if (exception is IOException) {
// Logger.error("Error reading preferences.", exception)
// emit(emptyPreferences())
// } else {
// throw exception
// }
// }.map { preferences ->
// val reportSiteDomainsString = preferences[REPORT_SITE_DOMAINS] ?: ""
// val reportSiteDomainsList =
// reportSiteDomainsString.split(SEPARATOR).filter { it.isNotEmpty() }
// reportSiteDomainsList.contains(siteDomain)
// }.first()
// }
//
// /**
// * Save the given site's domain url in datastore to keep it persistent locally.
// * This method gets called after the site domain was reported with Nimbus.
// * @param siteDomain the [siteDomain] that will be saved.
// */
// suspend fun saveSiteDomain(siteDomain: String) {
// dataStore.edit { preferences ->
// val siteDomainsPreferences = preferences[REPORT_SITE_DOMAINS] ?: ""
// val siteDomainsList = siteDomainsPreferences.split(SEPARATOR).filter { it.isNotEmpty() }
// if (siteDomainsList.contains(siteDomain)) {
// return@edit
// }
// val domains = mutableListOf<String>()
// domains.addAll(siteDomainsList)
// domains.add(siteDomain)
// preferences[REPORT_SITE_DOMAINS] = domains.joinToString(SEPARATOR)
// }
// }
//}
......@@ -26,136 +26,136 @@ import org.mozilla.geckoview.StorageController
@ExperimentalCoroutinesApi
class GeckoCookieBannersStorageTest {
private lateinit var runtime: GeckoRuntime
private lateinit var geckoStorage: GeckoCookieBannersStorage
private lateinit var storageController: StorageController
private lateinit var reportSiteDomainsRepository: ReportSiteDomainsRepository
@Before
fun setup() {
storageController = mock()
runtime = mock()
reportSiteDomainsRepository = mock()
whenever(runtime.storageController).thenReturn(storageController)
geckoStorage = spy(GeckoCookieBannersStorage(runtime, reportSiteDomainsRepository))
}
@Test
fun `GIVEN a cookie banner mode WHEN adding an exception THEN add an exception for the given uri and browsing mode`() =
runTest {
val uri = "https://www.mozilla.org"
doNothing().`when`(geckoStorage)
.setGeckoException(uri = uri, mode = DISABLED, privateBrowsing = false)
geckoStorage.addException(uri = uri, privateBrowsing = false)
verify(geckoStorage).setGeckoException(uri, DISABLED, false)
}
@Test
fun `GIVEN uri and browsing mode WHEN removing an exception THEN remove the exception`() =
runTest {
val uri = "https://www.mozilla.org"
doNothing().`when`(geckoStorage).removeGeckoException(uri, false)
geckoStorage.removeException(uri = uri, privateBrowsing = false)
verify(geckoStorage).removeGeckoException(uri, false)
}
@Test
fun `GIVEN uri and browsing mode WHEN querying an exception THEN return the matching exception`() =
runTest {
val uri = "https://www.mozilla.org"
doReturn(REJECT_OR_ACCEPT_ALL).`when`(geckoStorage)
.queryExceptionInGecko(uri = uri, privateBrowsing = false)
val result = geckoStorage.findExceptionFor(uri = uri, privateBrowsing = false)
assertEquals(REJECT_OR_ACCEPT_ALL, result)
}
@Test
fun `GIVEN error WHEN querying an exception THEN return null`() =
runTest {
val uri = "https://www.mozilla.org"
doReturn(null).`when`(geckoStorage)
.queryExceptionInGecko(uri = uri, privateBrowsing = false)
val result = geckoStorage.findExceptionFor(uri = uri, privateBrowsing = false)
assertNull(result)
}
@Test
fun `GIVEN uri and browsing mode WHEN checking for an exception THEN indicate if it has exceptions`() =
runTest {
val uri = "https://www.mozilla.org"
doReturn(REJECT_OR_ACCEPT_ALL).`when`(geckoStorage)
.queryExceptionInGecko(uri = uri, privateBrowsing = false)
var result = geckoStorage.hasException(uri = uri, privateBrowsing = false)
assertFalse(result!!)
Mockito.reset(geckoStorage)
doReturn(DISABLED).`when`(geckoStorage)
.queryExceptionInGecko(uri = uri, privateBrowsing = false)
result = geckoStorage.hasException(uri = uri, privateBrowsing = false)
assertTrue(result!!)
}
@Test
fun `GIVEN an error WHEN checking for an exception THEN indicate if that an error happened`() =
runTest {
val uri = "https://www.mozilla.org"
doReturn(null).`when`(geckoStorage)
.queryExceptionInGecko(uri = uri, privateBrowsing = false)
val result = geckoStorage.hasException(uri = uri, privateBrowsing = false)
assertNull(result)
}
@Test
fun `GIVEN a cookie banner mode WHEN adding a persistent exception in private mode THEN add a persistent exception for the given uri in private browsing mode`() =
runTest {
val uri = "https://www.mozilla.org"
doNothing().`when`(geckoStorage)
.setPersistentPrivateGeckoException(uri = uri, mode = DISABLED)
geckoStorage.addPersistentExceptionInPrivateMode(uri = uri)
verify(geckoStorage).setPersistentPrivateGeckoException(uri, DISABLED)
}
@Test
fun `GIVEN site domain url WHEN checking if site domain is reported THEN the report site domain repository gets called`() =
runTest {
val reportSiteDomainUrl = "mozilla.org"
geckoStorage.isSiteDomainReported(reportSiteDomainUrl)
verify(reportSiteDomainsRepository).isSiteDomainReported(reportSiteDomainUrl)
}
@Test
fun `GIVEN site domain url WHEN saving a site domain THEN the save method from repository should get called`() =
runTest {
val reportSiteDomainUrl = "mozilla.org"
geckoStorage.saveSiteDomain(reportSiteDomainUrl)
verify(reportSiteDomainsRepository).saveSiteDomain(reportSiteDomainUrl)
}
// private lateinit var runtime: GeckoRuntime
// private lateinit var geckoStorage: GeckoCookieBannersStorage
// private lateinit var storageController: StorageController
// private lateinit var reportSiteDomainsRepository: ReportSiteDomainsRepository
//
// @Before
// fun setup() {
// storageController = mock()
// runtime = mock()
// reportSiteDomainsRepository = mock()
//
// whenever(runtime.storageController).thenReturn(storageController)
//
// geckoStorage = spy(GeckoCookieBannersStorage(runtime, reportSiteDomainsRepository))
// }
//
// @Test
// fun `GIVEN a cookie banner mode WHEN adding an exception THEN add an exception for the given uri and browsing mode`() =
// runTest {
// val uri = "https://www.mozilla.org"
//
// doNothing().`when`(geckoStorage)
// .setGeckoException(uri = uri, mode = DISABLED, privateBrowsing = false)
//
// geckoStorage.addException(uri = uri, privateBrowsing = false)
//
// verify(geckoStorage).setGeckoException(uri, DISABLED, false)
// }
//
// @Test
// fun `GIVEN uri and browsing mode WHEN removing an exception THEN remove the exception`() =
// runTest {
// val uri = "https://www.mozilla.org"
//
// doNothing().`when`(geckoStorage).removeGeckoException(uri, false)
//
// geckoStorage.removeException(uri = uri, privateBrowsing = false)
//
// verify(geckoStorage).removeGeckoException(uri, false)
// }
//
// @Test
// fun `GIVEN uri and browsing mode WHEN querying an exception THEN return the matching exception`() =
// runTest {
// val uri = "https://www.mozilla.org"
//
// doReturn(REJECT_OR_ACCEPT_ALL).`when`(geckoStorage)
// .queryExceptionInGecko(uri = uri, privateBrowsing = false)
//
// val result = geckoStorage.findExceptionFor(uri = uri, privateBrowsing = false)
// assertEquals(REJECT_OR_ACCEPT_ALL, result)
// }
//
// @Test
// fun `GIVEN error WHEN querying an exception THEN return null`() =
// runTest {
// val uri = "https://www.mozilla.org"
//
// doReturn(null).`when`(geckoStorage)
// .queryExceptionInGecko(uri = uri, privateBrowsing = false)
//
// val result = geckoStorage.findExceptionFor(uri = uri, privateBrowsing = false)
// assertNull(result)
// }
//
// @Test
// fun `GIVEN uri and browsing mode WHEN checking for an exception THEN indicate if it has exceptions`() =
// runTest {
// val uri = "https://www.mozilla.org"
//
// doReturn(REJECT_OR_ACCEPT_ALL).`when`(geckoStorage)
// .queryExceptionInGecko(uri = uri, privateBrowsing = false)
//
// var result = geckoStorage.hasException(uri = uri, privateBrowsing = false)
//
// assertFalse(result!!)
//
// Mockito.reset(geckoStorage)
//
// doReturn(DISABLED).`when`(geckoStorage)
// .queryExceptionInGecko(uri = uri, privateBrowsing = false)
//
// result = geckoStorage.hasException(uri = uri, privateBrowsing = false)
//
// assertTrue(result!!)
// }
//
// @Test
// fun `GIVEN an error WHEN checking for an exception THEN indicate if that an error happened`() =
// runTest {
// val uri = "https://www.mozilla.org"
//
// doReturn(null).`when`(geckoStorage)
// .queryExceptionInGecko(uri = uri, privateBrowsing = false)
//
// val result = geckoStorage.hasException(uri = uri, privateBrowsing = false)
//
// assertNull(result)
// }
//
// @Test
// fun `GIVEN a cookie banner mode WHEN adding a persistent exception in private mode THEN add a persistent exception for the given uri in private browsing mode`() =
// runTest {
// val uri = "https://www.mozilla.org"
//
// doNothing().`when`(geckoStorage)
// .setPersistentPrivateGeckoException(uri = uri, mode = DISABLED)
//
// geckoStorage.addPersistentExceptionInPrivateMode(uri = uri)
//
// verify(geckoStorage).setPersistentPrivateGeckoException(uri, DISABLED)
// }
//
// @Test
// fun `GIVEN site domain url WHEN checking if site domain is reported THEN the report site domain repository gets called`() =
// runTest {
// val reportSiteDomainUrl = "mozilla.org"
//
// geckoStorage.isSiteDomainReported(reportSiteDomainUrl)
//
// verify(reportSiteDomainsRepository).isSiteDomainReported(reportSiteDomainUrl)
// }
//
// @Test
// fun `GIVEN site domain url WHEN saving a site domain THEN the save method from repository should get called`() =
// runTest {
// val reportSiteDomainUrl = "mozilla.org"
//
// geckoStorage.saveSiteDomain(reportSiteDomainUrl)
//
// verify(reportSiteDomainsRepository).saveSiteDomain(reportSiteDomainUrl)
// }
}
......@@ -23,52 +23,52 @@ import org.junit.runner.RunWith
@ExperimentalCoroutinesApi
@RunWith(AndroidJUnit4::class)
class ReportSiteDomainsRepositoryTest {
companion object {
const val TEST_DATASTORE_NAME = "test_data_store"
}
private lateinit var testDataStore: DataStore<Preferences>
private lateinit var reportSiteDomainsRepository: ReportSiteDomainsRepository
@Before
fun setUp() {
testDataStore = PreferenceDataStoreFactory.create(
produceFile = { testContext.preferencesDataStoreFile(TEST_DATASTORE_NAME) },
)
reportSiteDomainsRepository = ReportSiteDomainsRepository(testDataStore)
}
@After
fun cleanUp() = runTest { testDataStore.edit { it.clear() } }
@Test
fun `GIVEN site domain url WHEN site domain url is not saved THEN is side domain reported return false`() =
runTest {
assertFalse(reportSiteDomainsRepository.isSiteDomainReported("mozilla.org"))
}
@Test
fun `GIVEN site domain url WHEN site domain url is saved THEN is side domain reported return true`() =
runTest {
val siteDomainReported = "mozilla.org"
reportSiteDomainsRepository.saveSiteDomain(siteDomainReported)
assertTrue(reportSiteDomainsRepository.isSiteDomainReported(siteDomainReported))
}
@Test
fun `GIVEN site domain urls WHEN site domain urls are saved THEN is side domain reported return true for each one`() =
runTest {
val mozillaSiteDomainReported = "mozilla.org"
val youtubeSiteDomainReported = "youtube.com"
reportSiteDomainsRepository.saveSiteDomain(mozillaSiteDomainReported)
reportSiteDomainsRepository.saveSiteDomain(youtubeSiteDomainReported)
assertTrue(reportSiteDomainsRepository.isSiteDomainReported(mozillaSiteDomainReported))
assertTrue(reportSiteDomainsRepository.isSiteDomainReported(youtubeSiteDomainReported))
}
//
// companion object {
// const val TEST_DATASTORE_NAME = "test_data_store"
// }
//
// private lateinit var testDataStore: DataStore<Preferences>
//
// private lateinit var reportSiteDomainsRepository: ReportSiteDomainsRepository
//
// @Before
// fun setUp() {
// testDataStore = PreferenceDataStoreFactory.create(
// produceFile = { testContext.preferencesDataStoreFile(TEST_DATASTORE_NAME) },
// )
// reportSiteDomainsRepository = ReportSiteDomainsRepository(testDataStore)
// }
//
// @After
// fun cleanUp() = runTest { testDataStore.edit { it.clear() } }
//
// @Test
// fun `GIVEN site domain url WHEN site domain url is not saved THEN is side domain reported return false`() =
// runTest {
// assertFalse(reportSiteDomainsRepository.isSiteDomainReported("mozilla.org"))
// }
//
// @Test
// fun `GIVEN site domain url WHEN site domain url is saved THEN is side domain reported return true`() =
// runTest {
// val siteDomainReported = "mozilla.org"
//
// reportSiteDomainsRepository.saveSiteDomain(siteDomainReported)
//
// assertTrue(reportSiteDomainsRepository.isSiteDomainReported(siteDomainReported))
// }
//
// @Test
// fun `GIVEN site domain urls WHEN site domain urls are saved THEN is side domain reported return true for each one`() =
// runTest {
// val mozillaSiteDomainReported = "mozilla.org"
// val youtubeSiteDomainReported = "youtube.com"
//
// reportSiteDomainsRepository.saveSiteDomain(mozillaSiteDomainReported)
// reportSiteDomainsRepository.saveSiteDomain(youtubeSiteDomainReported)
//
// assertTrue(reportSiteDomainsRepository.isSiteDomainReported(mozillaSiteDomainReported))
// assertTrue(reportSiteDomainsRepository.isSiteDomainReported(youtubeSiteDomainReported))
// }
}
......@@ -24,14 +24,14 @@ interface CookieBannersStorage {
* Check if the given site's domain url is saved locally.
* @param siteDomain the [siteDomain] that will be checked.
*/
suspend fun isSiteDomainReported(siteDomain: String): Boolean
// suspend fun isSiteDomainReported(siteDomain: String): Boolean
/**
* Save the given site's domain url in datastore to keep it persistent locally.
* This method gets called after the site domain was reported with Nimbus.
* @param siteDomain the [siteDomain] that will be saved.
*/
suspend fun saveSiteDomain(siteDomain: String)
// suspend fun saveSiteDomain(siteDomain: String)
/**
* Set persistently the [CookieBannerHandlingMode.DISABLED] mode for the given [uri] in
......
mobile/android/fenix/app/src/beta/ic_launcher-playstore.png

64.2 KiB

mobile/android/fenix/app/src/beta/ic_launcher_monochrome-playstore.png

27.3 KiB

<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="432"
android:viewportHeight="432">
<path
android:pathData="m0,0h432v432h-432z"
android:fillColor="#dcf9ef"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="256"
android:viewportHeight="257">
<group android:scaleX="0.4869866"
android:scaleY="0.4888889"
android:translateX="65.66572"
android:translateY="65.67778">
<path
android:pathData="M62.56,111.94C67,111.94 70.72,110.38 73.92,107.17C77.13,103.96 78.68,99.93 78.68,94.86C78.68,90.5 77.04,86.73 73.65,83.34L73.63,83.32C70.34,79.95 66.63,78.31 62.29,78.31C58.59,78.31 55.28,79.9 52.17,83.17C49.12,86.38 47.63,90.16 47.63,94.72C47.63,97.37 47.99,99.8 48.7,101.94C49.48,104.04 50.53,105.88 51.84,107.43C53.11,108.84 54.66,109.98 56.45,110.81C58.27,111.56 60.33,111.94 62.56,111.94Z"
android:fillColor="#4A454E"/>
<path
android:pathData="M128,256.91C198.69,256.91 256,199.6 256,128.91C256,58.22 198.69,0.91 128,0.91C57.31,0.91 0,58.22 0,128.91C0,199.6 57.31,256.91 128,256.91ZM233,128.91C233,70.92 185.99,23.91 128,23.91V39.91C177.15,39.91 217,79.75 217,128.91C217,178.06 177.15,217.91 128,217.91V233.91C185.99,233.91 233,186.9 233,128.91ZM193.75,128.91C193.75,92.6 164.31,63.16 128,63.16V79.16C155.48,79.16 177.75,101.43 177.75,128.91C177.75,156.38 155.48,178.66 128,178.66V194.66C164.31,194.66 193.75,165.22 193.75,128.91ZM128,101.66C143.05,101.66 155.25,113.86 155.25,128.91C155.25,143.96 143.05,156.16 128,156.16V101.66ZM90.71,94.86C90.71,102.56 93.36,108.02 98.8,111.54C100.29,112.5 101.06,114.24 100.75,115.96L99.93,120.5C99.68,121.87 98.79,123.03 97.53,123.61C96.29,124.18 94.9,124.11 93.71,123.42C89.35,120.88 86.16,117.89 84.18,114.5C82.28,116.93 79.87,119.01 76.97,120.71L76.97,120.72L76.75,120.84C72.29,123.36 67.51,124.64 62.56,124.64C53.76,124.64 46.62,121.63 41.34,115.68L41.3,115.63C36.54,110.19 34.13,103.15 34.13,94.72C34.13,87.5 36.44,81.01 40.98,75.43L41.23,75.12L41.48,74.83C46.84,68.62 53.54,65.47 62.56,65.47C71.58,65.47 78.82,68.88 84.13,75.62C86.04,71.65 89.25,68.27 93.74,65.52C94.97,64.77 96.45,64.71 97.73,65.34C99.04,66 99.91,67.26 100.05,68.73L100.51,73.51C100.64,74.82 100.16,76.11 99.2,77.03C93.49,82.51 90.71,88.34 90.71,94.86Z"
android:fillColor="#4A454E"
android:fillType="evenOdd"/>
</group>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_launcher_monochrome_foreground" />
</adaptive-icon>
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_monochrome_background"/>
<foreground android:drawable="@drawable/ic_launcher_monochrome_foreground"/>
</adaptive-icon>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_monochrome_background"/>
<foreground android:drawable="@drawable/ic_launcher_monochrome_foreground"/>
</adaptive-icon>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>
\ No newline at end of file
mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher.webp

3.39 KiB | W: | H:

mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher.webp

2.59 KiB | W: | H:

mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher.webp
mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher.webp
mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher.webp
mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher.webp
  • 2-up
  • Swipe
  • Onion skin
mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher_foreground.webp

4.41 KiB

mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher_monochrome.webp

1.57 KiB

mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher_monochrome_round.webp

3.04 KiB

mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher_round.webp

5.1 KiB | W: | H:

mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher_round.webp

4.68 KiB | W: | H:

mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher_round.webp
mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher_round.webp
mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher_round.webp
mobile/android/fenix/app/src/beta/res/mipmap-hdpi/ic_launcher_round.webp
  • 2-up
  • Swipe
  • Onion skin
mobile/android/fenix/app/src/beta/res/mipmap-mdpi/ic_launcher.webp

1.92 KiB | W: | H:

mobile/android/fenix/app/src/beta/res/mipmap-mdpi/ic_launcher.webp

1.73 KiB | W: | H:

mobile/android/fenix/app/src/beta/res/mipmap-mdpi/ic_launcher.webp
mobile/android/fenix/app/src/beta/res/mipmap-mdpi/ic_launcher.webp
mobile/android/fenix/app/src/beta/res/mipmap-mdpi/ic_launcher.webp
mobile/android/fenix/app/src/beta/res/mipmap-mdpi/ic_launcher.webp
  • 2-up
  • Swipe
  • Onion skin
mobile/android/fenix/app/src/beta/res/mipmap-mdpi/ic_launcher_foreground.webp

2.84 KiB

0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment