Skip to content

Commit a13c3e2

Browse files
authored
Moved bloom filter binary to Play flavor (#1120)
* added a httpsdatapersister that does not persist embedded data for froid * more code cleanup * we don't need to duplicate so much code * fixed bloom filter test * spotless check * improved logging statements
1 parent 4738421 commit a13c3e2

File tree

13 files changed

+203
-47
lines changed

13 files changed

+203
-47
lines changed

app/src/androidTest/java/com/duckduckgo/app/integration/HttpsEmbeddedDataIntegrationTest.kt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import com.duckduckgo.app.httpsupgrade.api.HttpsFalsePositivesJsonAdapter
2828
import com.duckduckgo.app.httpsupgrade.store.HttpsDataPersister
2929
import com.duckduckgo.app.privacy.db.UserWhitelistDao
3030
import com.duckduckgo.app.statistics.pixels.Pixel
31+
import com.duckduckgo.httpsupgrade.store.PlayHttpsEmbeddedDataPersister
3132
import com.nhaarman.mockitokotlin2.mock
3233
import com.squareup.moshi.Moshi
3334
import org.junit.After
@@ -51,20 +52,21 @@ class HttpsEmbeddedDataIntegrationTest {
5152
db = Room.inMemoryDatabaseBuilder(context, AppDatabase::class.java)
5253
.allowMainThreadQueries()
5354
.build()
55+
5456
var httpsBloomSpecDao = db.httpsBloomFilterSpecDao()
5557
var httpsFalsePositivesDao = db.httpsFalsePositivesDao()
56-
var binaryDataStore: BinaryDataStore = BinaryDataStore(context)
58+
var binaryDataStore = BinaryDataStore(context)
5759

5860
val persister = HttpsDataPersister(
5961
binaryDataStore,
6062
httpsBloomSpecDao,
6163
httpsFalsePositivesDao,
62-
db,
63-
context,
64-
moshi
64+
db
6565
)
6666

67-
val factory = HttpsBloomFilterFactoryImpl(httpsBloomSpecDao, binaryDataStore, persister)
67+
var embeddedDataPersister = PlayHttpsEmbeddedDataPersister(persister, binaryDataStore, httpsBloomSpecDao, context, moshi)
68+
69+
val factory = HttpsBloomFilterFactoryImpl(httpsBloomSpecDao, binaryDataStore, embeddedDataPersister, persister)
6870
httpsUpgrader = HttpsUpgraderImpl(factory, httpsFalsePositivesDao, mockUserAllowlistDao, mockPixel)
6971
httpsUpgrader.reloadData()
7072
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (c) 2021 DuckDuckGo
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.duckduckgo.app.di
18+
19+
import com.duckduckgo.app.httpsupgrade.store.HttpsEmbeddedDataPersister
20+
import com.duckduckgo.httpsupgrade.store.FDroidHttpsEmbeddedDataPersister
21+
import dagger.Module
22+
import dagger.Provides
23+
24+
@Module
25+
class HttpsPersisterModule {
26+
27+
@Provides
28+
fun providesHttpsDataManager(): HttpsEmbeddedDataPersister {
29+
return FDroidHttpsEmbeddedDataPersister()
30+
}
31+
32+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (c) 2021 DuckDuckGo
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.duckduckgo.httpsupgrade.store
18+
19+
import com.duckduckgo.app.httpsupgrade.store.HttpsEmbeddedDataPersister
20+
import timber.log.Timber
21+
22+
class FDroidHttpsEmbeddedDataPersister : HttpsEmbeddedDataPersister {
23+
24+
override fun shouldPersistEmbeddedData(): Boolean {
25+
Timber.d("Ignoring, FDroid does not use embedded data due to binary data restrictions")
26+
return false
27+
}
28+
29+
override fun persistEmbeddedData() {
30+
Timber.d("Ignoring, FDroid does not use embedded data due to binary data restrictions")
31+
}
32+
}

app/src/main/java/com/duckduckgo/app/di/AppComponent.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ import javax.inject.Singleton
7878
StoreReferralModule::class,
7979
CoroutinesModule::class,
8080
CertificateTrustedStoreModule::class,
81-
WelcomePageModule::class
81+
WelcomePageModule::class,
82+
HttpsPersisterModule::class
8283
]
8384
)
8485
interface AppComponent : AndroidInjector<DuckDuckGoApplication> {

app/src/main/java/com/duckduckgo/app/httpsupgrade/HttpsBloomFilterFactory.kt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import androidx.annotation.WorkerThread
2020
import com.duckduckgo.app.global.store.BinaryDataStore
2121
import com.duckduckgo.app.httpsupgrade.model.HttpsBloomFilterSpec.Companion.HTTPS_BINARY_FILE
2222
import com.duckduckgo.app.httpsupgrade.store.HttpsBloomFilterSpecDao
23+
import com.duckduckgo.app.httpsupgrade.store.HttpsEmbeddedDataPersister
2324
import com.duckduckgo.app.httpsupgrade.store.HttpsDataPersister
2425
import timber.log.Timber
2526
import javax.inject.Inject
@@ -31,21 +32,22 @@ interface HttpsBloomFilterFactory {
3132
class HttpsBloomFilterFactoryImpl @Inject constructor(
3233
private val dao: HttpsBloomFilterSpecDao,
3334
private val binaryDataStore: BinaryDataStore,
34-
private val persister: HttpsDataPersister
35+
private val httpsEmbeddedDataPersister: HttpsEmbeddedDataPersister,
36+
private val httpsDataPersister: HttpsDataPersister
3537
) : HttpsBloomFilterFactory {
3638

3739
@WorkerThread
3840
override fun create(): BloomFilter? {
3941

40-
if (!persister.isPersisted()) {
42+
if (httpsEmbeddedDataPersister.shouldPersistEmbeddedData()) {
4143
Timber.d("Https update data not found, loading embedded data")
42-
persister.persistEmbeddedData()
44+
httpsEmbeddedDataPersister.persistEmbeddedData()
4345
}
4446

4547
val specification = dao.get()
4648
val dataPath = binaryDataStore.dataFilePath(HTTPS_BINARY_FILE)
47-
if (dataPath == null || specification == null || !persister.isPersisted(specification)) {
48-
Timber.d("Embedded https update data failed to load")
49+
if (dataPath == null || specification == null || !httpsDataPersister.isPersisted(specification)) {
50+
Timber.d("Https update data not available")
4951
return null
5052
}
5153

app/src/main/java/com/duckduckgo/app/httpsupgrade/di/HttpsUpgraderModule.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import com.duckduckgo.app.httpsupgrade.HttpsBloomFilterFactory
2323
import com.duckduckgo.app.httpsupgrade.HttpsBloomFilterFactoryImpl
2424
import com.duckduckgo.app.httpsupgrade.store.HttpsBloomFilterSpecDao
2525
import com.duckduckgo.app.httpsupgrade.store.HttpsDataPersister
26+
import com.duckduckgo.app.httpsupgrade.store.HttpsEmbeddedDataPersister
2627
import com.duckduckgo.app.httpsupgrade.store.HttpsFalsePositivesDao
2728
import com.duckduckgo.app.privacy.db.UserWhitelistDao
2829
import com.duckduckgo.app.statistics.pixels.Pixel
@@ -48,8 +49,9 @@ class HttpsUpgraderModule {
4849
fun bloomFilterFactory(
4950
specificationDao: HttpsBloomFilterSpecDao,
5051
binaryDataStore: BinaryDataStore,
51-
persister: HttpsDataPersister
52+
embeddedDataPersister: HttpsEmbeddedDataPersister,
53+
dataPersister: HttpsDataPersister
5254
): HttpsBloomFilterFactory {
53-
return HttpsBloomFilterFactoryImpl(specificationDao, binaryDataStore, persister)
55+
return HttpsBloomFilterFactoryImpl(specificationDao, binaryDataStore, embeddedDataPersister, dataPersister)
5456
}
5557
}
Lines changed: 9 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020 DuckDuckGo
2+
* Copyright (c) 2021 DuckDuckGo
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,15 +16,10 @@
1616

1717
package com.duckduckgo.app.httpsupgrade.store
1818

19-
import android.content.Context
20-
import com.duckduckgo.app.browser.R
2119
import com.duckduckgo.app.global.db.AppDatabase
2220
import com.duckduckgo.app.global.store.BinaryDataStore
2321
import com.duckduckgo.app.httpsupgrade.model.HttpsBloomFilterSpec
2422
import com.duckduckgo.app.httpsupgrade.model.HttpsFalsePositiveDomain
25-
import com.squareup.moshi.JsonAdapter
26-
import com.squareup.moshi.Moshi
27-
import com.squareup.moshi.Types
2823
import timber.log.Timber
2924
import java.io.IOException
3025
import javax.inject.Inject
@@ -33,11 +28,16 @@ class HttpsDataPersister @Inject constructor(
3328
private val binaryDataStore: BinaryDataStore,
3429
private val httpsBloomSpecDao: HttpsBloomFilterSpecDao,
3530
private val httpsFalsePositivesDao: HttpsFalsePositivesDao,
36-
private val appDatabase: AppDatabase,
37-
private val context: Context,
38-
private val moshi: Moshi
31+
private val appDatabase: AppDatabase
3932
) {
4033

34+
fun persistBloomFilter(specification: HttpsBloomFilterSpec, bytes: ByteArray, falsePositives: List<HttpsFalsePositiveDomain>) {
35+
appDatabase.runInTransaction {
36+
persistBloomFilter(specification, bytes)
37+
persistFalsePositives(falsePositives)
38+
}
39+
}
40+
4141
fun persistBloomFilter(specification: HttpsBloomFilterSpec, bytes: ByteArray) {
4242
if (!binaryDataStore.verifyCheckSum(bytes, specification.sha256)) {
4343
throw IOException("Https binary has incorrect sha, throwing away file")
@@ -50,36 +50,11 @@ class HttpsDataPersister @Inject constructor(
5050
}
5151
}
5252

53-
private fun persistBloomFilter(specification: HttpsBloomFilterSpec, bytes: ByteArray, falsePositives: List<HttpsFalsePositiveDomain>) {
54-
appDatabase.runInTransaction {
55-
persistBloomFilter(specification, bytes)
56-
persistFalsePositives(falsePositives)
57-
}
58-
}
59-
6053
fun persistFalsePositives(falsePositives: List<HttpsFalsePositiveDomain>) {
6154
httpsFalsePositivesDao.updateAll(falsePositives)
6255
}
6356

64-
fun persistEmbeddedData() {
65-
Timber.d("Updating https data from embedded files")
66-
val specJson = context.resources.openRawResource(R.raw.https_mobile_v2_bloom_spec).bufferedReader().use { it.readText() }
67-
val specAdapter = moshi.adapter(HttpsBloomFilterSpec::class.java)
68-
69-
val falsePositivesJson = context.resources.openRawResource(R.raw.https_mobile_v2_false_positives).bufferedReader().use { it.readText() }
70-
val falsePositivesType = Types.newParameterizedType(List::class.java, HttpsFalsePositiveDomain::class.java)
71-
val falsePositivesAdapter: JsonAdapter<List<HttpsFalsePositiveDomain>> = moshi.adapter(falsePositivesType)
72-
73-
val bytes = context.resources.openRawResource(R.raw.https_mobile_v2_bloom).use { it.readBytes() }
74-
persistBloomFilter(specAdapter.fromJson(specJson)!!, bytes, falsePositivesAdapter.fromJson(falsePositivesJson)!!)
75-
}
76-
7757
fun isPersisted(specification: HttpsBloomFilterSpec): Boolean {
7858
return specification == httpsBloomSpecDao.get() && binaryDataStore.verifyCheckSum(HttpsBloomFilterSpec.HTTPS_BINARY_FILE, specification.sha256)
7959
}
80-
81-
fun isPersisted(): Boolean {
82-
val specification = httpsBloomSpecDao.get() ?: return false
83-
return binaryDataStore.verifyCheckSum(HttpsBloomFilterSpec.HTTPS_BINARY_FILE, specification.sha256)
84-
}
8560
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright (c) 2021 DuckDuckGo
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.duckduckgo.app.httpsupgrade.store
18+
19+
interface HttpsEmbeddedDataPersister {
20+
21+
fun shouldPersistEmbeddedData(): Boolean
22+
23+
fun persistEmbeddedData()
24+
25+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright (c) 2021 DuckDuckGo
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.duckduckgo.app.di
18+
19+
import android.content.Context
20+
import com.duckduckgo.app.global.store.BinaryDataStore
21+
import com.duckduckgo.app.httpsupgrade.store.HttpsBloomFilterSpecDao
22+
import com.duckduckgo.app.httpsupgrade.store.HttpsDataPersister
23+
import com.duckduckgo.app.httpsupgrade.store.HttpsEmbeddedDataPersister
24+
import com.duckduckgo.httpsupgrade.store.PlayHttpsEmbeddedDataPersister
25+
import com.squareup.moshi.Moshi
26+
import dagger.Module
27+
import dagger.Provides
28+
29+
@Module
30+
class HttpsPersisterModule {
31+
32+
@Provides
33+
fun providesPlayHttpsEmbeddedDataPersister(
34+
httpsDataPersister: HttpsDataPersister,
35+
binaryDataStore: BinaryDataStore,
36+
httpsBloomSpecDao: HttpsBloomFilterSpecDao,
37+
context: Context,
38+
moshi: Moshi
39+
): HttpsEmbeddedDataPersister {
40+
return PlayHttpsEmbeddedDataPersister(httpsDataPersister, binaryDataStore, httpsBloomSpecDao, context, moshi)
41+
}
42+
43+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.duckduckgo.httpsupgrade.store
2+
3+
import android.content.Context
4+
import com.duckduckgo.app.browser.R
5+
import com.duckduckgo.app.global.store.BinaryDataStore
6+
import com.duckduckgo.app.httpsupgrade.model.HttpsBloomFilterSpec
7+
import com.duckduckgo.app.httpsupgrade.model.HttpsFalsePositiveDomain
8+
import com.duckduckgo.app.httpsupgrade.store.HttpsBloomFilterSpecDao
9+
import com.duckduckgo.app.httpsupgrade.store.HttpsDataPersister
10+
import com.duckduckgo.app.httpsupgrade.store.HttpsEmbeddedDataPersister
11+
import com.squareup.moshi.JsonAdapter
12+
import com.squareup.moshi.Moshi
13+
import com.squareup.moshi.Types
14+
import timber.log.Timber
15+
16+
class PlayHttpsEmbeddedDataPersister(
17+
private val httpsDataPersister: HttpsDataPersister,
18+
private val binaryDataStore: BinaryDataStore,
19+
private val httpsBloomSpecDao: HttpsBloomFilterSpecDao,
20+
private val context: Context,
21+
private val moshi: Moshi
22+
) : HttpsEmbeddedDataPersister {
23+
24+
override fun shouldPersistEmbeddedData(): Boolean {
25+
val specification = httpsBloomSpecDao.get() ?: return true
26+
return !binaryDataStore.verifyCheckSum(HttpsBloomFilterSpec.HTTPS_BINARY_FILE, specification.sha256)
27+
}
28+
29+
override fun persistEmbeddedData() {
30+
Timber.d("Updating https data from embedded files")
31+
val specJson = context.resources.openRawResource(R.raw.https_mobile_v2_bloom_spec).bufferedReader().use { it.readText() }
32+
val specAdapter = moshi.adapter(HttpsBloomFilterSpec::class.java)
33+
34+
val falsePositivesJson = context.resources.openRawResource(R.raw.https_mobile_v2_false_positives).bufferedReader().use { it.readText() }
35+
val falsePositivesType = Types.newParameterizedType(List::class.java, HttpsFalsePositiveDomain::class.java)
36+
val falsePositivesAdapter: JsonAdapter<List<HttpsFalsePositiveDomain>> = moshi.adapter(falsePositivesType)
37+
38+
val bytes = context.resources.openRawResource(R.raw.https_mobile_v2_bloom).use { it.readBytes() }
39+
httpsDataPersister.persistBloomFilter(specAdapter.fromJson(specJson)!!, bytes, falsePositivesAdapter.fromJson(falsePositivesJson)!!)
40+
}
41+
42+
}

0 commit comments

Comments
 (0)