@@ -27,32 +27,40 @@ import androidx.annotation.VisibleForTesting
2727import androidx.appcompat.app.AlertDialog
2828import androidx.core.content.pm.PackageInfoCompat
2929import androidx.webkit.WebViewCompat
30- import com.ichi2.anki.AnkiActivity
3130import com.ichi2.anki.CrashReportService
3231import com.ichi2.anki.R
32+ import com.ichi2.anki.utils.openUrl
3333import kotlinx.coroutines.Dispatchers
3434import kotlinx.coroutines.withContext
3535import timber.log.Timber
3636
37- internal const val OLDEST_WORKING_WEBVIEW_VERSION_CODE = 443000000L
38- internal const val OLDEST_WORKING_WEBVIEW_VERSION = 90
37+ /* * The Android package version code which corresponds to the Webview version. */
38+ internal const val OLDEST_WORKING_WEBVIEW_VERSION_CODE = 418306960L
39+
40+ /* * The minimum supported Webview version(Human readable). */
41+ internal const val OLDEST_WORKING_WEBVIEW_VERSION = 85
3942
4043/* *
4144 * Shows a dialog if the current WebView version is older than the last supported version.
4245 */
43- fun checkWebviewVersion (activity : AnkiActivity ): Boolean {
44- val userVisibleCode = getChromeLikeWebViewVersionIfOutdated(activity) ? : return false
46+
47+ context(context: Context )
48+ fun showDialogIfWebViewOutdated (
49+ minimumWebViewVersion : Int = OLDEST_WORKING_WEBVIEW_VERSION ,
50+ onOutdated : () -> Unit = {},
51+ ): Boolean {
52+ val userVisibleCode = getChromeLikeWebViewVersionIfOutdated(context, minimumWebViewVersion) ? : return false
4553
4654 // Provide guidance to the user if the WebView is outdated
47- val webviewPackageInfo = getAndroidSystemWebViewPackageInfo(activity.packageManager )
48- val legacyWebViewPackageInfo = getLegacyWebViewPackageInfo(activity .packageManager)
55+ val webviewPackageInfo = WebViewCompat .getCurrentWebViewPackage(context )
56+ val legacyWebViewPackageInfo = getLegacyWebViewPackageInfo(context .packageManager)
4957 // TODO modify the alert dialog text to handle the usage of developer builds for system WebView
5058 if (legacyWebViewPackageInfo != null ) {
5159 Timber .w(" WebView is outdated. %s: %s" , legacyWebViewPackageInfo.packageName, legacyWebViewPackageInfo.versionName)
52- showOutdatedWebViewDialog(activity , userVisibleCode, R .string.link_legacy_webview_update)
60+ showOutdatedWebViewDialog(context , userVisibleCode, R .string.link_legacy_webview_update, onOutdated )
5361 } else {
5462 Timber .w(" WebView is outdated. %s: %s" , webviewPackageInfo?.packageName, webviewPackageInfo?.versionName)
55- showOutdatedWebViewDialog(activity , userVisibleCode, R .string.link_webview_update)
63+ showOutdatedWebViewDialog(context , userVisibleCode, R .string.link_webview_update, onOutdated )
5664 }
5765 return true
5866}
@@ -78,16 +86,25 @@ fun getWebviewUserAgent(context: Context): String? {
7886 * Returns a Chrome-like WebView version if it is outdated, otherwise null if
7987 * cannot be determined at all or if okay
8088 */
81- private fun getChromeLikeWebViewVersionIfOutdated (activity : AnkiActivity ): Int? {
89+ private fun getChromeLikeWebViewVersionIfOutdated (
90+ context : Context ,
91+ minimumWebViewVersion : Int ,
92+ ): Int? {
8293 // If we cannot get the package information at all, return null
83- val webviewPackageInfo = getAndroidSystemWebViewPackageInfo(activity.packageManager ) ? : return null
94+ val webviewPackageInfo = WebViewCompat .getCurrentWebViewPackage(context ) ? : return null
8495 val webviewVersion =
8596 webviewPackageInfo.versionName ? : run {
8697 Timber .w(" Failed to obtain WebView version" )
8798 return null
8899 }
89100 val versionCode = PackageInfoCompat .getLongVersionCode(webviewPackageInfo)
90- return checkWebViewVersionComponents(webviewPackageInfo.packageName, webviewVersion, versionCode, getWebviewUserAgent(activity))
101+ return checkWebViewVersionComponents(
102+ webviewPackageInfo.packageName,
103+ webviewVersion,
104+ versionCode,
105+ getWebviewUserAgent(context),
106+ minimumWebViewVersion,
107+ )
91108}
92109
93110@VisibleForTesting
@@ -96,6 +113,7 @@ fun checkWebViewVersionComponents(
96113 webviewVersion : String ,
97114 versionCode : Long ,
98115 userAgent : String? ,
116+ minimumWebViewVersion : Int = OLDEST_WORKING_WEBVIEW_VERSION ,
99117): Int? {
100118 // Sometimes the webview version code appears too old, and the package name does as well,
101119 // but it's a webview that advertises modern capabilities via User-Agent in "Chrome" section
@@ -104,7 +122,7 @@ fun checkWebViewVersionComponents(
104122 val chromeRegex = """ Chrome/(\d+)""" .toRegex()
105123 val matchResult = chromeRegex.find(userAgent)?.groupValues?.get(1 )
106124 matchResult?.toInt()?.let {
107- if (it >= OLDEST_WORKING_WEBVIEW_VERSION ) {
125+ if (it >= minimumWebViewVersion ) {
108126 // If the User-Agent says we are modern, trust it and skip further checks.
109127 return null
110128 } else {
@@ -154,15 +172,17 @@ suspend fun getWebViewInfo(context: Context): WebViewInfo =
154172 }
155173
156174private fun showOutdatedWebViewDialog (
157- activity : AnkiActivity ,
175+ context : Context ,
158176 installedVersion : Int ,
159177 @StringRes learnMoreUrl : Int ,
178+ onDismiss : () -> Unit = {},
160179) {
161- AlertDialog .Builder (activity ).show {
162- setMessage(activity .getString(R .string.webview_update_message, installedVersion, OLDEST_WORKING_WEBVIEW_VERSION ))
180+ AlertDialog .Builder (context ).show {
181+ setMessage(context .getString(R .string.webview_update_message, installedVersion, OLDEST_WORKING_WEBVIEW_VERSION ))
163182 setPositiveButton(R .string.scoped_storage_learn_more) { _, _ ->
164- activity .openUrl(learnMoreUrl)
183+ context .openUrl(learnMoreUrl)
165184 }
185+ setOnDismissListener { onDismiss() }
166186 }
167187}
168188
@@ -173,26 +193,6 @@ private fun getLegacyWebViewPackageInfo(packageManager: PackageManager): Package
173193 null
174194 }
175195
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-
196196/* *
197197 * Enables debugging of web contents (HTML / CSS / JavaScript)
198198 * loaded into any WebViews of this application. This flag can be enabled
0 commit comments