Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions packages/cloud_functions_tvos/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@ environment:
flutter: '>=3.27.0'

dependencies:
# Pinned exact to the 4.11.x train (firebase_core_platform_interface 7.1.0)
# that firebase_core_tvos ships on — 6.3.6 / firebase_core 4.13.0 drift to
# platform_interface 8.1.0 (14-field FirebaseOptions) and mismatch the native
# Pigeon, crashing at launch under Dart options: init.
# firebase_core is pinned exact; its train picks the matching firebase_core_tvos
# (4.11.x -> pi 7.1.0 -> 0.0.2); floating it breaks the native Pigeon ABI.
cloud_functions: 6.3.3
cloud_functions_tvos:
path: ../
Expand Down
5 changes: 2 additions & 3 deletions packages/firebase_ai_tvos/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ environment:
flutter: '>=3.27.0'

dependencies:
# Pinned to the 4.11.x train (firebase_core_platform_interface 7.1.0) that the
# Firebase _tvos family ships on; newer firebase_core drifts to pi 8.1 and
# mismatches firebase_core_tvos's native Pigeon.
# firebase_core is pinned exact; its train picks the matching firebase_core_tvos
# (4.11.x -> pi 7.1.0 -> 0.0.2); floating it breaks the native Pigeon ABI.
firebase_ai: 3.13.1
firebase_ai_tvos:
path: ../
Expand Down
7 changes: 2 additions & 5 deletions packages/firebase_analytics_tvos/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,8 @@ environment:
flutter: '>=3.27.0'

dependencies:
# Pinned to the train the published _tvos packages were built from
# (firebase_core 4.11.0 -> firebase_core_platform_interface 7.1.0, whose
# FirebaseOptions has 15 fields incl. recaptchaSiteKey, matching the native
# Pigeon in firebase_core_tvos). No patch, no plist needed: Dart sends 15
# fields, native reads 15. This is the same train flutter_pca will bump to.
# firebase_core is pinned exact; its train picks the matching firebase_core_tvos
# (4.11.x -> pi 7.1.0 -> 0.0.2); floating it breaks the native Pigeon ABI.
firebase_core: 4.11.0
firebase_analytics: 12.4.3
firebase_analytics_tvos:
Expand Down
11 changes: 11 additions & 0 deletions packages/firebase_app_check_tvos/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
## 0.0.2

* Regenerated the Pigeon messages against `firebase_app_check` 0.4.7: `activate()`
takes a 5th `recaptchaSiteKey` argument and the `getTokenResult` channel is
implemented.
* Fixed `appAttestWithDeviceCheckFallback` never falling back: it now checks
`DCAppAttestService.shared.isSupported` rather than the OS version alone,
mirroring upstream's fix in 0.4.7 (flutterfire#18568).
* Requires `firebase_app_check` `>=0.4.7 <0.4.8` and `firebase_core_tvos`
`^0.0.3` (the `firebase_core_platform_interface` 8.1.1 train).

## 0.0.1

* Initial tvOS (Apple TV) implementation of `firebase_app_check`, ported from
Expand Down
63 changes: 55 additions & 8 deletions packages/firebase_app_check_tvos/PORTING_REPORT.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

Generated by `flutter-tvos plugin port` on 2026-08-14.

Source: `firebase_app_check` 0.4.5 (Swift). Base platform: ios.
Source: `firebase_app_check` 0.4.7 (Swift). Base platform: ios.
Originally ported from 0.4.5; re-synced to 0.4.7 for 0.0.2 (see addendum).
Output: `./firebase_app_check_tvos`

## Summary
Expand Down Expand Up @@ -49,18 +50,25 @@ firebase_core_shared` repointed to a plain `import firebase_core_tvos`.
- **reCAPTCHA triage (the one real tvOS-incompatible API):** `RecaptchaProvider`
is unavailable in the tvOS Firebase SDK, so the `case "recaptcha":` branch was
narrowed from `#if (os(iOS) || os(tvOS))` to `#if os(iOS)`. The `case` is
**kept** (so Pigeon dispatch stays intact); on tvOS, requesting reCAPTCHA falls
back to the default DeviceCheck provider. tvOS callers should use DeviceCheck /
App Attest.
**kept** (so Pigeon dispatch stays intact); on tvOS `delegateProvider` is left
nil, so `getToken` fails with `Provider not configured` rather than silently
attesting as something else. tvOS callers should use DeviceCheck / App Attest.
- **Deleted the generated `tvos/Package.swift`** (route via the podspec).
- **`lib/firebase_app_check_tvos.dart`:** one-line re-export of
`package:firebase_app_check/firebase_app_check.dart`. Copied Dart (`lib/src/`)
removed.

**Version alignment:** matches `firebase_app_check 0.4.5` on the
`firebase_core_platform_interface` **7.1.0** train (`firebase_core 4.11.x`) — the
same train as `firebase_core_tvos`. 0.4.5+1 is core 4.12 and 0.4.6 is core 4.13
(off-train), so 0.4.5 is the correct latest on this train.
**Version alignment (0.0.2):** matches `firebase_app_check 0.4.7` on the
`firebase_core_platform_interface` **8.1.1** train (`firebase_core 4.14.x`),
which is the train `firebase_core_tvos` 0.0.3 ships on — hence the
`firebase_core_tvos: ^0.0.3` floor here. 0.0.2 is excluded by the solver
(it declares pi `>=7.1.0 <8.1.0`) and 0.0.1 declares no pi constraint at all, so
without that floor pub could legally select a core pod whose native Pigeon
expects the pre-8.1 `FirebaseOptions` payload — a crash at launch rather than a
resolution error.

Superseded (0.0.1): matched `firebase_app_check 0.4.5` on the pi **7.1.0** train
(`firebase_core 4.11.x`), when 0.4.6 was off-train.

**Verified (runtime):** on the tvOS simulator (26.2, Apple TV 4K) against a live
Firebase project — native `[FirebaseAppCheck] 12.15.0` initialized, the Debug
Expand All @@ -78,3 +86,42 @@ pending.
`Unknown=0 … Unsupported=4`), so on tvOS `Unsupported` (App Attest missing on
older hardware) reaches Dart as `unknown`. Left verbatim to keep rebases cheap —
the physical-hardware pass should expect `unknown` where `unsupported` is meant.

## Addendum: re-sync to 0.4.7 (2026-09-17, release 0.0.2)

- **`FirebaseAppCheckMessages.g.swift`** regenerated from `firebase_app_check`
0.4.7 — byte-identical to upstream's apart from the `#if os(iOS)` →
`#if (os(iOS) || os(tvOS))` guard on line 9. Covers the two 0.4.6 contract
changes: `activate` gains a 5th `recaptchaSiteKey` argument, and
`getTokenResult` exists.
- **`FirebaseAppCheckPlugin.swift`:** `getTokenResult` and the `recaptchaSiteKey`
plumbing taken verbatim from 0.4.7; `appAttestWithDeviceCheckFallback` now
mirrors upstream's fix for flutterfire#18568 (check
`DCAppAttestService.shared.isSupported` rather than OS version alone, so the
provider actually falls back), with `import DeviceCheck` restored and the
porter's `tvOS 15.0` availability kept.
- **`Constants.swift`:** `versionNumber` → `"0.4.7"`, matching upstream.
- **Constraints:** `firebase_app_check ">=0.4.7 <0.4.8"`,
`firebase_core_tvos ^0.0.3`.

**Verified on the simulator for 0.0.2** (tvOS 26.5, Apple TV 4K 3rd gen, native
`Firebase/AppCheck 12.15.0`):

| Probe | Result |
| -------------------------------- | -------------------------------------------------------------- |
| `activate(Debug)` | ok — 5-argument payload accepted |
| `getToken` | reaches `…/exchangeDebugToken`, HTTP 403 (debug token not registered for this app) |
| `getLimitedUseToken` | same endpoint, same 403 — i.e. the channel dispatches |
| `activate(DeviceCheck)` | ok; `getToken` → "DeviceCheckProvider is not supported…" |
| `activate(AppAttestFallback)` | ok; `getToken` → "**DeviceCheckProvider** is not supported…" |

The last row is the App Attest fallback fix, observed rather than inferred. The
simulator reports tvOS 26.5, so the old `#available(tvOS 15.0)` check passed and
selected App Attest — a control build with the pre-fix block reports
"**AppAttestProvider** is not supported…" on the same call. Naming DeviceCheck
means `DCAppAttestService.shared.isSupported` returned false and the provider
actually fell back.

What the simulator still cannot show: a successfully *issued* token (needs a
debug token registered in the Firebase console) and real DeviceCheck / App
Attest attestation (needs a physical Apple TV).
14 changes: 7 additions & 7 deletions packages/firebase_app_check_tvos/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
The tvOS implementation of [`firebase_app_check`](https://pub.dev/packages/firebase_app_check).

> Ported with [`flutter-tvos plugin port`](https://github.com/fluttertv/flutter-tvos)
> from `firebase_app_check` 0.4.5, then finished + verified by hand. See
> from `firebase_app_check` 0.4.7, then finished + verified by hand. See
> `PORTING_REPORT.md`.

## Usage
Expand All @@ -13,10 +13,10 @@ automatically. Apps that already use `firebase_app_check` and target tvOS add:

```yaml
dependencies:
firebase_app_check: ^0.4.5
firebase_app_check_tvos: ^0.0.1
firebase_core: ^4.11.0
firebase_core_tvos: ^0.0.1 # tvOS core (this package depends on it)
firebase_app_check: ">=0.4.7 <0.4.8" # closed window: 0.4.8 may move the Pigeon contract
firebase_app_check_tvos: ^0.0.2
firebase_core: ^4.14.0
firebase_core_tvos: ^0.0.3 # tvOS core (this package depends on it)
```

Use the Apple providers that exist on tvOS 15+ — **DeviceCheck** or **App Attest**:
Expand All @@ -41,7 +41,7 @@ await FirebaseAppCheck.instance.activate(
| **DeviceCheck** (`AppleDeviceCheckProvider`) | ✅ (tvOS 15+) |
| **App Attest** (`AppleAppAttestProvider`, …WithDeviceCheckFallback) | ✅ (tvOS 15+) |
| **Debug** (`AppleDebugProvider`) | ✅ (use on the simulator) |
| **reCAPTCHA** (`AppleReCaptchaProvider`) | ❌ **not available** — `RecaptchaProvider` is iOS-only in the Firebase Apple SDK; not an Apple-TV provider. Use a DeviceCheck / App Attest provider on tvOS; if reCAPTCHA is requested, the tvOS build falls back to the default DeviceCheck provider rather than reCAPTCHA. |
| **reCAPTCHA** (`AppleReCaptchaProvider`) | ❌ **not available** — `RecaptchaProvider` is iOS-only in the Firebase Apple SDK; not an Apple-TV provider. Use a DeviceCheck / App Attest provider on tvOS; if reCAPTCHA is requested, the provider is left unconfigured and `getToken` fails with `Provider not configured`. |

DeviceCheck / App Attest attestation runs on **real Apple TV hardware** (not the
simulator — use the Debug provider there).
Expand All @@ -51,7 +51,7 @@ simulator — use the Debug provider there).
| Platform | Implemented | Verified |
| --- | --- | --- |
| Apple TV (`appletvos`) | yes | ⏳ pending physical Apple TV pass (DeviceCheck runs only on real hardware) |
| Apple TV simulator (`appletvsimulator`) | yes | ✅ verified — native `FirebaseAppCheck 12.15.0` initializes on tvOS, the Debug provider issues a token, and `getToken` round-trips to the App Check backend (`exchangeDebugToken`) via the Pigeon channel |
| Apple TV simulator (`appletvsimulator`) | yes | ✅ re-verified for 0.0.2 on tvOS 26.5 (Apple TV 4K, 3rd gen) — all three `activate()` calls cross the 5-argument Pigeon payload, and `getToken` / `getLimitedUseToken` both reach `exchangeDebugToken` on the App Check backend and return typed errors to Dart. Token *issuance* still needs a debug token registered in the console; attestation itself needs real hardware |

## License

Expand Down
28 changes: 23 additions & 5 deletions packages/firebase_app_check_tvos/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ class _AppCheckHomePageState extends State<AppCheckHomePage> {
String _status = 'Ready.';
String _token = '(none yet)';

/// A token is ~700 chars of JWT; show enough to tell a real one from a stub.
static String _describe(String? token) => token == null
? '(null)'
: '${token.substring(0, token.length.clamp(0, 24))}… (${token.length} chars)';

Future<void> _run(String label, Future<void> Function() action) async {
try {
await action();
Expand Down Expand Up @@ -76,17 +81,30 @@ class _AppCheckHomePageState extends State<AppCheckHomePage> {
}),
child: const Text('activate (DeviceCheck)'),
),
ElevatedButton(
onPressed: () => _run('activate (Debug)', () async {
// The only provider that can mint a token on the simulator:
// App Attest and DeviceCheck both need real hardware.
await _appCheck.activate(
providerApple: const AppleDebugProvider(),
);
}),
child: const Text('activate (Debug)'),
),
ElevatedButton(
onPressed: () => _run('getToken', () async {
final token = await _appCheck.getToken();
setState(() {
_token = token == null
? '(null)'
: '${token.substring(0, token.length.clamp(0, 24))}… (${token.length} chars)';
});
setState(() => _token = _describe(token));
}),
child: const Text('get App Check token'),
),
ElevatedButton(
onPressed: () => _run('getLimitedUseToken', () async {
final token = await _appCheck.getLimitedUseToken();
setState(() => _token = _describe(token));
}),
child: const Text('get limited-use token'),
),
],
),
],
Expand Down
11 changes: 5 additions & 6 deletions packages/firebase_app_check_tvos/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@ environment:
flutter: '>=3.27.0'

dependencies:
# Pinned to the train the published _tvos packages ship on (firebase_core
# 4.11.x -> firebase_core_platform_interface 7.1.0). Keeps the native Pigeon
# ABI in sync with firebase_core_tvos.
firebase_core: 4.11.0
firebase_app_check: 0.4.5
# firebase_core is pinned exact and firebase_core_tvos floored to match:
# 0.4.7 needs pi ^8.1.1 (the 4.14.x train), which only core_tvos 0.0.3 accepts.
firebase_core: 4.14.0
firebase_app_check: 0.4.7
firebase_app_check_tvos:
path: ../
firebase_core_tvos: ^0.0.1
firebase_core_tvos: ^0.0.3
flutter:
sdk: flutter

Expand Down
15 changes: 9 additions & 6 deletions packages/firebase_app_check_tvos/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: firebase_app_check_tvos
description: >-
tvOS (Apple TV) implementation of the firebase_app_check Flutter plugin,
providing Firebase App Check on Apple TV (App Attest / DeviceCheck).
version: 0.0.1
version: 0.0.2
homepage: https://fluttertv.dev
repository: https://github.com/fluttertv/plugins/tree/main/packages/firebase_app_check_tvos
issue_tracker: https://github.com/fluttertv/plugins/issues
Expand All @@ -16,16 +16,19 @@ environment:
dependencies:
flutter:
sdk: flutter
# Pinned below 0.4.6: that release moves the platform-interface pigeon
# contract (new getTokenResult channel; activate() gains a 5th
# recaptchaSiteKey arg) which the generated Swift here does not cover.
firebase_app_check: ">=0.4.5 <0.4.6"
firebase_app_check: ">=0.4.7 <0.4.8"
# Transitive Dart dependency so the app's dependency graph includes
# firebase_core_tvos — plugin discovery (tvos_plugins.dart) only adds a
# package's native pod to the generated Podfile if it's reachable here,
# which the podspec's `s.dependency 'firebase_core_tvos'` then resolves
# instead of failing over to upstream's iOS-only firebase_core pod.
firebase_core_tvos: ^0.0.1
#
# Floored at 0.0.3, not ^0.0.1: firebase_app_check 0.4.7 requires
# firebase_core_platform_interface ^8.1.1, which 0.0.2 excludes by its own
# constraint but 0.0.1 does not constrain at all. Without this floor pub can
# legally pick 0.0.1, whose native Pigeon expects the pre-8.1 FirebaseOptions
# payload — a crash at launch instead of a solver error.
firebase_core_tvos: ^0.0.3

dev_dependencies:
flutter_lints: ^4.0.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
// found in the LICENSE file.

/// Auto-generated file. Do not edit.
public let versionNumber = "0.4.5"
public let versionNumber = "0.4.7"
Loading
Loading