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

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions