Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Need a way to make synchronous calls from plugin platform code to Dart code #28310

Open
amirh opened this issue Feb 22, 2019 · 9 comments
Open
Labels
a: plugins Support for writing, building, and running plugin packages c: new feature Nothing broken; request for a new capability engine flutter/engine repository. See also e: labels. p: webview The WebView plugin P3 Issues that are less important to the Flutter project team-engine Owned by Engine team triaged-engine Triaged by Engine team

Comments

@amirh
Copy link
Contributor

amirh commented Feb 22, 2019

This came up as part of #25329:

The Android WebView API allows passing in a delegate that is invoked on the platform thread before a page is about to be loaded, the delegate needs to synchronously return true or false to determine whether to allow the navigation or to block it.

We needed to expose the same functionality in the webview_flutter plugin, ideally by delegating the decision to the Flutter application's Dart code. But this is currently impossible due to the combination of:

  1. Communication over platform channels is asynchronous.
  2. Messages sent from Dart to the platform channels are only delivered to the platform thread(by posting a task to the message loop).

Even if we were to block the platform thread waiting for the Dart code to make a decision, we would not be able to receive the message back from Dart(as the platform thread is blocked) and create a deadlock.

One potential approach for overriding this is to allow "platform channels" that deliver message to platform code on a separate thread. We could then:

  1. Send a message to Dart from the platform thread.
  2. Block the platform thread with some thread synchronization primitive.
  3. Dart code will send the response to a dedicated thread.
  4. The dedicated thread will release the latch that the platform thread is waiting on.

If we do this we should probably require that the "special thread" is always different from the platform thread.

For #25329 we're currently proceeding with a workaround that makes some security compromises(which means when an app sets a navigation delegate it should only load trusted content). But we should remove that workaround as soon as this issue is resolved.

cc @cbracken @jason-simmons

@amirh amirh added c: new feature Nothing broken; request for a new capability engine flutter/engine repository. See also e: labels. plugin p: webview The WebView plugin labels Feb 22, 2019
@amirh amirh added this to the Goals milestone Feb 22, 2019
@yohom
Copy link

yohom commented Sep 19, 2019

Hi @amirh, is there any progress on this issue?

@kf6gpe kf6gpe changed the title Need a way to make synchronous calls from plugin platform code to Dart code. Need a way to make synchronous calls from plugin platform code to Dart code Jan 7, 2020
@kf6gpe kf6gpe added the P2 Important issues not at the top of the work list label May 29, 2020
@Hixie
Copy link
Contributor

Hixie commented Jul 21, 2020

I don't see how the proposal would avoid deadlocks. Wouldn't a deadlock still happen if the dedicated isolate communicated with the main Dart thread which then communicated with the platform thread?

@xster
Copy link
Member

xster commented Jul 31, 2020

cc @gaaclarke since this ties in to your https://docs.google.com/document/d/1bD_tiN987fWEPtw7tjXHzqZVg_g9H95IS32Cm609VZ8 explorations (sorry google internal) on pigeon.

@gaaclarke
Copy link
Member

This is already possible with FFI. I have examples of it here for android and iOS: https://github.com/gaaclarke/MessagingTiming

@Hixie Hixie removed this from the None. milestone Aug 17, 2020
@xster
Copy link
Member

xster commented May 13, 2021

@iskakaushik just found this bug with some more context. Also, there's some interest in the reverse direction as well. But it doesn't have to be the same technical solution. An example is ByteDance wanting to consult a native SDK API while building a frame without incurring the thread hopping expenses. But I'd treat that direction at a lower priority.

@sdas19
Copy link

sdas19 commented Jun 1, 2021

The same limitation we are also facing when we are trying to share data via content provider from flutter app to a different native app.

Please find the scenario below.

  1. Android part of a flutter app exposes a content provider.
  2. A different native android app is communicating to the content provider.
  3. Now upon receiving the request native part of the flutter app fires up a platform channel to fetch data from the flutter side.
  4. However only the asynchronous callback mechanism is supported by the native to flutter platform channel for data sharing and the content provider needs data to be returned in a synchronous way from the query method.
  5. We can achieve this by putting a latch or blocking the thread, however, when we block the thread the native c++ code in the platform channel event queue does not propagate the communication anymore (to flutter part from native) as the platform channel only works in the main thread.

If anyone can think of any workaround, please jump in.

@bdlukaa

This comment was marked as off-topic.

@bdlukaa

This comment was marked as off-topic.

@stuartmorgan stuartmorgan added a: plugins Support for writing, building, and running plugin packages and removed plugin labels Mar 26, 2023
@flutter-triage-bot flutter-triage-bot bot added team-engine Owned by Engine team triaged-engine Triaged by Engine team labels Jul 7, 2023
@stuartmorgan stuartmorgan added P3 Issues that are less important to the Flutter project and removed P2 Important issues not at the top of the work list labels Aug 26, 2023
@filipraj08
Copy link

It would be very good to have synchronous way of communicating with native platforms, and not only from plugins. I can give some examples for both directions:

from flutter to iOS

  • i want to implement custom TextEditingController. the purpose is to find urls/phone numbers and to underline that text while user writes into text field. matching is done in overridden method buildTextSpan. best solution would be to call iOS native to do matching on text, and then parse results in flutter, but since buildTextSpan cannot be async, i cannot do this, so i need to do workaround like implementing matcher on flutter level (which is never as good as iOS solution).

from iOS to flutter

  • im building macOS app and depending on where currently user is in the app i want to enable/disable specific menu items (macOS menu items on top left part of the screen inside File, Edit, View, etc...). how it works on iOS, when menu is opened system calls specific function and asks if menu item is enabled. I would love at that stage to call Flutter and to ask if item should be enabled, but this is not possible because of async limitation. so i need to do workaround with preemptively storing values so i have them when function is called.

what i want to say is most of time there is some kind of workaround possible, but it requires unnecessary extra work for things which are already existing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a: plugins Support for writing, building, and running plugin packages c: new feature Nothing broken; request for a new capability engine flutter/engine repository. See also e: labels. p: webview The WebView plugin P3 Issues that are less important to the Flutter project team-engine Owned by Engine team triaged-engine Triaged by Engine team
Projects
None yet
Development

No branches or pull requests