Skip to content

Commit b72fe8d

Browse files
committed
FF suspend version of writing favicon to disk
1 parent 4d21e97 commit b72fe8d

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

app/src/main/java/com/duckduckgo/app/browser/favicon/FaviconPersister.kt

+47-1
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,14 @@ import android.content.Context
2020
import android.graphics.Bitmap
2121
import android.graphics.BitmapFactory
2222
import com.duckduckgo.app.global.file.FileDeleter
23+
import com.duckduckgo.app.pixels.remoteconfig.AndroidBrowserConfigFeature
2324
import com.duckduckgo.common.utils.DispatcherProvider
2425
import com.duckduckgo.common.utils.sha256
2526
import java.io.File
2627
import java.io.FileOutputStream
2728
import kotlinx.coroutines.NonCancellable
29+
import kotlinx.coroutines.sync.Mutex
30+
import kotlinx.coroutines.sync.withLock
2831
import kotlinx.coroutines.withContext
2932
import timber.log.Timber
3033

@@ -62,8 +65,11 @@ class FileBasedFaviconPersister(
6265
val context: Context,
6366
private val fileDeleter: FileDeleter,
6467
private val dispatcherProvider: DispatcherProvider,
68+
private val androidBrowserConfigFeature: AndroidBrowserConfigFeature,
6569
) : FaviconPersister {
6670

71+
val mutex = Mutex()
72+
6773
override suspend fun deleteAll(directory: String) {
6874
fileDeleter.deleteDirectory(faviconDirectory(directory))
6975
}
@@ -100,7 +106,11 @@ class FileBasedFaviconPersister(
100106
domain: String,
101107
): File? {
102108
return withContext(dispatcherProvider.io() + NonCancellable) {
103-
writeToDisk(directory, subFolder, bitmap, domain)
109+
if (androidBrowserConfigFeature.storeFaviconSuspend().isEnabled()) {
110+
writeToDiskAsync(directory, subFolder, bitmap, domain)
111+
} else {
112+
writeToDisk(directory, subFolder, bitmap, domain)
113+
}
104114
}
105115
}
106116

@@ -181,6 +191,42 @@ class FileBasedFaviconPersister(
181191
}
182192
}
183193

194+
private suspend fun writeToDiskAsync(
195+
directory: String,
196+
subFolder: String,
197+
bitmap: Bitmap,
198+
domain: String,
199+
): File? {
200+
mutex.withLock {
201+
val existingFile = fileForFavicon(directory, subFolder, domain)
202+
203+
if (existingFile.exists()) {
204+
Timber.i("Favicon favicon exists for $domain in $subFolder")
205+
val existingFavicon = BitmapFactory.decodeFile(existingFile.absolutePath)
206+
207+
existingFavicon?.let {
208+
if (it.width > bitmap.width) {
209+
return null // Stored file has better quality
210+
}
211+
}
212+
}
213+
214+
val faviconFile = prepareDestinationFile(directory, subFolder, domain)
215+
runCatching {
216+
FileOutputStream(faviconFile).use { outputStream ->
217+
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream)
218+
outputStream.flush()
219+
}
220+
}
221+
222+
return if (faviconFile.exists()) {
223+
faviconFile
224+
} else {
225+
null
226+
}
227+
}
228+
}
229+
184230
@Synchronized
185231
private fun writeBytesToFile(
186232
file: File,

app/src/main/java/com/duckduckgo/app/pixels/remoteconfig/AndroidBrowserConfigFeature.kt

+3
Original file line numberDiff line numberDiff line change
@@ -118,4 +118,7 @@ interface AndroidBrowserConfigFeature {
118118
*/
119119
@Toggle.DefaultValue(false)
120120
fun omnibarAnimation(): Toggle
121+
122+
@Toggle.DefaultValue(true)
123+
fun storeFaviconSuspend(): Toggle
121124
}

0 commit comments

Comments
 (0)