This repository has been archived by the owner on Nov 1, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 473
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
For issue #3264 Add api for interacting with the tracking protection
exceptions.
- Loading branch information
Showing
16 changed files
with
1,176 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
130 changes: 130 additions & 0 deletions
130
...in/java/mozilla/components/browser/engine/gecko/TrackingProtectionExceptionFileStorage.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
/* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
|
||
package mozilla.components.browser.engine.gecko | ||
|
||
import android.content.Context | ||
import android.util.AtomicFile | ||
import androidx.annotation.VisibleForTesting | ||
import kotlinx.coroutines.CoroutineScope | ||
import kotlinx.coroutines.Dispatchers | ||
import kotlinx.coroutines.launch | ||
import mozilla.components.concept.engine.EngineSession | ||
import mozilla.components.concept.engine.content.blocking.TrackingProtectionExceptionStorage | ||
import mozilla.components.support.ktx.util.readAndDeserialize | ||
import mozilla.components.support.ktx.util.writeString | ||
import org.mozilla.geckoview.GeckoRuntime | ||
import java.io.File | ||
|
||
private const val STORE_FILE_NAME_FORMAT = | ||
"mozilla_components_tracking_protection_storage_gecko.json" | ||
|
||
/** | ||
* A [TrackingProtectionExceptionStorage] implementation to store tracking protection exceptions. | ||
*/ | ||
internal class TrackingProtectionExceptionFileStorage( | ||
private val context: Context, | ||
private val runtime: GeckoRuntime | ||
) : TrackingProtectionExceptionStorage { | ||
private val fileLock = Any() | ||
internal var scope = CoroutineScope(Dispatchers.IO) | ||
|
||
/** | ||
* Restore all exceptions from the [STORE_FILE_NAME_FORMAT] file, | ||
* and provides them to the gecko [runtime]. | ||
*/ | ||
override fun restore() { | ||
scope.launch { | ||
synchronized(fileLock) { | ||
getFile(context).readAndDeserialize { json -> | ||
if (json.isNotEmpty()) { | ||
val exceptionList = runtime.contentBlockingController.ExceptionList(json) | ||
runtime.contentBlockingController.restoreExceptionList(exceptionList) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
override fun contains(session: EngineSession, onFinish: (Boolean) -> Unit) { | ||
val geckoSession = (session as GeckoEngineSession).geckoSession | ||
runtime.contentBlockingController.checkException(geckoSession).accept { | ||
if (it != null) { | ||
onFinish(it) | ||
} else { | ||
onFinish(false) | ||
} | ||
} | ||
} | ||
|
||
override fun fetchAll(onFinish: (List<String>) -> Unit) { | ||
runtime.contentBlockingController.saveExceptionList().accept { exceptionList -> | ||
val exceptions = if (exceptionList != null) { | ||
val uris = exceptionList.uris.map { uri -> | ||
uri | ||
} | ||
uris | ||
} else { | ||
emptyList() | ||
} | ||
onFinish(exceptions) | ||
} | ||
} | ||
|
||
override fun add(session: EngineSession) { | ||
val geckoSession = (session as GeckoEngineSession).geckoSession | ||
runtime.contentBlockingController.addException(geckoSession) | ||
persist() | ||
} | ||
|
||
override fun remove(session: EngineSession) { | ||
val geckoSession = (session as GeckoEngineSession).geckoSession | ||
runtime.contentBlockingController.removeException(geckoSession) | ||
persist() | ||
} | ||
|
||
override fun removeAll() { | ||
runtime.contentBlockingController.clearExceptionList() | ||
removeFileFromDisk(context) | ||
} | ||
|
||
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) | ||
internal fun getFile(context: Context): AtomicFile { | ||
return AtomicFile( | ||
File( | ||
context.filesDir, | ||
STORE_FILE_NAME_FORMAT | ||
) | ||
) | ||
} | ||
|
||
/** | ||
* Take all the exception from the gecko [runtime] and saves them into the | ||
* [STORE_FILE_NAME_FORMAT] file. | ||
*/ | ||
private fun persist() { | ||
runtime.contentBlockingController.saveExceptionList().accept { exceptionList -> | ||
if (exceptionList != null) { | ||
scope.launch { | ||
synchronized(fileLock) { | ||
getFile(context).writeString { | ||
exceptionList.toJson().toString() | ||
} | ||
} | ||
} | ||
} else { | ||
removeFileFromDisk(context) | ||
} | ||
} | ||
} | ||
|
||
private fun removeFileFromDisk(context: Context) { | ||
scope.launch { | ||
synchronized(fileLock) { | ||
getFile(context) | ||
.delete() | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.