Skip to content

[in_app_purchase] Migrate from platform channels to Pigeon-generated Dart FFI. - #1210

Open
gin7773 wants to merge 3 commits into
flutter-tizen:mainfrom
gin7773:ffi/in_app_purchase
Open

gin7773 wants to merge 3 commits into
flutter-tizen:mainfrom
gin7773:ffi/in_app_purchase

Conversation

@gin7773

@gin7773 gin7773 commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Main changes:

  • Migrate from platform channels to Dart FFI using the pigeon C++ FFI generator (git ref 1e63f1b5).

Fix: #1172

Replace the MethodChannel transport with dart:ffi bindings generated
by the pigeon C++ FFI generator (git ref 1e63f1b5), following the
video_player migration in flutter-tizen#1207.

- Generate the C++ FFI bindings (messages_ffi.{h,cc}), the Dart FFI
  bindings (messages.g.ffi.dart), and the ffigen config from
  pigeons/messages.dart
- Marshal every FFI entry point onto the platform thread's GLib main
  context via a MainContextDispatcher, preserving the thread affinity
  the messenger-based implementation provided
- Register the FFI API at plugin construction and tear it down in
  Dispose()
- Add an integration test that round-trips sync and async FFI calls
- Bump version to 0.2.0

Co-Authored-By: Cline SR
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-05T09:12:42.982269Z 3c3ad96 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@gin7773 gin7773 changed the title [in_app_purchase] Migrate from platform channels to Dart FFI [in_app_purchase] Migrate from platform channels to Pigeon-generated Dart FFI. Nov 4, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fe0675ddd3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

pigeon_in_x5f_app_x5f_purchase_x5f_tizen_tizen_x2f_src_x2f_messages_x5f_ffi_x2e_h_free_buffer(reply);
return;
}
on_reply(reply_id, reply);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Guard pending FFI replies against isolate teardown

If a hot restart occurs while a billing request is pending, the native plugin and BillingManager retain the response lambda, but its on_reply points to the NativeCallable.listener created by the destroyed Dart isolate. A delayed billing response then invokes an invalid callback trampoline here, which can terminate the process. TearDownInAppPurchaseApiFfi() only clears the API and dispatcher pointers; it does not invalidate callbacks already stored by BillingManager. Cancel or invalidate pending native replies before isolate teardown, or use a port-based reply transport that safely rejects replies to a dead isolate.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

…sters

After a hot restart the old isolate is destroyed while native reply
callbacks survive in BillingManager. A late billing response would
then invoke a NativeCallable of the dead isolate and can crash the
process.

Add an initialize() host API that resets pending BillingManager
callbacks, and call it from register() in the root isolate so stale
replies are invalidated as soon as the new isolate registers the
plugin, before any new request is made.

Co-Authored-By: Cline SR

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 80f0056498

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +171 to +175
is_available_callback_ = nullptr;
buy_item_callback_ = nullptr;
get_product_list_callback_ = nullptr;
get_purchase_list_callback_ = nullptr;
verify_invoice_callback_ = nullptr;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject stale native completions when resetting callbacks

When a hot restart occurs while a billing call is pending, initialize() clears these slots without cancelling the underlying native request, whose user_data still references the same BillingManager. If its reply arrives before a replacement call, handlers such as OnAvailable enter their null-callback branch and invoke the empty std::function, throwing std::bad_function_call out of the native callback. If a replacement call has already populated the slot, the old reply instead completes the new call with the wrong result, and the actual new reply then encounters the empty slot. Cancel the underlying operations or associate completions with per-request contexts/generations so stale replies cannot invoke or clear the current callback.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

…e replies

- Add meta to dependencies: pigeon v29 generates an import of
  package:meta in messages.g.dart, and pub publish --dry-run requires
  every imported package to be declared.
- Change the null-callback branches of the billing reply handlers to
  log instead of invoking the empty std::function, which throws
  std::bad_function_call and terminates the process when a stale reply
  arrives after initialize() has reset the pending callbacks.

Co-Authored-By: Cline SR
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[in_app_purchase_tizen] Migrating from Platform Channels to Dart FFI

1 participant