wordpress-mobile / wordpress-mobile/GutenbergKit

Android: requestLatestContent() lacks threading contract

Open
#436 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Gutenberg Webviews
Dominant language
JavaScript
Stars
29
Forks
6
Avg merge
1d 9h
Merged PRs (30d)
41

Description

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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with requestLatestContent() in GutenbergView.kt and the LatestContentProvider interface, then trace how the JavaBridge thread invokes the provider. Clarify whether the intended change is an annotation/KDoc contract or internal main-thread dispatch; done means the chosen threading behavior is explicit to host-app implementors and consistent with the API’s synchronous return value.

Written by the indexing model from the issue text.

Assessment

Tech stack
android, kotlin
Domain
documentation, mobile
Issue type
Documentation
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.