Skip to content

Android: requestLatestContent() lacks threading contract #436

@jkmassel

Description

@jkmassel

Summary

requestLatestContent() in GutenbergView.kt is a @JavascriptInterface method that calls LatestContentProvider.getLatestContent() on the WebView's JavaBridge thread — not the main thread. However, neither the method nor the LatestContentProvider interface documents this threading behavior.

This is the only @JavascriptInterface method in GutenbergView that returns a value to JavaScript. Every other @JavascriptInterface method that touches app state uses handler.post { } to dispatch to the main thread, but requestLatestContent() cannot do this without losing its return value.

The problem

Host app implementors of LatestContentProvider.getLatestContent() will naturally access main-thread-only state (e.g., Android ViewModel/LiveData, repositories with @MainThread contracts). Without documentation or annotations, they have no indication that getLatestContent() runs off the main thread.

For comparison, the iOS equivalent in EditorViewController.swift explicitly dispatches to the main actor:

await MainActor.run { ... }

Suggested improvements

  1. Document the threading contract — Add a @WorkerThread annotation (or equivalent KDoc) to LatestContentProvider.getLatestContent() so implementors know they're responsible for thread safety.

  2. (Optional) Handle thread dispatch internally — Since requestLatestContent() already runs on the JavaBridge thread (a background thread), GutenbergKit could internally use a CountDownLatch or similar mechanism to read from the main thread and return the result synchronously:

    @JavascriptInterface
    fun requestLatestContent(): String? {
        var content: LatestContent? = null
        val latch = CountDownLatch(1)
        handler.post {
            content = latestContentProvider?.getLatestContent()
            latch.countDown()
        }
        latch.await()
        // serialize and return
    }

    This would make the API safe by default, matching the iOS behavior.

Context

Found during review of wordpress-mobile/WordPress-Android#22774. The WordPress-Android implementation accesses EditPostRepository.title/.content (which have no synchronization) directly from the JavaBridge thread.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions