Skip to content

Commit f8a8c1b

Browse files
authored
Check WebView capabilities when determining if bookmark import possible (#7037)
Task/Issue URL: https://app.asana.com/1/137249556945/project/488551667048375/task/1211794988737145?focus=true ### Description Adds WebView capability checks when determining if bookmark importing is possible ### Steps to test this PR ℹ️ QA optional - [ ] To test, run the app on a device with old `Webview` and tap on `Import Bookmarks` button inside `Bookmarks` activity. Verify it launches straight into the "old" flow to choose a file to import directly (no dialog, no offer to do the web flow)
1 parent abe79c5 commit f8a8c1b

File tree

3 files changed

+54
-2
lines changed

3 files changed

+54
-2
lines changed

autofill/autofill-impl/src/main/java/com/duckduckgo/autofill/impl/importing/ImportFromGoogleImpl.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,12 @@ class ImportFromGoogleImpl @Inject constructor(
3737
private val dispatchers: DispatcherProvider,
3838
private val globalActivityStarter: GlobalActivityStarter,
3939
private val context: Context,
40+
private val webViewCapabilityChecker: ImportGoogleBookmarksWebViewCapabilityChecker,
4041
) : ImportFromGoogle {
4142

4243
override suspend fun getBookmarksImportLaunchIntent(): Intent? {
4344
return withContext(dispatchers.io()) {
44-
if (autofillFeature.canImportBookmarksFromGoogleTakeout().isEnabled()) {
45+
if (autofillFeature.canImportBookmarksFromGoogleTakeout().isEnabled() && webViewCapabilityChecker.webViewCapableOfImporting()) {
4546
val launchSource = getLaunchSource()
4647
globalActivityStarter.startIntent(context, ImportBookmarksViaGoogleTakeoutScreen(launchSource))
4748
} else {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright (c) 2025 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.autofill.impl.importing
18+
19+
import com.duckduckgo.app.browser.api.WebViewCapabilityChecker
20+
import com.duckduckgo.app.browser.api.WebViewCapabilityChecker.WebViewCapability.DocumentStartJavaScript
21+
import com.duckduckgo.app.browser.api.WebViewCapabilityChecker.WebViewCapability.WebMessageListener
22+
import com.duckduckgo.di.scopes.AppScope
23+
import com.squareup.anvil.annotations.ContributesBinding
24+
import javax.inject.Inject
25+
26+
interface ImportGoogleBookmarksWebViewCapabilityChecker {
27+
suspend fun webViewCapableOfImporting(): Boolean
28+
}
29+
30+
@ContributesBinding(AppScope::class)
31+
class DefaultImportGoogleBookmarksWebViewCapabilityChecker @Inject constructor(
32+
private val webViewCapabilityChecker: WebViewCapabilityChecker,
33+
) : ImportGoogleBookmarksWebViewCapabilityChecker {
34+
35+
override suspend fun webViewCapableOfImporting(): Boolean {
36+
val webViewWebMessageSupport = webViewCapabilityChecker.isSupported(WebMessageListener)
37+
val webViewDocumentStartJavascript = webViewCapabilityChecker.isSupported(DocumentStartJavaScript)
38+
return webViewWebMessageSupport && webViewDocumentStartJavascript
39+
}
40+
}

autofill/autofill-impl/src/test/java/com/duckduckgo/autofill/impl/importing/ImportFromGoogleImplTest.kt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ class ImportFromGoogleImplTest {
5454

5555
private val globalActivityStarter: GlobalActivityStarter = mock()
5656

57+
private val webViewCapabilityChecker: ImportGoogleBookmarksWebViewCapabilityChecker = mock()
58+
5759
private val context: Context = mock()
5860

5961
private lateinit var testee: ImportFromGoogleImpl
@@ -65,6 +67,7 @@ class ImportFromGoogleImplTest {
6567
dispatchers = coroutinesTestRule.testDispatcherProvider,
6668
globalActivityStarter = globalActivityStarter,
6769
context = context,
70+
webViewCapabilityChecker = webViewCapabilityChecker,
6871
)
6972

7073
whenever(
@@ -82,11 +85,19 @@ class ImportFromGoogleImplTest {
8285
}
8386

8487
@Test
85-
fun `Launch intent is not null when feature is enabled`() = runTest {
88+
fun `Launch intent is not null when feature is enabled and WebView is capable`() = runTest {
8689
configureFeatureState(isEnabled = true)
90+
whenever(webViewCapabilityChecker.webViewCapableOfImporting()).thenReturn(true)
8791
assertNotNull(testee.getBookmarksImportLaunchIntent())
8892
}
8993

94+
@Test
95+
fun `Launch intent is null when feature is enabled but WebView is not capable`() = runTest {
96+
configureFeatureState(isEnabled = true)
97+
whenever(webViewCapabilityChecker.webViewCapableOfImporting()).thenReturn(false)
98+
assertNull(testee.getBookmarksImportLaunchIntent())
99+
}
100+
90101
@Test
91102
fun `parseResult returns UserCancelled when intent is null`() = runTest {
92103
val result = testee.parseResult(null)

0 commit comments

Comments
 (0)