Skip to content
Snippets Groups Projects
Commit 257257b8 authored by Matthew Finkel's avatar Matthew Finkel Committed by Pier Angelo Vendrame
Browse files

[android] Disable features and functionality

Bug 33594: Disable data collection by default (Glean)

Bug 40019: Adjust is disabled on Release when data collection is disabled

Bug 34338: Disable the crash reporter

Bug 40014: Neuter Google Advertising ID

Bug 40018: Disable Push service

Bug 40034: Disable PWA onboading

Bug 40072: Disable Tracking Protection

Bug 40061: Do not show "Send to device" in sharing menu

Bug 40109: Reduce requested permissions

Exclude LOCATION and NETWORK_STATE
parent 9778edcb
Branches
Tags
1 merge request!1503TB 43415, part 3: Shuffle commits
Showing
with 349 additions and 392 deletions
......@@ -180,7 +180,7 @@ class SettingsTest {
cookieBannerHandlingDetectOnlyMode = true,
cookieBannerHandlingGlobalRules = true,
cookieBannerHandlingGlobalRulesSubFrames = true,
emailTrackerBlockingPrivateBrowsing = true,
emailTrackerBlockingPrivateBrowsing = false,
)
assertFalse(defaultSettings.domStorageEnabled)
......
......
......@@ -8,6 +8,10 @@ apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
android {
androidResources {
ignoreAssetsPattern '!<dir>extensions'
}
defaultConfig {
minSdkVersion config.minSdkVersion
compileSdk config.compileSdkVersion
......
......
......@@ -79,7 +79,7 @@ class AddonManager(
* the [addonsProvider] or querying web extension state from the engine / store.
*/
@Throws(AddonManagerException::class)
@Suppress("TooGenericExceptionCaught")
@Suppress("TooGenericExceptionCaught", "UNUSED_PARAMETER")
suspend fun getAddons(waitForPendingActions: Boolean = true, allowCache: Boolean = true): List<Addon> {
try {
// Make sure extension support is initialized, i.e. the state of all installed extensions is known.
......@@ -93,6 +93,7 @@ class AddonManager(
// Get all the featured add-ons not installed from provider.
// NB: We're keeping translations only for the default locale.
var featuredAddons = emptyList<Addon>()
/* tor-browser#40502: Do not recommend addons on Tor Browser
try {
val userLanguage = Locale.getDefault().language
val locales = listOf(userLanguage)
......@@ -104,6 +105,7 @@ class AddonManager(
// Do not throw when we fail to fetch the featured add-ons since there can be installed add-ons.
logger.warn("Failed to get the featured add-ons", throwable)
}
*/
// Build a list of installed extensions that are not built-in extensions.
val installedAddons = installedExtensions
......
......
......@@ -9,7 +9,7 @@ apply plugin: 'kotlin-android'
android {
androidResources {
ignoreAssetsPattern '!amazon*:!azerdict*:!baidu*:!bing*:!ceneje*:!coccoc*:!daum*:!ebay*:!ecosia*:!faclair*:!google*:!gulesider*:!leo*:!mapy*:!mercadolibre*:!odpiralni*:!pazaruvaj*:!prisjakt*:!qwant*:!rakuten*:!salidzinilv*:!seznam*:!vatera*:!wikipedia-*:!wiktionary*:!yahoo*:!yandex*'
ignoreAssetsPattern '!<dir>extensions:!search_telemetry_v2.json:!amazon*:!azerdict*:!baidu*:!bing*:!ceneje*:!coccoc*:!daum*:!ebay*:!ecosia*:!faclair*:!google*:!gulesider*:!leo*:!mapy*:!mercadolibre*:!odpiralni*:!pazaruvaj*:!prisjakt*:!qwant*:!rakuten*:!salidzinilv*:!seznam*:!vatera*:!wikipedia-*:!wiktionary*:!yahoo*:!yandex*'
}
defaultConfig {
......
......
......@@ -8,7 +8,7 @@ import mozilla.appservices.remotesettings.RemoteSettingsResponse
import mozilla.components.support.base.log.logger.Logger
import mozilla.components.support.ktx.android.org.json.asSequence
import mozilla.components.support.ktx.android.org.json.toList
import mozilla.components.support.remotesettings.RemoteSettingsClient
//import mozilla.components.support.remotesettings.RemoteSettingsClient
import mozilla.components.support.remotesettings.RemoteSettingsResult
import org.jetbrains.annotations.VisibleForTesting
import org.json.JSONArray
......@@ -23,22 +23,22 @@ internal const val REMOTE_ENDPOINT_BUCKET_NAME = "main"
* Parse SERP Telemetry json from remote config.
*/
class SerpTelemetryRepository(
rootStorageDirectory: File,
// rootStorageDirectory: File,
private val readJson: () -> JSONObject,
collectionName: String,
serverUrl: String = REMOTE_PROD_ENDPOINT_URL,
bucketName: String = REMOTE_ENDPOINT_BUCKET_NAME,
// collectionName: String,
// serverUrl: String = REMOTE_PROD_ENDPOINT_URL,
// bucketName: String = REMOTE_ENDPOINT_BUCKET_NAME,
) {
val logger = Logger("SerpTelemetryRepository")
private var providerList: List<SearchProviderModel> = emptyList()
@VisibleForTesting
internal var remoteSettingsClient = RemoteSettingsClient(
serverUrl = serverUrl,
bucketName = bucketName,
collectionName = collectionName,
storageRootDirectory = rootStorageDirectory,
)
// @VisibleForTesting
// internal var remoteSettingsClient = RemoteSettingsClient(
// serverUrl = serverUrl,
// bucketName = bucketName,
// collectionName = collectionName,
// storageRootDirectory = rootStorageDirectory,
// )
/**
* Provides list of search providers from cache or dump and fetches from remotes server .
......@@ -65,7 +65,7 @@ class SerpTelemetryRepository(
val remoteResponse = fetchRemoteResponse()
if (remoteResponse.lastModified > cacheLastModified) {
providerList = parseRemoteResponse(remoteResponse)
writeToCache(remoteResponse)
//writeToCache(remoteResponse)
}
}
......@@ -73,8 +73,9 @@ class SerpTelemetryRepository(
* Writes data to local cache.
*/
@VisibleForTesting
internal suspend fun writeToCache(records: RemoteSettingsResponse): RemoteSettingsResult {
return remoteSettingsClient.write(records)
internal suspend fun writeToCache(/*records: RemoteSettingsResponse*/): RemoteSettingsResult {
return RemoteSettingsResult.NetworkFailure(Exception("Bug-43113: no remote fetching"))
// return remoteSettingsClient.write(records)
}
/**
......@@ -104,12 +105,12 @@ class SerpTelemetryRepository(
*/
@VisibleForTesting
internal suspend fun fetchRemoteResponse(): RemoteSettingsResponse {
val result = remoteSettingsClient.fetch()
return if (result is RemoteSettingsResult.Success) {
result.response
} else {
RemoteSettingsResponse(emptyList(), 0u)
}
// val result = remoteSettingsClient.fetch()
// return if (result is RemoteSettingsResult.Success) {
// result.response
// } else {
return RemoteSettingsResponse(emptyList(), 0u)
// }
}
/**
......@@ -117,16 +118,16 @@ class SerpTelemetryRepository(
*/
@VisibleForTesting
internal suspend fun loadProvidersFromCache(): Pair<ULong, List<SearchProviderModel>> {
val result = remoteSettingsClient.read()
return if (result is RemoteSettingsResult.Success) {
val response = result.response.records.mapNotNull {
it.fields.toSearchProviderModel()
}
val lastModified = result.response.lastModified
Pair(lastModified, response)
} else {
Pair(0u, emptyList())
}
// val result = remoteSettingsClient.read()
// return if (result is RemoteSettingsResult.Success) {
// val response = result.response.records.mapNotNull {
// it.fields.toSearchProviderModel()
// }
// val lastModified = result.response.lastModified
// Pair(lastModified, response)
// } else {
return Pair(0u, emptyList())
// }
}
}
......
......
......@@ -27,161 +27,161 @@ import java.io.File
@RunWith(AndroidJUnit4::class)
class BaseSearchTelemetryTest {
private lateinit var baseTelemetry: BaseSearchTelemetry
private lateinit var handler: BaseSearchTelemetry.SearchTelemetryMessageHandler
@Mock
private lateinit var mockRepo: SerpTelemetryRepository
private val mockReadJson: () -> JSONObject = mock()
private val mockRootStorageDirectory: File = mock()
private fun createMockProviderList(): List<SearchProviderModel> = listOf(
SearchProviderModel(
schema = 1698656464939,
taggedCodes = listOf("monline_7_dg"),
telemetryId = "baidu",
organicCodes = emptyList(),
codeParamName = "tn",
queryParamNames = listOf("wd"),
searchPageRegexp = "^https://(?:m|www)\\\\.baidu\\\\.com/(?:s|baidu)",
followOnParamNames = listOf("oq"),
extraAdServersRegexps = listOf("^https?://www\\\\.baidu\\\\.com/baidu\\\\.php?"),
expectedOrganicCodes = emptyList(),
),
)
private val rawJson = """
{
"data": [
{
"schema": 1698656464939,
"taggedCodes": [
"monline_7_dg"
],
"telemetryId": "baidu",
"organicCodes": [],
"codeParamName": "tn",
"queryParamNames": [
"wd"
],
"searchPageRegexp": "^https://(?:m|www)\\.baidu\\.com/(?:s|baidu)",
"followOnParamNames": [
"oq"
],
"extraAdServersRegexps": [
"^https?://www\\.baidu\\.com/baidu\\.php?"
],
"id": "19c434a3-d173-4871-9743-290ac92a3f6a",
"last_modified": 1698666532326
}],
"timestamp": 16
}
""".trimIndent()
@Before
fun setup() {
baseTelemetry = spy(
object : BaseSearchTelemetry() {
override suspend fun install(
engine: Engine,
store: BrowserStore,
providerList: List<SearchProviderModel>,
) {
// mock, do nothing
}
override fun processMessage(message: JSONObject) {
// mock, do nothing
}
},
)
handler = baseTelemetry.SearchTelemetryMessageHandler()
mockRepo = spy(SerpTelemetryRepository(mockRootStorageDirectory, mockReadJson, "test"))
}
@Test
fun `GIVEN an engine WHEN installWebExtension is called THEN the provided extension is installed in engine`() {
val engine: Engine = mock()
val store: BrowserStore = mock()
val id = "id"
val resourceUrl = "resourceUrl"
val messageId = "messageId"
val extensionInfo = ExtensionInfo(id, resourceUrl, messageId)
baseTelemetry.installWebExtension(engine, store, extensionInfo)
verify(engine).installBuiltInWebExtension(
id = eq(id),
url = eq(resourceUrl),
onSuccess = any(),
onError = any(),
)
}
@Test
fun `GIVEN a search provider does not exist for the url WHEN getProviderForUrl is called THEN return null`() {
val url = "https://www.mozilla.com/search?q=firefox"
baseTelemetry.providerList = createMockProviderList()
assertEquals(null, baseTelemetry.getProviderForUrl(url))
}
@Test(expected = IllegalStateException::class)
fun `GIVEN an extension message WHEN that cannot be processed THEN throw IllegalStateException`() {
val message = "message"
handler.onMessage(message, mock())
}
@Test
fun `GIVEN an extension message WHEN received THEN pass it to processMessage`() {
val message = JSONObject()
handler.onMessage(message, mock())
verify(baseTelemetry).processMessage(message)
}
@Test
fun `GIVEN empty cacheResponse WHEN initializeProviderList is called THEN update providerList`(): Unit =
runBlocking {
val localResponse = JSONObject(rawJson)
val cacheResponse: Pair<ULong, List<SearchProviderModel>> = Pair(0u, emptyList())
`when`(mockRepo.loadProvidersFromCache()).thenReturn(cacheResponse)
doAnswer {
localResponse
}.`when`(mockReadJson)()
`when`(mockRepo.parseLocalPreinstalledData(localResponse)).thenReturn(createMockProviderList())
doReturn(Unit).`when`(mockRepo).fetchRemoteResponse(any())
baseTelemetry.setProviderList(mockRepo.updateProviderList())
assertEquals(baseTelemetry.providerList.toString(), createMockProviderList().toString())
}
@Test
fun `GIVEN non-empty cacheResponse WHEN initializeProviderList is called THEN update providerList`(): Unit =
runBlocking {
val localResponse = JSONObject(rawJson)
val cacheResponse: Pair<ULong, List<SearchProviderModel>> = Pair(123u, createMockProviderList())
`when`(mockRepo.loadProvidersFromCache()).thenReturn(cacheResponse)
doAnswer {
localResponse
}.`when`(mockReadJson)()
doReturn(Unit).`when`(mockRepo).fetchRemoteResponse(any())
baseTelemetry.setProviderList(mockRepo.updateProviderList())
assertEquals(baseTelemetry.providerList.toString(), createMockProviderList().toString())
}
fun getProviderForUrl(url: String): SearchProviderModel? {
return createMockProviderList().find { provider ->
provider.searchPageRegexp.pattern.toRegex().containsMatchIn(url)
}
}
// private lateinit var baseTelemetry: BaseSearchTelemetry
// private lateinit var handler: BaseSearchTelemetry.SearchTelemetryMessageHandler
//
// @Mock
// private lateinit var mockRepo: SerpTelemetryRepository
//
// private val mockReadJson: () -> JSONObject = mock()
// private val mockRootStorageDirectory: File = mock()
//
// private fun createMockProviderList(): List<SearchProviderModel> = listOf(
// SearchProviderModel(
// schema = 1698656464939,
// taggedCodes = listOf("monline_7_dg"),
// telemetryId = "baidu",
// organicCodes = emptyList(),
// codeParamName = "tn",
// queryParamNames = listOf("wd"),
// searchPageRegexp = "^https://(?:m|www)\\\\.baidu\\\\.com/(?:s|baidu)",
// followOnParamNames = listOf("oq"),
// extraAdServersRegexps = listOf("^https?://www\\\\.baidu\\\\.com/baidu\\\\.php?"),
// expectedOrganicCodes = emptyList(),
// ),
// )
//
// private val rawJson = """
// {
// "data": [
// {
// "schema": 1698656464939,
// "taggedCodes": [
// "monline_7_dg"
// ],
// "telemetryId": "baidu",
// "organicCodes": [],
// "codeParamName": "tn",
// "queryParamNames": [
// "wd"
// ],
// "searchPageRegexp": "^https://(?:m|www)\\.baidu\\.com/(?:s|baidu)",
// "followOnParamNames": [
// "oq"
// ],
// "extraAdServersRegexps": [
// "^https?://www\\.baidu\\.com/baidu\\.php?"
// ],
// "id": "19c434a3-d173-4871-9743-290ac92a3f6a",
// "last_modified": 1698666532326
// }],
// "timestamp": 16
//}
// """.trimIndent()
//
// @Before
// fun setup() {
// baseTelemetry = spy(
// object : BaseSearchTelemetry() {
// override suspend fun install(
// engine: Engine,
// store: BrowserStore,
// providerList: List<SearchProviderModel>,
// ) {
// // mock, do nothing
// }
//
// override fun processMessage(message: JSONObject) {
// // mock, do nothing
// }
// },
// )
// handler = baseTelemetry.SearchTelemetryMessageHandler()
// mockRepo = spy(SerpTelemetryRepository(mockRootStorageDirectory, mockReadJson, "test"))
// }
//
// @Test
// fun `GIVEN an engine WHEN installWebExtension is called THEN the provided extension is installed in engine`() {
// val engine: Engine = mock()
// val store: BrowserStore = mock()
// val id = "id"
// val resourceUrl = "resourceUrl"
// val messageId = "messageId"
// val extensionInfo = ExtensionInfo(id, resourceUrl, messageId)
//
// baseTelemetry.installWebExtension(engine, store, extensionInfo)
//
// verify(engine).installBuiltInWebExtension(
// id = eq(id),
// url = eq(resourceUrl),
// onSuccess = any(),
// onError = any(),
// )
// }
//
// @Test
// fun `GIVEN a search provider does not exist for the url WHEN getProviderForUrl is called THEN return null`() {
// val url = "https://www.mozilla.com/search?q=firefox"
// baseTelemetry.providerList = createMockProviderList()
//
// assertEquals(null, baseTelemetry.getProviderForUrl(url))
// }
//
// @Test(expected = IllegalStateException::class)
// fun `GIVEN an extension message WHEN that cannot be processed THEN throw IllegalStateException`() {
// val message = "message"
//
// handler.onMessage(message, mock())
// }
//
// @Test
// fun `GIVEN an extension message WHEN received THEN pass it to processMessage`() {
// val message = JSONObject()
//
// handler.onMessage(message, mock())
//
// verify(baseTelemetry).processMessage(message)
// }
//
// @Test
// fun `GIVEN empty cacheResponse WHEN initializeProviderList is called THEN update providerList`(): Unit =
// runBlocking {
// val localResponse = JSONObject(rawJson)
// val cacheResponse: Pair<ULong, List<SearchProviderModel>> = Pair(0u, emptyList())
//
// `when`(mockRepo.loadProvidersFromCache()).thenReturn(cacheResponse)
// doAnswer {
// localResponse
// }.`when`(mockReadJson)()
//
// `when`(mockRepo.parseLocalPreinstalledData(localResponse)).thenReturn(createMockProviderList())
// doReturn(Unit).`when`(mockRepo).fetchRemoteResponse(any())
//
// baseTelemetry.setProviderList(mockRepo.updateProviderList())
//
// assertEquals(baseTelemetry.providerList.toString(), createMockProviderList().toString())
// }
//
// @Test
// fun `GIVEN non-empty cacheResponse WHEN initializeProviderList is called THEN update providerList`(): Unit =
// runBlocking {
// val localResponse = JSONObject(rawJson)
// val cacheResponse: Pair<ULong, List<SearchProviderModel>> = Pair(123u, createMockProviderList())
//
// `when`(mockRepo.loadProvidersFromCache()).thenReturn(cacheResponse)
// doAnswer {
// localResponse
// }.`when`(mockReadJson)()
// doReturn(Unit).`when`(mockRepo).fetchRemoteResponse(any())
//
// baseTelemetry.setProviderList(mockRepo.updateProviderList())
//
// assertEquals(baseTelemetry.providerList.toString(), createMockProviderList().toString())
// }
//
// fun getProviderForUrl(url: String): SearchProviderModel? {
// return createMockProviderList().find { provider ->
// provider.searchPageRegexp.pattern.toRegex().containsMatchIn(url)
// }
// }
}
......@@ -23,70 +23,70 @@ import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class SerpTelemetryRepositoryTest {
@Mock
private lateinit var mockRemoteSettingsClient: RemoteSettingsClient
private lateinit var serpTelemetryRepository: SerpTelemetryRepository
@Before
fun setup() {
MockitoAnnotations.openMocks(this)
serpTelemetryRepository = SerpTelemetryRepository(
rootStorageDirectory = mock(),
readJson = mock(),
collectionName = "",
serverUrl = "https://test.server",
bucketName = "",
)
serpTelemetryRepository.remoteSettingsClient = mockRemoteSettingsClient
}
@Test
fun `GIVEN non-empty response WHEN writeToCache is called THEN the result is a success`() = runBlocking {
val records = listOf(
RemoteSettingsRecord("1", 123u, false, null, JSONObject()),
RemoteSettingsRecord("2", 456u, true, null, JSONObject()),
)
val response = RemoteSettingsResponse(records, 125614567U)
`when`(mockRemoteSettingsClient.write(response))
.thenReturn(RemoteSettingsResult.Success(response))
val result = serpTelemetryRepository.writeToCache(response)
assertTrue(result is RemoteSettingsResult.Success)
assertEquals(response, (result as RemoteSettingsResult.Success).response)
}
@Test
fun `GIVEN non-empty response WHEN fetchRemoteResponse is called THEN the result is equal to the response`() = runBlocking {
val records = listOf(
RemoteSettingsRecord("1", 123u, false, null, JSONObject()),
RemoteSettingsRecord("2", 456u, true, null, JSONObject()),
)
val response = RemoteSettingsResponse(records, 125614567U)
`when`(mockRemoteSettingsClient.fetch())
.thenReturn(RemoteSettingsResult.Success(response))
val result = serpTelemetryRepository.fetchRemoteResponse()
assertEquals(response, result)
}
@Test
fun `GIVEN non-empty response WHEN loadProvidersFromCache is called THEN the result is equal to the response`() = runBlocking {
val records = listOf(
RemoteSettingsRecord("1", 123u, false, null, JSONObject()),
RemoteSettingsRecord("2", 456u, true, null, JSONObject()),
)
val response = RemoteSettingsResponse(records, 125614567U)
`when`(mockRemoteSettingsClient.read())
.thenReturn(RemoteSettingsResult.Success(response))
val result = serpTelemetryRepository.loadProvidersFromCache()
assertEquals(response.lastModified, result.first)
assertEquals(response.records.mapNotNull { it.fields.toSearchProviderModel() }, result.second)
}
// @Mock
// private lateinit var mockRemoteSettingsClient: RemoteSettingsClient
//
// private lateinit var serpTelemetryRepository: SerpTelemetryRepository
//
// @Before
// fun setup() {
// MockitoAnnotations.openMocks(this)
// serpTelemetryRepository = SerpTelemetryRepository(
// rootStorageDirectory = mock(),
// readJson = mock(),
// collectionName = "",
// serverUrl = "https://test.server",
// bucketName = "",
// )
//
// serpTelemetryRepository.remoteSettingsClient = mockRemoteSettingsClient
// }
//
// @Test
// fun `GIVEN non-empty response WHEN writeToCache is called THEN the result is a success`() = runBlocking {
// val records = listOf(
// RemoteSettingsRecord("1", 123u, false, null, JSONObject()),
// RemoteSettingsRecord("2", 456u, true, null, JSONObject()),
// )
// val response = RemoteSettingsResponse(records, 125614567U)
//
// `when`(mockRemoteSettingsClient.write(response))
// .thenReturn(RemoteSettingsResult.Success(response))
//
// val result = serpTelemetryRepository.writeToCache(response)
//
// assertTrue(result is RemoteSettingsResult.Success)
// assertEquals(response, (result as RemoteSettingsResult.Success).response)
// }
//
// @Test
// fun `GIVEN non-empty response WHEN fetchRemoteResponse is called THEN the result is equal to the response`() = runBlocking {
// val records = listOf(
// RemoteSettingsRecord("1", 123u, false, null, JSONObject()),
// RemoteSettingsRecord("2", 456u, true, null, JSONObject()),
// )
// val response = RemoteSettingsResponse(records, 125614567U)
// `when`(mockRemoteSettingsClient.fetch())
// .thenReturn(RemoteSettingsResult.Success(response))
//
// val result = serpTelemetryRepository.fetchRemoteResponse()
//
// assertEquals(response, result)
// }
//
// @Test
// fun `GIVEN non-empty response WHEN loadProvidersFromCache is called THEN the result is equal to the response`() = runBlocking {
// val records = listOf(
// RemoteSettingsRecord("1", 123u, false, null, JSONObject()),
// RemoteSettingsRecord("2", 456u, true, null, JSONObject()),
// )
// val response = RemoteSettingsResponse(records, 125614567U)
// `when`(mockRemoteSettingsClient.read())
// .thenReturn(RemoteSettingsResult.Success(response))
//
// val result = serpTelemetryRepository.loadProvidersFromCache()
//
// assertEquals(response.lastModified, result.first)
// assertEquals(response.records.mapNotNull { it.fields.toSearchProviderModel() }, result.second)
// }
}
......@@ -64,18 +64,20 @@ class RemoteSettingsClient(
*/
@Suppress("TooGenericExceptionCaught")
suspend fun fetch(): RemoteSettingsResult = withContext(Dispatchers.IO) {
try {
val serverRecords = RemoteSettings(config).use {
it.getRecords()
}
RemoteSettingsResult.Success(serverRecords)
} catch (e: RemoteSettingsException) {
Logger.error(e.message.toString())
RemoteSettingsResult.NetworkFailure(e)
} catch (e: NullPointerException) {
Logger.error(e.message.toString())
RemoteSettingsResult.NetworkFailure(e)
}
// try {
// val serverRecords = RemoteSettings(config).use {
// it.getRecords()
// }
// RemoteSettingsResult.Success(serverRecords)
// } catch (e: RemoteSettingsException) {
// Logger.error(e.message.toString())
// RemoteSettingsResult.NetworkFailure(e)
// } catch (e: NullPointerException) {
// Logger.error(e.message.toString())
// RemoteSettingsResult.NetworkFailure(e)
// }
RemoteSettingsResult.NetworkFailure(Exception("tb-43113: no remote fetching"))
}
/**
......@@ -123,7 +125,8 @@ class RemoteSettingsClient(
suspend fun RemoteSettingsClient.readOrFetch(): RemoteSettingsResult {
val readResult = read()
return if (readResult is RemoteSettingsResult.DiskFailure) {
fetch()
//fetch()
RemoteSettingsResult.NetworkFailure(Exception("tb-43113: no remote fetching"))
} else {
readResult
}
......
......
......@@ -106,6 +106,8 @@ android {
]
buildConfigField "String[]", "SUPPORTED_LOCALE_ARRAY", getSupportedLocales()
buildConfigField "boolean", "DATA_COLLECTION_DISABLED", "true"
}
def releaseTemplate = {
......@@ -315,6 +317,8 @@ android.applicationVariants.configureEach { variant ->
// -------------------------------------------------------------------------------------------------
def isDebug = variant.buildType.resValues['bool/IS_DEBUG']?.value ?: false
def isDataCollectionDisabled = variant.buildType.buildConfigFields['DATA_COLLECTION_DISABLED']?.value ?: true
def isDebugOrDCD = isDebug || isDataCollectionDisabled
def useReleaseVersioning = variant.buildType.buildConfigFields['USE_RELEASE_VERSIONING']?.value ?: false
println("----------------------------------------------")
......@@ -322,7 +326,7 @@ android.applicationVariants.configureEach { variant ->
println("Application ID: " + [variant.applicationId, variant.buildType.applicationIdSuffix].findAll().join())
println("Build type: " + variant.buildType.name)
println("Flavor: " + variant.flavorName)
println("Telemetry enabled: " + !isDebug)
println("Telemetry enabled: " + !isDebugOrDCD)
if (useReleaseVersioning) {
// The Google Play Store does not allow multiple APKs for the same app that all have the
......@@ -364,7 +368,7 @@ android.applicationVariants.configureEach { variant ->
// -------------------------------------------------------------------------------------------------
buildConfigField 'String', 'SENTRY_TOKEN', 'null'
if (!isDebug) {
if (!isDebugOrDCD) {
buildConfigField 'boolean', 'CRASH_REPORTING', 'true'
// Reading sentry token from local file (if it exists). In a release task on taskcluster it will be available.
try {
......@@ -375,7 +379,7 @@ android.applicationVariants.configureEach { variant ->
buildConfigField 'boolean', 'CRASH_REPORTING', 'false'
}
if (!isDebug) {
if (!isDebugOrDCD) {
buildConfigField 'boolean', 'TELEMETRY', 'true'
} else {
buildConfigField 'boolean', 'TELEMETRY', 'false'
......@@ -396,7 +400,7 @@ android.applicationVariants.configureEach { variant ->
print("Adjust token: ")
if (!isDebug) {
if (!isDebugOrDCD) {
try {
def token = new File("${rootDir}/.adjust_token").text.trim()
buildConfigField 'String', 'ADJUST_TOKEN', '"' + token + '"'
......@@ -706,12 +710,8 @@ dependencies {
implementation ComponentsDependencies.protobuf_javalite
implementation ComponentsDependencies.google_material
implementation FenixDependencies.adjust
implementation FenixDependencies.installreferrer // Required by Adjust
// Required for the Google Advertising ID
implementation ComponentsDependencies.play_services_ads_id
// Required for in-app reviews
implementation ComponentsDependencies.play_review
implementation ComponentsDependencies.play_review_ktx
......
......
......@@ -4,6 +4,7 @@
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
<!--
<shortcut
android:shortcutId="password_manager"
android:enabled="true"
......@@ -34,4 +35,5 @@
android:targetPackage="org.mozilla.firefox_beta"
android:targetClass="org.mozilla.fenix.IntentReceiverActivity" />
</shortcut>
-->
</shortcuts>
......@@ -4,6 +4,7 @@
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
<!--
<shortcut
android:shortcutId="password_manager"
android:enabled="true"
......@@ -34,4 +35,5 @@
android:targetPackage="org.mozilla.fenix.debug"
android:targetClass="org.mozilla.fenix.IntentReceiverActivity" />
</shortcut>
-->
</shortcuts>
......@@ -7,15 +7,12 @@
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28"
tools:ignore="ScopedStorage"
/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CAMERA" />
<!-- This is needed because the android.permission.CAMERA above automatically
......@@ -32,9 +29,6 @@
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<!-- Needed for Google Play policy https://support.google.com/googleplay/android-developer/answer/6048248 -->
<uses-permission android:name="com.google.android.gms.permission.AD_ID"/>
<!-- Needed to prompt the user to give permission to install a downloaded apk -->
<uses-permission-sdk-23 android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
......@@ -131,6 +125,7 @@
android:exported="true"
android:configChanges="keyboard|keyboardHidden|mcc|mnc|orientation|screenSize|layoutDirection|smallestScreenSize|screenLayout"
android:launchMode="singleTask"
android:taskAffinity=""
android:resizeableActivity="true"
android:supportsPictureInPicture="true"
android:windowSoftInputMode="adjustResize">
......@@ -246,11 +241,11 @@
<data android:mimeType="application/xhtml+xml" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<!-- <intent-filter>-->
<!-- <action android:name="android.intent.action.SEND" />-->
<!-- <category android:name="android.intent.category.DEFAULT" />-->
<!-- <data android:mimeType="text/plain" />-->
<!-- </intent-filter>-->
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
......@@ -400,6 +395,7 @@
<service
android:name=".push.FirebasePushService"
android:enabled="false"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
......
......
......@@ -192,6 +192,10 @@ open class FenixApplication : LocaleAwareApplication(), Provider {
@VisibleForTesting
protected open fun initializeGlean() {
val telemetryEnabled = settings().isTelemetryEnabled
if (!telemetryEnabled) {
logger.debug("Preventing Glean from initializing, since telemetry is disabled")
return
}
logger.debug("Initializing Glean (uploadEnabled=$telemetryEnabled})")
......@@ -1053,9 +1057,7 @@ open class FenixApplication : LocaleAwareApplication(), Provider {
@OptIn(DelicateCoroutinesApi::class)
open fun downloadWallpapers() {
GlobalScope.launch {
components.useCases.wallpaperUseCases.initialize()
}
// IN TOR BROWSER: we don't download wallpapers.
}
/**
......
......
......@@ -251,7 +251,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
OpenSpecificTabIntentProcessor(this),
OpenPasswordManagerIntentProcessor(),
OpenRecentlyClosedIntentProcessor(),
ReEngagementIntentProcessor(this, settings()),
//ReEngagementIntentProcessor(this, settings()),
)
}
......
......
......@@ -161,7 +161,7 @@ import org.mozilla.fenix.browser.tabstrip.isTabStripEnabled
import org.mozilla.fenix.components.Components
import org.mozilla.fenix.components.FindInPageIntegration
import org.mozilla.fenix.components.StoreProvider
import org.mozilla.fenix.components.accounts.FxaWebChannelIntegration
// import org.mozilla.fenix.components.accounts.FxaWebChannelIntegration
import org.mozilla.fenix.components.appstate.AppAction
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.MicrosurveyAction
......@@ -308,7 +308,7 @@ abstract class BaseBrowserFragment :
private val sitePermissionsFeature = ViewBoundFeatureWrapper<SitePermissionsFeature>()
private val fullScreenFeature = ViewBoundFeatureWrapper<FullScreenFeature>()
private val swipeRefreshFeature = ViewBoundFeatureWrapper<SwipeRefreshFeature>()
private val webchannelIntegration = ViewBoundFeatureWrapper<FxaWebChannelIntegration>()
// private val webchannelIntegration = ViewBoundFeatureWrapper<FxaWebChannelIntegration>()
private val sitePermissionWifiIntegration =
ViewBoundFeatureWrapper<SitePermissionsWifiIntegration>()
private val secureWindowFeature = ViewBoundFeatureWrapper<SecureWindowFeature>()
......@@ -1181,6 +1181,7 @@ abstract class BaseBrowserFragment :
)
}
/*
webchannelIntegration.set(
feature = FxaWebChannelIntegration(
customTabSessionId = customTabSessionId,
......@@ -1193,6 +1194,7 @@ abstract class BaseBrowserFragment :
owner = this,
view = view,
)
*/
initializeEngineView(
topToolbarHeight = context.settings().getTopToolbarHeight(
......
......
......@@ -117,7 +117,7 @@ class Analytics(
appName = context.getString(R.string.app_name),
organizationName = "Mozilla",
),
enabled = true,
enabled = !isDataColectionDisabled(),
nonFatalCrashIntent = pendingIntent,
notificationsDelegate = context.components.notificationsDelegate,
useLegacyReporting = !context.settings().useNewCrashReporter,
......@@ -149,6 +149,7 @@ class Analytics(
}
}
fun isDataColectionDisabled() = BuildConfig.DATA_COLLECTION_DISABLED
private fun isSentryEnabled() = !BuildConfig.SENTRY_TOKEN.isNullOrEmpty()
private fun getSentryProjectUrl(): String? {
......
......
......@@ -59,13 +59,13 @@ import mozilla.components.feature.readerview.ReaderViewMiddleware
import mozilla.components.feature.recentlyclosed.RecentlyClosedMiddleware
import mozilla.components.feature.recentlyclosed.RecentlyClosedTabsStorage
import mozilla.components.feature.search.ext.createApplicationSearchEngine
import mozilla.components.feature.search.middleware.AdsTelemetryMiddleware
// import mozilla.components.feature.search.middleware.AdsTelemetryMiddleware
import mozilla.components.feature.search.middleware.SearchExtraParams
import mozilla.components.feature.search.middleware.SearchMiddleware
import mozilla.components.feature.search.region.RegionMiddleware
import mozilla.components.feature.search.telemetry.SerpTelemetryRepository
import mozilla.components.feature.search.telemetry.ads.AdsTelemetry
import mozilla.components.feature.search.telemetry.incontent.InContentTelemetry
// import mozilla.components.feature.search.telemetry.SerpTelemetryRepository
// import mozilla.components.feature.search.telemetry.ads.AdsTelemetry
// import mozilla.components.feature.search.telemetry.incontent.InContentTelemetry
import mozilla.components.feature.session.HistoryDelegate
import mozilla.components.feature.session.middleware.LastAccessMiddleware
import mozilla.components.feature.session.middleware.undo.UndoMiddleware
......@@ -172,7 +172,7 @@ class Core(
cookieBannerHandlingDetectOnlyMode = context.settings().shouldEnableCookieBannerDetectOnly,
cookieBannerHandlingGlobalRules = context.settings().shouldEnableCookieBannerGlobalRules,
cookieBannerHandlingGlobalRulesSubFrames = context.settings().shouldEnableCookieBannerGlobalRulesSubFrame,
emailTrackerBlockingPrivateBrowsing = true,
emailTrackerBlockingPrivateBrowsing = false,
userCharacteristicPingCurrentVersion = FxNimbus.features.userCharacteristics.value().currentVersion,
getDesktopMode = {
store.state.desktopMode
......@@ -332,7 +332,7 @@ class Core(
),
RecordingDevicesMiddleware(context, context.components.notificationsDelegate),
PromptMiddleware(),
AdsTelemetryMiddleware(adsTelemetry),
// AdsTelemetryMiddleware(adsTelemetry),
LastMediaAccessMiddleware(),
HistoryMetadataMiddleware(historyMetadataService),
SessionPrioritizationMiddleware(),
......@@ -368,6 +368,7 @@ class Core(
// Install the "icons" WebExtension to automatically load icons for every visited website.
icons.install(engine, this)
/*
CoroutineScope(Dispatchers.Main).launch {
val readJson = { context.assets.readJSONObject("search/search_telemetry_v2.json") }
val providerList = withContext(Dispatchers.IO) {
......@@ -387,6 +388,7 @@ class Core(
// Install the "cookies" WebExtension and tracks user interaction with SERPs.
searchTelemetry.install(engine, this@apply, providerList)
}
*/
WebNotificationFeature(
context,
......@@ -432,13 +434,13 @@ class Core(
context.components.analytics.metrics
}
val adsTelemetry by lazyMonitored {
AdsTelemetry()
}
// val adsTelemetry by lazyMonitored {
// AdsTelemetry()
// }
val searchTelemetry by lazyMonitored {
InContentTelemetry()
}
// val searchTelemetry by lazyMonitored {
// InContentTelemetry()
// }
/**
* Shortcut component for managing shortcuts on the device home screen.
......
......
......@@ -8,11 +8,6 @@ import android.app.Activity
import android.app.Application
import android.os.Bundle
import android.util.Log
import com.adjust.sdk.Adjust
import com.adjust.sdk.AdjustConfig
import com.adjust.sdk.AdjustEvent
import com.adjust.sdk.Constants.ADJUST_PREINSTALL_SYSTEM_PROPERTY_PATH
import com.adjust.sdk.LogLevel
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
......@@ -34,84 +29,16 @@ class AdjustMetricsService(
override val type = MetricServiceType.Marketing
override fun start() {
if ((BuildConfig.ADJUST_TOKEN.isNullOrBlank())) {
Log.i(LOGTAG, "No adjust token defined")
if (Config.channel.isReleased) {
throw IllegalStateException("No adjust token defined for release build")
}
return
}
System.setProperty(ADJUST_PREINSTALL_SYSTEM_PROPERTY_PATH, "/preload/etc/adjust.preinstall")
val config = AdjustConfig(
application,
BuildConfig.ADJUST_TOKEN,
AdjustConfig.ENVIRONMENT_PRODUCTION,
true,
)
config.setPreinstallTrackingEnabled(true)
val installationPing = FirstSessionPing(application, application.components.core.store)
FirstSession.adjustAttributionTimespan.start()
val timerId = FirstSession.adjustAttributionTime.start()
config.setOnAttributionChangedListener {
if (!installationPing.wasAlreadyTriggered()) {
FirstSession.adjustAttributionTimespan.stop()
}
FirstSession.adjustAttributionTime.stopAndAccumulate(timerId)
if (!it.network.isNullOrEmpty()) {
application.applicationContext.settings().adjustNetwork =
it.network
}
if (!it.adgroup.isNullOrEmpty()) {
application.applicationContext.settings().adjustAdGroup =
it.adgroup
}
if (!it.creative.isNullOrEmpty()) {
application.applicationContext.settings().adjustCreative =
it.creative
}
if (!it.campaign.isNullOrEmpty()) {
application.applicationContext.settings().adjustCampaignId =
it.campaign
}
installationPing.checkAndSend()
}
config.setLogLevel(LogLevel.SUPRESS)
Adjust.onCreate(config)
Adjust.setEnabled(true)
application.registerActivityLifecycleCallbacks(AdjustLifecycleCallbacks())
/* noop */
}
override fun stop() {
FirstSession.adjustAttributionTimespan.cancel()
Adjust.setEnabled(false)
Adjust.gdprForgetMe(application.applicationContext)
/* noop */
}
@Suppress("TooGenericExceptionCaught")
override fun track(event: Event) {
CoroutineScope(dispatcher).launch {
try {
if (event is Event.GrowthData) {
if (storage.shouldTrack(event)) {
Adjust.trackEvent(AdjustEvent(event.tokenName))
storage.updateSentState(event)
} else {
storage.updatePersistentState(event)
}
}
} catch (e: Exception) {
crashReporter.submitCaughtException(e)
}
}
/* noop */
}
override fun shouldTrack(event: Event): Boolean =
......@@ -123,11 +50,11 @@ class AdjustMetricsService(
private class AdjustLifecycleCallbacks : Application.ActivityLifecycleCallbacks {
override fun onActivityResumed(activity: Activity) {
Adjust.onResume()
/* noop */
}
override fun onActivityPaused(activity: Activity) {
Adjust.onPause()
/* noop */
}
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { /* noop */ }
......
......
......@@ -7,6 +7,7 @@ package org.mozilla.fenix.components.metrics
import android.content.Context
import mozilla.components.support.base.log.logger.Logger
import mozilla.telemetry.glean.Glean
import org.mozilla.fenix.BuildConfig
import org.mozilla.fenix.GleanMetrics.Pings
import org.mozilla.fenix.ext.components
......@@ -35,6 +36,9 @@ private class EventWrapper<T : Enum<T>>(
}
fun track(event: Event) {
if (BuildConfig.DATA_COLLECTION_DISABLED) {
return
}
val extras = if (keyMapper != null) {
event.extras?.mapKeys { (key) ->
keyMapper.invoke(key.toString().asCamelCase())
......@@ -68,6 +72,12 @@ class GleanMetricsService(
private val activationPing = ActivationPing(context)
override fun start() {
if (BuildConfig.DATA_COLLECTION_DISABLED) {
Logger.debug("Data collection is disabled, not initializing Glean.")
initialized = true
return
}
logger.debug("Enabling Glean.")
// Initialization of Glean already happened in FenixApplication.
Glean.setUploadEnabled(true)
......@@ -94,10 +104,12 @@ class GleanMetricsService(
}
override fun track(event: Event) {
if (!BuildConfig.DATA_COLLECTION_DISABLED) {
event.wrapper?.track(event)
}
}
override fun shouldTrack(event: Event): Boolean {
return event.wrapper != null
return !BuildConfig.DATA_COLLECTION_DISABLED && event.wrapper != null
}
}
......@@ -532,7 +532,8 @@ internal class ReleaseMetricController(
private fun isInitialized(type: MetricServiceType): Boolean = initialized.contains(type)
private fun isTelemetryEnabled(type: MetricServiceType): Boolean = when (type) {
private fun isTelemetryEnabled(type: MetricServiceType): Boolean =
!BuildConfig.DATA_COLLECTION_DISABLED && when (type) {
MetricServiceType.Data -> isDataTelemetryEnabled()
MetricServiceType.Marketing -> isMarketingDataTelemetryEnabled()
}
......
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment