... |
... |
@@ -8,8 +8,14 @@ package org.mozilla.fenix.components |
8
|
8
|
|
9
|
9
|
import android.os.StrictMode
|
10
|
10
|
import android.content.Context
|
|
11
|
+import kotlinx.coroutines.DelicateCoroutinesApi
|
|
12
|
+import kotlinx.coroutines.Dispatchers
|
|
13
|
+import kotlinx.coroutines.GlobalScope
|
|
14
|
+import kotlinx.coroutines.launch
|
|
15
|
+import kotlinx.coroutines.withContext
|
11
|
16
|
import mozilla.components.concept.engine.webextension.WebExtension
|
12
|
17
|
import mozilla.components.concept.engine.webextension.WebExtensionRuntime
|
|
18
|
+import mozilla.components.support.webextensions.WebExtensionSupport
|
13
|
19
|
import mozilla.components.support.base.log.logger.Logger
|
14
|
20
|
import org.mozilla.fenix.ext.components
|
15
|
21
|
import org.mozilla.fenix.ext.settings
|
... |
... |
@@ -66,47 +72,57 @@ object TorBrowserFeatures { |
66
|
72
|
onError = { _, throwable -> onError(throwable) })
|
67
|
73
|
}
|
68
|
74
|
|
69
|
|
- private fun installHTTPSEverywhere(
|
|
75
|
+ @OptIn(DelicateCoroutinesApi::class) // GlobalScope usage
|
|
76
|
+ private fun uninstallHTTPSEverywhere(
|
70
|
77
|
runtime: WebExtensionRuntime,
|
71
|
|
- onSuccess: ((WebExtension) -> Unit),
|
|
78
|
+ onSuccess: (() -> Unit),
|
72
|
79
|
onError: ((Throwable) -> Unit)
|
73
|
80
|
) {
|
74
|
|
- runtime.installWebExtension(
|
75
|
|
- id = "https-everywhere-eff@eff.org",
|
76
|
|
- url = "resource://android/assets/extensions/https-everywhere/",
|
77
|
|
- onSuccess = onSuccess,
|
78
|
|
- onError = { _, throwable -> onError(throwable) }
|
79
|
|
- )
|
|
81
|
+ // Wait for WebExtensionSupport on the I/O thread to avoid deadlocks.
|
|
82
|
+ GlobalScope.launch(Dispatchers.IO) {
|
|
83
|
+ WebExtensionSupport.awaitInitialization()
|
|
84
|
+ // Back to the main thread.
|
|
85
|
+ withContext(Dispatchers.Main) {
|
|
86
|
+ val extension =
|
|
87
|
+ WebExtensionSupport.installedExtensions["https-everywhere-eff@eff.org"]
|
|
88
|
+ ?: return@withContext onSuccess() // Fine, nothing to uninstall.
|
|
89
|
+ runtime.uninstallWebExtension(
|
|
90
|
+ extension,
|
|
91
|
+ onSuccess = onSuccess,
|
|
92
|
+ onError = { _, throwable -> onError(throwable) }
|
|
93
|
+ )
|
|
94
|
+ }
|
|
95
|
+ }
|
80
|
96
|
}
|
81
|
97
|
|
82
|
98
|
fun install(context: Context, runtime: WebExtensionRuntime) {
|
|
99
|
+ val settings = context.settings()
|
83
|
100
|
/**
|
84
|
|
- * Install HTTPS Everywhere as a builtin addon, with a resource://android/ URI.
|
85
|
|
- * No signatures will be checked/required and there will be no automatic
|
86
|
|
- * extension updates. It's ok to always try to install, since for builtin extensions it will
|
87
|
|
- * be checked internally whether it is necessary to install or not: it will only be done
|
88
|
|
- * if this is the first time or if it's a newer version.
|
|
101
|
+ * Remove HTTPS Everywhere if we didn't yet, unless HTTPS-Only is disabled, which might
|
|
102
|
+ * mean user opted out from the built-in mechanism and still relies on the extension.
|
89
|
103
|
*/
|
90
|
|
- installHTTPSEverywhere(
|
91
|
|
- runtime,
|
92
|
|
- onSuccess = {
|
93
|
|
- logger.debug("HTTPS Everywhere extension was installed successfully")
|
94
|
|
- },
|
95
|
|
- onError = { throwable ->
|
96
|
|
- logger.error("Could not install HTTPS Everywhere extension", throwable)
|
97
|
|
- }
|
98
|
|
- )
|
99
|
|
-
|
|
104
|
+ if (!settings.httpsEverywhereRemoved && settings.shouldUseHttpsOnly) {
|
|
105
|
+ uninstallHTTPSEverywhere(
|
|
106
|
+ runtime,
|
|
107
|
+ onSuccess = {
|
|
108
|
+ settings.httpsEverywhereRemoved = true
|
|
109
|
+ logger.debug("HTTPS Everywhere extension was uninstalled successfully")
|
|
110
|
+ },
|
|
111
|
+ onError = { throwable ->
|
|
112
|
+ logger.error("Could not uninstall HTTPS Everywhere extension", throwable)
|
|
113
|
+ }
|
|
114
|
+ )
|
|
115
|
+ }
|
100
|
116
|
/**
|
101
|
117
|
* Install NoScript as a user WebExtension if we have not already done so.
|
102
|
118
|
* AMO signature is checked, but automatic updates still need to be enabled.
|
103
|
119
|
*/
|
104
|
|
- if (!context.settings().noscriptInstalled) {
|
|
120
|
+ if (!settings.noscriptInstalled) {
|
105
|
121
|
installNoScript(
|
106
|
122
|
context,
|
107
|
123
|
runtime,
|
108
|
124
|
onSuccess = {
|
109
|
|
- context.settings().noscriptInstalled = true
|
|
125
|
+ settings.noscriptInstalled = true
|
110
|
126
|
logger.debug("NoScript extension was installed successfully")
|
111
|
127
|
},
|
112
|
128
|
onError = { throwable ->
|
... |
... |
@@ -123,7 +139,7 @@ object TorBrowserFeatures { |
123
|
139
|
* causing automatic update checks failures (components.addonUpdater being a lazy prop).
|
124
|
140
|
* The extension, from then on, should behave as if the user had installed it manually.
|
125
|
141
|
*/
|
126
|
|
- if (context.settings().noscriptUpdated == 0) {
|
|
142
|
+ if (settings.noscriptUpdated == 0) {
|
127
|
143
|
context.components.torController.registerTorListener(object : TorEvents {
|
128
|
144
|
override fun onTorConnected() {
|
129
|
145
|
context.components.torController.unregisterTorListener(this)
|
... |
... |
@@ -131,7 +147,7 @@ object TorBrowserFeatures { |
131
|
147
|
context.components.addonUpdater.registerForFutureUpdates(NOSCRIPT_ID)
|
132
|
148
|
// Force an immediate update check
|
133
|
149
|
context.components.addonUpdater.update(NOSCRIPT_ID)
|
134
|
|
- context.settings().noscriptUpdated = 1
|
|
150
|
+ settings.noscriptUpdated = 1
|
135
|
151
|
}
|
136
|
152
|
|
137
|
153
|
@SuppressWarnings("EmptyFunctionBlock")
|