Skip to content

fix(android): keep editor load disk and SSL work off the main thread - #859

Draft
jkmassel wants to merge 2 commits into
jkmassel/issue-488from
jkmassel/gutenbergkit-issue-848
Draft

jkmassel wants to merge 2 commits into
jkmassel/issue-488from
jkmassel/gutenbergkit-issue-848

Conversation

@jkmassel

Copy link
Copy Markdown
Contributor

What?

Fixes #848. Opening the editor on Android no longer reads the disk or sets up SSL on the main thread, so host apps that run StrictMode with penaltyDeath no longer crash when the editor opens. The demo's ThreadPolicy now uses penaltyDeath.

Stacked on #489, which added the demo's StrictMode setup and docs/code/strictmode.md.

Why?

GutenbergView did this work on the main thread while the page loaded. The host had no call it could move to a background thread:

  • onPageStarted: started the upload server (OkHttp SSL setup, cacheDir, temp file sweep) and built the window.GBKit JSON (reads the asset bundle from disk).
  • prepareAndLoadEditor: created EditorService on the main dispatcher (SSL setup and several disk reads).

How?

GutenbergView.kt

  • The upload server and the window.GBKit JSON are built on Dispatchers.IO before loadUrl. onPageStarted only injects the prebuilt JSON. A reload reuses the same JSON.
  • mediaProcessor and mediaUploader are still read on the main thread, one main-thread pass after construction. Setting them right after construction still works, and setting them later still throws.
  • If the view is detached while the server is starting, the setup is cancelled and the server is stopped. Otherwise nothing else would stop it.
  • prepareAndLoadEditor creates and prepares EditorService on Dispatchers.IO, then loads the editor on Main. Progress updates are posted to the main thread.

Demo and docs

  • GutenbergKitApplication: ThreadPolicy is now penaltyLog().penaltyDeath(). The log keeps the full violation. VmPolicy stays on penaltyLog.
  • docs/code/strictmode.md: replaces the table of remaining violations with a short note, and updates the configuration and verified flows.

Tests

  • The upload-server and navigation tests now run the pre-load setup, instead of calling onEditorPageStarted through reflection to start the server.
  • New: the globals carry the upload server's port, and a view detached before load never starts a server.
  • Removed: "a non-editor page does not start the upload server". The server no longer depends on which page loads. The navigation tests still check that non-editor pages get no globals.

Testing Instructions

Run the demo in a debug build, then open the editor from a connected site's Editor Configuration screen:

  1. Tap Start without Prepare Editor, with Enable Native Media Upload on.
  2. Repeat with native upload off.
  3. Tap Prepare Editor, then Start, with native upload on and off.

The editor should load each time without crashing. adb logcat -s StrictMode should show only UntaggedSocketViolation, which is VmPolicy noise.

Test plan

  • :Gutenberg:testDebugUnitTest: 764 tests, 0 failures.
  • make lint-android (Detekt) is clean. Prettier is clean on docs/code/strictmode.md.
  • The four flows above on an API 36 emulator with penaltyDeath on. No crash. Only UntaggedSocketViolation was logged. With native upload on, the app had a loopback listener; with it off, it had none.
  • The other flows in strictmode.md with penaltyDeath on: Standalone editor → Prepare Editor → Start with typing, the inserter sheet (category tabs and search), background and resume, and Browse → open a post without preparing. No crash.
  • Control: the same demo built with the old GutenbergView.kt crashes on Start with CustomViolation: newSSLContext. This confirms penaltyDeath is active.

GutenbergView started the upload server and built the window.GBKit JSON
on the main thread in onPageStarted, and created its EditorService on the
main dispatcher. Hosts running StrictMode with penaltyDeath crashed on
every editor launch.

Both are now built on Dispatchers.IO before loadUrl, and onPageStarted
only injects the prebuilt JSON. The media processor and uploader are
still captured on the main thread, one pass after construction.

Fixes #848
The library no longer does main-thread disk or SSL work while the editor
loads (#848), so the demo's ThreadPolicy adds penaltyDeath. VmPolicy
stays on penaltyLog.
@jkmassel jkmassel added the [Type] Bug An existing feature does not function as intended label Oct 30, 2026
@jkmassel jkmassel self-assigned this Oct 30, 2026
@jkmassel jkmassel added this to the 0.20.0 milestone Oct 30, 2026
@wpmobilebot

Copy link
Copy Markdown

XCFramework Build

This PR's XCFramework is available for testing. Add the following to your Package.swift:

.package(url: "https://github.com/wordpress-mobile/GutenbergKit", branch: "pr-build/859")

Built from e08b871

@jkmassel
jkmassel added this pull request to stack #861 October 30, 2026 16:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Android [Type] Bug An existing feature does not function as intended

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants