Skip to content

Commit effcf66

Browse files
committed
fix:add test case for huawei and implement the correct fix
1 parent 5de9e67 commit effcf66

5 files changed

Lines changed: 35 additions & 51 deletions

File tree

AnkiDroid/src/main/java/com/ichi2/anki/pages/AnkiPackageImporterFragment.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,15 @@ import com.ichi2.anki.CollectionManager
2525
import com.ichi2.anki.R
2626
import com.ichi2.anki.SingleFragmentActivity
2727
import com.ichi2.anki.hideShowButtonCss
28+
import com.ichi2.utils.OLDEST_WORKING_WEBVIEW_VERSION
2829

2930
class AnkiPackageImporterFragment : PageFragment() {
3031
override val pagePath: String by lazy {
3132
val filePath = requireArguments().getString(KEY_FILE_PATH)
3233
"import-anki-package$filePath"
3334
}
3435

35-
override fun requiresModernWebView() = true
36+
override val minimumWebViewVersion: Int = OLDEST_WORKING_WEBVIEW_VERSION
3637

3738
override fun onCreateWebViewClient(savedInstanceState: Bundle?): PageWebViewClient {
3839
// the back callback is only enabled when import is running and showing progress

AnkiDroid/src/main/java/com/ichi2/anki/pages/CsvImporter.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import com.ichi2.anki.CollectionManager
2727
import com.ichi2.anki.R
2828
import com.ichi2.anki.SingleFragmentActivity
2929
import com.ichi2.anki.hideShowButtonCss
30+
import com.ichi2.utils.OLDEST_WORKING_WEBVIEW_VERSION
3031

3132
/**
3233
* Anki page used to import text/csv files
@@ -37,7 +38,7 @@ class CsvImporter : PageFragment() {
3738
"import-csv$filePath"
3839
}
3940

40-
override fun requiresModernWebView() = true
41+
override val minimumWebViewVersion: Int = OLDEST_WORKING_WEBVIEW_VERSION
4142

4243
override fun onCreateWebViewClient(savedInstanceState: Bundle?): PageWebViewClient {
4344
// the back callback is only enabled when import is running and showing progress

AnkiDroid/src/main/java/com/ichi2/anki/pages/PageFragment.kt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ abstract class PageFragment(
6666

6767
protected open fun onWebViewCreated() { }
6868

69-
protected open fun requiresModernWebView(): Boolean = false
69+
protected open val minimumWebViewVersion: Int? = null
7070

7171
/**
7272
* When the webview calls `BridgeCommand("foo")`, the PageFragment execute `bridgeCommands["foo"]`.
@@ -106,13 +106,14 @@ abstract class PageFragment(
106106
savedInstanceState: Bundle?,
107107
) {
108108
val ankiActivity = requireActivity() as AnkiActivity
109-
if (requiresModernWebView() && checkWebviewVersion(ankiActivity)) {
109+
server = AnkiServer(this).also { it.start() }
110+
webViewLayout = view.findViewById(R.id.webview_layout)
111+
112+
val minVersion = minimumWebViewVersion
113+
if (minVersion != null && checkWebviewVersion(ankiActivity, minVersion)) {
110114
Timber.w("${this::class.simpleName} requires modern WebView (Chrome 90+), aborting load")
111-
ankiActivity.onBackPressedDispatcher.onBackPressed()
112115
return
113116
}
114-
server = AnkiServer(this).also { it.start() }
115-
webViewLayout = view.findViewById(R.id.webview_layout)
116117

117118
view.findViewById<MaterialToolbar>(R.id.toolbar)?.setNavigationOnClickListener {
118119
requireActivity().onBackPressedDispatcher.onBackPressed()

AnkiDroid/src/main/java/com/ichi2/utils/WebViewUtils.kt

Lines changed: 22 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,20 @@ import kotlinx.coroutines.Dispatchers
3434
import kotlinx.coroutines.withContext
3535
import timber.log.Timber
3636

37-
internal const val OLDEST_WORKING_WEBVIEW_VERSION_CODE = 443000000L
38-
internal const val OLDEST_WORKING_WEBVIEW_VERSION = 90
37+
internal const val OLDEST_WORKING_WEBVIEW_VERSION_CODE = 418306960L
38+
internal const val OLDEST_WORKING_WEBVIEW_VERSION = 85
3939

4040
/**
4141
* Shows a dialog if the current WebView version is older than the last supported version.
4242
*/
43-
fun checkWebviewVersion(activity: AnkiActivity): Boolean {
44-
val userVisibleCode = getChromeLikeWebViewVersionIfOutdated(activity) ?: return false
43+
fun checkWebviewVersion(
44+
activity: AnkiActivity,
45+
minimumWebViewVersion: Int = OLDEST_WORKING_WEBVIEW_VERSION,
46+
): Boolean {
47+
val userVisibleCode = getChromeLikeWebViewVersionIfOutdated(activity, minimumWebViewVersion) ?: return false
4548

4649
// Provide guidance to the user if the WebView is outdated
47-
val webviewPackageInfo = getAndroidSystemWebViewPackageInfo(activity.packageManager)
50+
val webviewPackageInfo = WebViewCompat.getCurrentWebViewPackage(activity)
4851
val legacyWebViewPackageInfo = getLegacyWebViewPackageInfo(activity.packageManager)
4952
// TODO modify the alert dialog text to handle the usage of developer builds for system WebView
5053
if (legacyWebViewPackageInfo != null) {
@@ -78,16 +81,25 @@ fun getWebviewUserAgent(context: Context): String? {
7881
* Returns a Chrome-like WebView version if it is outdated, otherwise null if
7982
* cannot be determined at all or if okay
8083
*/
81-
private fun getChromeLikeWebViewVersionIfOutdated(activity: AnkiActivity): Int? {
84+
private fun getChromeLikeWebViewVersionIfOutdated(
85+
activity: AnkiActivity,
86+
minimumWebViewVersion: Int,
87+
): Int? {
8288
// If we cannot get the package information at all, return null
83-
val webviewPackageInfo = getAndroidSystemWebViewPackageInfo(activity.packageManager) ?: return null
89+
val webviewPackageInfo = WebViewCompat.getCurrentWebViewPackage(activity) ?: return null
8490
val webviewVersion =
8591
webviewPackageInfo.versionName ?: run {
8692
Timber.w("Failed to obtain WebView version")
8793
return null
8894
}
8995
val versionCode = PackageInfoCompat.getLongVersionCode(webviewPackageInfo)
90-
return checkWebViewVersionComponents(webviewPackageInfo.packageName, webviewVersion, versionCode, getWebviewUserAgent(activity))
96+
return checkWebViewVersionComponents(
97+
webviewPackageInfo.packageName,
98+
webviewVersion,
99+
versionCode,
100+
getWebviewUserAgent(activity),
101+
minimumWebViewVersion,
102+
)
91103
}
92104

93105
@VisibleForTesting
@@ -96,6 +108,7 @@ fun checkWebViewVersionComponents(
96108
webviewVersion: String,
97109
versionCode: Long,
98110
userAgent: String?,
111+
minimumWebViewVersion: Int = OLDEST_WORKING_WEBVIEW_VERSION,
99112
): Int? {
100113
// Sometimes the webview version code appears too old, and the package name does as well,
101114
// but it's a webview that advertises modern capabilities via User-Agent in "Chrome" section
@@ -104,7 +117,7 @@ fun checkWebViewVersionComponents(
104117
val chromeRegex = """Chrome/(\d+)""".toRegex()
105118
val matchResult = chromeRegex.find(userAgent)?.groupValues?.get(1)
106119
matchResult?.toInt()?.let {
107-
if (it >= OLDEST_WORKING_WEBVIEW_VERSION) {
120+
if (it >= minimumWebViewVersion) {
108121
// If the User-Agent says we are modern, trust it and skip further checks.
109122
return null
110123
} else {
@@ -173,26 +186,6 @@ private fun getLegacyWebViewPackageInfo(packageManager: PackageManager): Package
173186
null
174187
}
175188

176-
/**
177-
* Returns a [PackageInfo] from the current system WebView, or `null` if unavailable
178-
*/
179-
private fun getAndroidSystemWebViewPackageInfo(packageManager: PackageManager): PackageInfo? {
180-
fun getPackage(packageName: String): PackageInfo? =
181-
try {
182-
packageManager.getPackageInfo(packageName, 0)
183-
} catch (_: PackageManager.NameNotFoundException) {
184-
null
185-
}
186-
187-
// The WebView is called com.android.webview by default.
188-
// Partner devices which ship with Google applications ship the Google-specific version
189-
// of the WebView called com.google.android.webview.
190-
// https://issues.chromium.org/issues/40419837#comment10
191-
192-
return getPackage("com.google.android.webview")
193-
?: getPackage("com.android.webview") // com.android.webview is used on API 24
194-
}
195-
196189
/**
197190
* Enables debugging of web contents (HTML / CSS / JavaScript)
198191
* loaded into any WebViews of this application. This flag can be enabled

AnkiDroid/src/test/java/com/ichi2/utils/WebViewUtilsTest.kt

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -56,26 +56,14 @@ class WebViewUtilsTest {
5656
equalTo(null),
5757
)
5858
assertThat(
59-
"Should catch old engine (78) in Huawei package even with valid versionCode",
59+
"Known old huawei webview determined correctly",
6060
checkWebViewVersionComponents(
6161
"com.huawei.webview",
62-
"12.1.2.322",
63-
450000000L,
62+
"unknown",
63+
356L,
6464
"Mozilla/5.0 (Linux; Android 10; CDY-AN90 Build/HUAWEICDY-AN90; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Mobile Safari/537.36",
6565
),
6666
equalTo(78),
6767
)
68-
// Link: https://www.apkmirror.com/apk/huawei/huawei-webview-2/huawei-webview-15-0-4-326-release/
69-
// verified version code is 2113L for 15.0.4.326 by analyzing the manifest
70-
assertThat(
71-
"Huawei v15 with code 21311 should be allowed if UA indicates modern engine (114)",
72-
checkWebViewVersionComponents(
73-
"com.huawei.webview",
74-
"15.0.4.326",
75-
21311L,
76-
"Mozilla/5.0 (Linux; Android 12; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.196 Mobile Safari/537.36",
77-
),
78-
equalTo(null),
79-
)
8068
}
8169
}

0 commit comments

Comments
 (0)