Skip to content

Fix 22091 shared decks safewebview - #22691

Merged
mikehardy merged 2 commits into
ankidroid:mainfrom
Ratnesh5:fix-22091-shared-decks-safewebview
Nov 3, 2026
Merged

mikehardy merged 2 commits into
ankidroid:mainfrom
Ratnesh5:fix-22091-shared-decks-safewebview

Conversation

@Ratnesh5

@Ratnesh5 Ratnesh5 commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Note

Assisted-by: Claude Sonnet

Purpose / Description

Migrates SharedDecksActivity to use SafeWebViewLayout to address [MissingOnRenderProcessGone] from #22091.

  • Adds clearHistory() and setDownloadListener() delegates to SafeWebViewLayout.
  • Implements OnWebViewRecreatedListener on SharedDecksActivity to re-apply WebView settings and reload the URL on recovery.
  • Replaces SharedDeckWebViewClient base class with SafeWebViewClient and teardown with binding.webView.safeDestroy().
  • Adds unit tests to SharedDecksActivityTest covering render process crash recovery and destroy cleanup.

Fixes

Approach

  1. Updated activity_shared_decks.xml to use SafeWebViewLayout.
  2. Implemented OnWebViewRecreatedListener in SharedDecksActivity.kt.
  3. Added delegates clearHistory() and setDownloadListener(...) in SafeWebViewLayout.kt.
  4. Added unit tests for crash recovery and destruction in SharedDecksActivityTest.kt.

How Has This Been Tested?

  • :AnkiDroid:testPlayDebugUnitTest --tests com.ichi2.anki.shareddeck.SharedDecksActivityTest (all 4 passed)
  • :AnkiDroid:testPlayDebugUnitTest --tests com.ichi2.anki.workarounds.SafeWebViewLayoutTest (all 9 passed)
  • ktlintMainSourceSetCheck & ktlintTestSourceSetCheck (all passed)

Checklist

Please, go through these checks before submitting the PR.

  • You have a descriptive commit message with a short title (first line, max 50 chars).
  • You have commented your code, particularly in hard-to-understand areas
  • You have performed a self-review of your own code
  • UI changes: include screenshots of all affected screens (in particular showing any new or changed strings)
  • UI Changes: You have tested your change using the Google Accessibility Scanner

@Ratnesh5
Ratnesh5 force-pushed the fix-22091-shared-decks-safewebview branch from 1642556 to f04626c Compare October 22, 2026 10:06
@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Snapshot diff report: Previous regressions were resolved by the latest commit.

@mikehardy mikehardy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assisted-by: prep verification (near-frontier withheld — unit red on act SHA)

Thanks for the shared-decks SafeWebView work.

Checked out the PR branch and rebased cleanly onto current ankidroid/main without pushing. On LOCAL_TIP 6c3fa6c18188ed74c7cde9a1a6f97729b634abab (act SHA remains PRE_TIP f04626c507f25c777c06982ba08cb08ecfe20646): ./gradlew -p buildSrc test, lintAll / ktlintCheck / lint-rules:test, and jacocoUnitTestReport on emulator-5554 / API36_GAPI_PS16K (cold-boot). Lint passed; unit failed.

SharedDecksDownloadFragmentTest.rate limited download with an AnkiDroid login redirects the WebView to the login page fails with ClassCastException: com.ichi2.anki.SafeWebViewLayout cannot be cast to android.webkit.WebView at SharedDecksDownloadFragmentTest.kt:384. The same test is red on all three GitHub JUnit jobs for this tip. Solo rerun of that test on current main passes, so this looks PR-caused after swapping the activity layout to SafeWebViewLayout.

Please update the fragment test (and any WebView-typed lookup) to match the new container, or expose the embedded WebView the way SharedDecksActivityTest already does. I am not approving while unit CI is red on this SHA.

@mikehardy mikehardy added Needs Author Reply Waiting for a reply from the original author and removed Needs Review labels Oct 22, 2026
@Ratnesh5
Ratnesh5 force-pushed the fix-22091-shared-decks-safewebview branch from f04626c to 28d3e3c Compare October 22, 2026 16:52
@david-allison david-allison removed the Needs Author Reply Waiting for a reply from the original author label Oct 23, 2026
@mikehardy
mikehardy force-pushed the fix-22091-shared-decks-safewebview branch from 28d3e3c to e77fb98 Compare October 24, 2026 13:42
@mikehardy

Copy link
Copy Markdown
Member

Conflict in AnkiDroid/src/main/java/com/ichi2/anki/workarounds/SafeWebViewLayout.kt: both sides added the same canGoBack() (warnIfNotActive("canGoBack"), then webView.canGoBack()). The PR also added clearHistory() and setDownloadListener(DownloadListener?) in that hunk.

Resolution: kept canGoBack() once and kept those two PR methods unchanged. upstream/main moved during validation (7aa9e51e56 to 212cf6a2af) with no overlapping files, so the same resolution was replayed cleanly. Pushed e77fb98bc6ae403480cd520171f56e3027a4cd58.

Pre-push, API33_GAPI (emulator-5554):

  • ./gradlew lintAll ktlintCheck lint-rules:test jacocoUnitTestReport exit 0
  • TEST_RELEASE_BUILD=true python3 .github/run_emulator_tests.py exit 0
  • Ignored only phone-AVD XML harness failures: DeckPickerTest.checkIfStudyOptionsIsDisplayedOnTablet, NoteEditorTabOrderTest.testTabOrder, PagesTest.activityOpens, NoteTypeFieldEditorContextMenuTest.showsAllOptions, PreferencesNavigationTest.testOnNonCompactMode, DeckPickerImportTest tablet assumption. No other failures.

Assisted-by: Grok 4.7 Medium

@Ratnesh5
Ratnesh5 force-pushed the fix-22091-shared-decks-safewebview branch from e77fb98 to 0058328 Compare October 27, 2026 06:29

@mikehardy mikehardy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assisted-by: grok-4.7-medium

Thanks for iterating on the shared-decks WebView fix.

I did not check out or rebase this tip locally, and I did not run lint, unit, or emulator Gradle lanes on this SHA (prep stopped on required-red CI before local validation).

The diff still centers on SharedDecksActivity, the SafeWebViewLayout workaround, activity_shared_decks.xml, and the shared-deck unit tests that exercise the WebView container.

Blocker: the required GitHub Actions compare job is failing on 0058328ed65b85d01468cb25411ce2d59dcc934a. Please fix the screenshot regression or update baselines so compare is green before we can approve.

@mikehardy mikehardy added Needs Author Reply Waiting for a reply from the original author and removed Needs Review labels Oct 27, 2026
@Ratnesh5
Ratnesh5 force-pushed the fix-22091-shared-decks-safewebview branch from 0058328 to 415757a Compare October 27, 2026 07:52
@Ratnesh5

Copy link
Copy Markdown
Contributor Author

Thanks @mikehardy!
Fixed the SharedDecksScreenshotTest, it had a direct cast to WebView on R.id.web_view which caused a ClassCastException with SafeWebViewLayout. Updated it to reference the inner WebView, verified locally with -Pscreenshot, and pushed the update.

@mikehardy mikehardy removed the Needs Author Reply Waiting for a reply from the original author label Oct 27, 2026
@Ratnesh5
Ratnesh5 requested a review from mikehardy October 27, 2026 08:59

@david-allison david-allison left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GPT-6 felt the back button needed improving

    @Test
    fun `back exits while the recovered WebView is loading`() {
        val activity = startSharedDecks()
        val initialWebView = activity.webView
        val homeUrl = getResourceString(R.string.shared_decks_url)
        val deckUrl = "https://ankiweb.net/shared/info/1"

        shadowOf(initialWebView).pushEntryToHistory(homeUrl)
        initialWebView.webViewClient.doUpdateVisitedHistory(initialWebView, homeUrl, false)
        assertFalse(activity.onBackPressedDispatcher.hasEnabledCallbacks())

        shadowOf(initialWebView).pushEntryToHistory(deckUrl)
        initialWebView.webViewClient.doUpdateVisitedHistory(initialWebView, deckUrl, false)
        assertTrue(initialWebView.canGoBack())
        assertTrue(activity.onBackPressedDispatcher.hasEnabledCallbacks())

        // Invoke the installed client, as Android does when the renderer exits.
        assertTrue(initialWebView.webViewClient.onRenderProcessGone(initialWebView, mock()))
        assertNotSame(initialWebView, activity.webView)
        assertFalse(activity.webView.canGoBack())
        assertFalse(activity.isFinishing)

        // Robolectric has not delivered the replacement page's history callback yet.
        activity.onBackPressedDispatcher.onBackPressed()

        assertTrue(activity.isFinishing, "Back should exit while the replacement WebView has no history")
    }

@david-allison david-allison added the Needs Author Reply Waiting for a reply from the original author label Oct 27, 2026
@david-allison

Copy link
Copy Markdown
Member

CI is failing

@Ratnesh5
Ratnesh5 force-pushed the fix-22091-shared-decks-safewebview branch from f336a8d to 6e6d226 Compare October 27, 2026 19:54
@Ratnesh5
Ratnesh5 marked this pull request as draft October 27, 2026 20:24
@Ratnesh5
Ratnesh5 force-pushed the fix-22091-shared-decks-safewebview branch from 6e6d226 to 2be6cfa Compare October 28, 2026 12:03
@Ratnesh5
Ratnesh5 marked this pull request as ready for review October 28, 2026 12:16
@Ratnesh5
Ratnesh5 force-pushed the fix-22091-shared-decks-safewebview branch from 2be6cfa to 11e2d04 Compare October 30, 2026 14:24
@Ratnesh5

Copy link
Copy Markdown
Contributor Author

Hi @mikehardy I have pushed the updates and changes as requested, could you review whenever you get time

@david-allison david-allison left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!!

@david-allison david-allison added Needs Second Approval Has one approval, one more approval to merge and removed Needs Author Reply Waiting for a reply from the original author labels Nov 2, 2026

@mikehardy mikehardy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assisted-by: Grok 4.7

Thank you — SafeWebViewLayout recovery plus fixing Back after renderer death closes the shared-decks crash loop.

Locally I rebased onto main without force-pushing (prep stayed at the PR tip). I ran lint (lintAll, ktlintCheck, lint-rules:test), unit tests (jacocoUnitTestReport), and release emulator tests (TEST_RELEASE_BUILD=true via run_emulator_tests.py on emulator-5556 / API35_GAPI); all passed.

Reviewed SharedDecksActivity hosting SafeWebViewLayout, render-process recreation reloading the home URL, back callback disabled after recovery until history returns, and tests/screenshots using the inner WebView.

some acceptable findings, no action required, just leaving for posterity: one commit title oversells activity support; copyBackForwardList bypasses activeWebView; a shorter subject for the shared-deck fix commit.

@mikehardy mikehardy added Pending Merge Things with approval that are waiting future merge (e.g. targets a future release, CI wait, etc) and removed Needs Second Approval Has one approval, one more approval to merge labels Nov 3, 2026
@mikehardy
mikehardy added this pull request to the merge queue Nov 3, 2026
Merged via the queue into ankidroid:main with commit 75566f7 Nov 3, 2026
29 of 30 checks passed
@github-actions github-actions Bot removed the Pending Merge Things with approval that are waiting future merge (e.g. targets a future release, CI wait, etc) label Nov 3, 2026
@github-actions github-actions Bot added this to the 2.26 release milestone Nov 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants