@@ -63,7 +63,7 @@ interface MaliciousSiteBlockerWebViewIntegration {
63
63
confirmationCallback : (maliciousStatus: MaliciousStatus ) -> Unit ,
64
64
): IsMaliciousViewData
65
65
66
- fun onPageLoadStarted ()
66
+ fun onPageLoadStarted (url : String )
67
67
68
68
fun onSiteExempted (
69
69
url : Uri ,
@@ -103,7 +103,7 @@ class RealMaliciousSiteBlockerWebViewIntegration @Inject constructor(
103
103
) : MaliciousSiteBlockerWebViewIntegration, PrivacyConfigCallbackPlugin {
104
104
105
105
@VisibleForTesting(otherwise = VisibleForTesting .PRIVATE )
106
- val processedUrls = mutableListOf <String >()
106
+ val processedUrls = mutableMapOf <String , MaliciousStatus >()
107
107
108
108
private var isFeatureEnabled = false
109
109
private val isSettingEnabled: Boolean
@@ -140,6 +140,9 @@ class RealMaliciousSiteBlockerWebViewIntegration @Inject constructor(
140
140
if (! isEnabled()) {
141
141
return IsMaliciousViewData .Safe
142
142
}
143
+
144
+ Timber .d(" shouldIntercept ${request.url} " )
145
+
143
146
val url = request.url.let {
144
147
if (it.fragment != null ) {
145
148
it.buildUpon().fragment(null ).build()
@@ -150,19 +153,22 @@ class RealMaliciousSiteBlockerWebViewIntegration @Inject constructor(
150
153
151
154
val decodedUrl = URLDecoder .decode(url.toString(), " UTF-8" ).lowercase()
152
155
153
- if (processedUrls.contains(decodedUrl)) {
154
- processedUrls.remove(decodedUrl)
155
- Timber .tag(" PhishingAndMalwareDetector" ).d(" Already intercepted, skipping $decodedUrl " )
156
- return IsMaliciousViewData .Safe
157
- }
158
-
159
156
val exemptedUrl = exemptedUrlsHolder.exemptedMaliciousUrls.firstOrNull { it.url.toString() == decodedUrl }
160
157
161
158
if (exemptedUrl != null ) {
162
- Timber .tag( " MaliciousSiteDetector " ). d(" Previously exempted, skipping $decodedUrl as ${exemptedUrl.feed} " )
159
+ Timber .d(" Previously exempted, skipping $decodedUrl as ${exemptedUrl.feed} " )
163
160
return IsMaliciousViewData .MaliciousSite (url, exemptedUrl.feed, true )
164
161
}
165
162
163
+ processedUrls[decodedUrl]?.let {
164
+ processedUrls.remove(decodedUrl)
165
+ Timber .d(" Already intercepted, skipping $decodedUrl , status: $it " )
166
+ return when (it) {
167
+ is Safe -> IsMaliciousViewData .Safe
168
+ is Malicious -> IsMaliciousViewData .MaliciousSite (url, it.feed, false )
169
+ }
170
+ }
171
+
166
172
val belongsToCurrentPage = documentUri?.host == request.requestHeaders[" Referer" ]?.toUri()?.host
167
173
val isForIframe = isForIframe(request) && belongsToCurrentPage
168
174
if (request.isForMainFrame || isForIframe) {
@@ -174,6 +180,7 @@ class RealMaliciousSiteBlockerWebViewIntegration @Inject constructor(
174
180
}
175
181
when (result) {
176
182
is ConfirmedResult -> {
183
+ processedUrls[decodedUrl] = result.status
177
184
when (val status = result.status) {
178
185
is Malicious -> {
179
186
if (isForIframe) {
@@ -183,14 +190,12 @@ class RealMaliciousSiteBlockerWebViewIntegration @Inject constructor(
183
190
}
184
191
185
192
is Safe -> {
186
- processedUrls.add(decodedUrl)
187
193
return IsMaliciousViewData .Safe
188
194
}
189
195
}
190
196
}
191
197
192
198
is WaitForConfirmation -> {
193
- processedUrls.add(decodedUrl)
194
199
return IsMaliciousViewData .WaitForConfirmation
195
200
}
196
201
}
@@ -207,21 +212,25 @@ class RealMaliciousSiteBlockerWebViewIntegration @Inject constructor(
207
212
if (! isEnabled()) {
208
213
return @runBlocking IsMaliciousViewData .Safe
209
214
}
215
+ Timber .d(" shouldOverrideUrlLoading $url " )
210
216
val decodedUrl = URLDecoder .decode(url.toString(), " UTF-8" ).lowercase()
211
217
212
- if (processedUrls.contains(decodedUrl)) {
213
- processedUrls.remove(decodedUrl)
214
- Timber .tag(" PhishingAndMalwareDetector" ).d(" Already intercepted, skipping $decodedUrl " )
215
- return @runBlocking IsMaliciousViewData .Safe
216
- }
217
-
218
218
val exemptedUrl = exemptedUrlsHolder.exemptedMaliciousUrls.firstOrNull { it.url.toString() == decodedUrl }
219
219
220
220
if (exemptedUrl != null ) {
221
- Timber .tag( " MaliciousSiteDetector " ). d(" Previously exempted, skipping $decodedUrl " )
221
+ Timber .d(" Previously exempted, skipping $decodedUrl " )
222
222
return @runBlocking IsMaliciousViewData .MaliciousSite (url, exemptedUrl.feed, true )
223
223
}
224
224
225
+ processedUrls[decodedUrl]?.let {
226
+ processedUrls.remove(decodedUrl)
227
+ Timber .d(" Already intercepted, skipping $decodedUrl , status: $it " )
228
+ return @runBlocking when (it) {
229
+ is Safe -> IsMaliciousViewData .Safe
230
+ is Malicious -> IsMaliciousViewData .MaliciousSite (url, it.feed, false )
231
+ }
232
+ }
233
+
225
234
// iframes always go through the shouldIntercept method, so we only need to check the main frame here
226
235
if (isForMainFrame) {
227
236
when (val result = checkMaliciousUrl(decodedUrl, confirmationCallback)) {
@@ -231,13 +240,12 @@ class RealMaliciousSiteBlockerWebViewIntegration @Inject constructor(
231
240
return @runBlocking IsMaliciousViewData .MaliciousSite (url, status.feed, false )
232
241
}
233
242
is Safe -> {
234
- processedUrls.add( decodedUrl)
243
+ processedUrls[ decodedUrl] = Safe
235
244
return @runBlocking IsMaliciousViewData .Safe
236
245
}
237
246
}
238
247
}
239
248
is WaitForConfirmation -> {
240
- processedUrls.add(decodedUrl)
241
249
return @runBlocking IsMaliciousViewData .WaitForConfirmation
242
250
}
243
251
}
@@ -262,7 +270,7 @@ class RealMaliciousSiteBlockerWebViewIntegration @Inject constructor(
262
270
} else {
263
271
Safe
264
272
}
265
- processedUrls.clear()
273
+ processedUrls[url] = isMalicious
266
274
confirmationCallback(isMalicious)
267
275
}
268
276
}
@@ -276,8 +284,15 @@ class RealMaliciousSiteBlockerWebViewIntegration @Inject constructor(
276
284
return isFeatureEnabled && isSettingEnabled
277
285
}
278
286
279
- override fun onPageLoadStarted () {
280
- processedUrls.clear()
287
+ override fun onPageLoadStarted (url : String ) {
288
+ val convertedUrl = URLDecoder .decode(url, " UTF-8" ).lowercase()
289
+ /* onPageLoadStarted is often called after shouldOverride/shouldIntercept, therefore, if the URL
290
+ * is already stored, we don't clear the processedUrls map to avoid re-checking the URL for the same
291
+ * page load.
292
+ */
293
+ if (! processedUrls.contains(convertedUrl)) {
294
+ processedUrls.clear()
295
+ }
281
296
}
282
297
283
298
override fun onSiteExempted (
@@ -286,8 +301,6 @@ class RealMaliciousSiteBlockerWebViewIntegration @Inject constructor(
286
301
) {
287
302
val convertedUrl = URLDecoder .decode(url.toString(), " UTF-8" ).lowercase()
288
303
exemptedUrlsHolder.addExemptedMaliciousUrl(ExemptedUrl (convertedUrl.toUri(), feed))
289
- Timber .tag(" MaliciousSiteDetector" ).d(
290
- " Added $url to exemptedUrls, contents: ${exemptedUrlsHolder.exemptedMaliciousUrls} " ,
291
- )
304
+ Timber .d(" Added $url to exemptedUrls" )
292
305
}
293
306
}
0 commit comments