Pending remote disconnect during cross-origin navigation

606 views
Skip to first unread message

Marshall Greenblatt

unread,
Nov 25, 2024, 1:47:15 PM11/25/24
to chromium-mojo
Hi All,

I'm experiencing an issue with pending Mojo connections from new renderer processes being disconnected during cross-origin navigation and I'm trying to understand if this is a bug or intended behavior. My test setup is a Chromium-based application on Windows at M132 with prerendering disabled.

Full details:

I have a test case where I create browsers and then navigate those browsers cross-origin. I'm initiating a Mojo channel from the renderer process (in the ContentRenderClient::RenderFrameCreated callback) like so:

// In the frame-specific .h file:
mojo::Remote<mojom::MyInterface> remote_;

// In the frame-specific .cc file:
render_frame->GetBrowserInterfaceBroker().GetInterface(
    remote_.BindNewPipeAndPassReceiver());
remote_.set_disconnect_with_reason_handler(
    base::BindOnce(&MyObject::OnDisconnect, this));

When I create only one 1 browser then the Mojo Channel connection from the new renderer process (new origin after the cross-origin navigation) is established successfully, meaning that my registered browser interface binder is executed in the browser process as expected. This occurs with a 100% success rate in my testing.

However, when I create 2+ browsers simultaneously I often see the Mojo Channel connection for the 2nd+ new renderer process fail (disconnect handler executed) due to MOJO_RESULT_FAILED_PRECONDITION on the renderer side. When this occurs my registered browser interface binder is not executed in the browser process. I can work around this issue currently by "retrying" the connection (calling GetInterface again) after the disconnect, and that workaround has a 100% success rate in my testing.

From debugging the disconnect issue this appears to be a race in the browser process between the binder execution and the main RFH change for the cross-origin navigation (WebContentsObserver::RenderFrameHostChanged called). The disconnect happens in cases where the main RFH change occurs before the binder is executed. If the binder is executed first then no disconnect occurs and the Mojo channel works as expected (e.g. messages on the new channel are eventually delivered).

Is this disconnect behavior expected for "normal" (non-prerender) frames? If so, can anyone point me to where in the code we're disconnecting the pending remotes on RFH change?

Thanks,
Marshall

Dave Tapuska

unread,
Nov 25, 2024, 1:58:37 PM11/25/24
to Marshall Greenblatt, chromium-mojo
A new browser interface broker is bound on every commit... See https://source.chromium.org/chromium/chromium/src/+/main:content/browser/renderer_host/render_frame_host_impl.cc;l=15571;drc=7f4d721b03db919854138fc8753d434cda9089cd I'd expect to see it be discard every navigation not just cross-orgin.

dave.

--
You received this message because you are subscribed to the Google Groups "chromium-mojo" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-moj...@chromium.org.
To view this discussion visit https://groups.google.com/a/chromium.org/d/msgid/chromium-mojo/CAFW9UJ8e4XzQGJnKUxNRZHNsqdy-F3-r3Xq2XrszpGr52OxrMg%40mail.gmail.com.

Marshall Greenblatt

unread,
Nov 25, 2024, 2:47:15 PM11/25/24
to Dave Tapuska, chromium-mojo
On Mon, Nov 25, 2024 at 1:58 PM Dave Tapuska <dtap...@chromium.org> wrote:
A new browser interface broker is bound on every commit... See https://source.chromium.org/chromium/chromium/src/+/main:content/browser/renderer_host/render_frame_host_impl.cc;l=15571;drc=7f4d721b03db919854138fc8753d434cda9089cd I'd expect to see it be discard every navigation not just cross-orgin.

Thanks. If I understand correctly, the connection will be closed if the GetInterface call from the renderer is still in-flight when RenderFrameHostImpl::DidCommitNavigation calls broker_receiver_.reset(). If, however, the GetInterface call arrives first (BrowserInterfaceBrokerImpl::GetInterface called and PendingReceiver bound) then the binding will be successful and remain connected [1] after the broker_receiver_.reset(). Does that sound correct?

[1] Until the connection is closed for some other reason like the Receiver being reset or the renderer process terminating.

Dave Tapuska

unread,
Nov 25, 2024, 2:52:00 PM11/25/24
to Marshall Greenblatt, chromium-mojo
Yes that sounds correct. Although it really depends on how you associate the data with the RenderFrameHostImpl. DocumentAssociated data should be getting cleared.

dave.
Reply all
Reply to author
Forward
0 new messages