Skip to content
Open
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
26 changes: 26 additions & 0 deletions packages/firebase_app_check_tvos/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Dart / Flutter
.dart_tool/
build/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub/

# CocoaPods
tvos/Pods/
tvos/Podfile.lock
tvos/.symlinks/
tvos/Flutter/Flutter.framework
tvos/Flutter/Flutter.podspec

# Xcode / SwiftPM (per-user, generated when tvos/Package.swift is opened)
**/.swiftpm/
**/xcuserdata/

# IDE
.idea/
.vscode/
*.iml

# macOS
.DS_Store
1 change: 1 addition & 0 deletions packages/firebase_app_check_tvos/.pubignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pubspec_overrides.yaml
10 changes: 10 additions & 0 deletions packages/firebase_app_check_tvos/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
## 0.0.1

* Initial tvOS (Apple TV) implementation of `firebase_app_check`, ported from
`firebase_app_check` 0.4.5 with `flutter-tvos plugin port` and finished by
hand. DeviceCheck and App Attest providers (tvOS 15+) plus the Debug provider;
the reCAPTCHA provider is not available on tvOS (iOS-only in the Firebase Apple
SDK).
* Native code aligned to the `firebase_core 4.11.x` /
`firebase_core_platform_interface 7.1.0` FlutterFire train; depends on
`firebase_core_tvos`.
27 changes: 27 additions & 0 deletions packages/firebase_app_check_tvos/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2021 The Chromium Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
74 changes: 74 additions & 0 deletions packages/firebase_app_check_tvos/PORTING_REPORT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# firebase_app_check_tvos — porting report

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

Source: `firebase_app_check` 0.4.5 (Swift). Base platform: ios.
Output: `./firebase_app_check_tvos`

## Summary

| Status | Count |
| ------------------------------- | ------------------------------ |
| Methods ported as-is | full API |
| Providers disabled on tvOS | 1 (reCAPTCHA — iOS-only SDK) |
| tvOS build outlook | ✅ compiles |
| Manual review items | 1 (handled — see addendum) |

## Providers

App Check dispatches through Pigeon (`FirebaseAppCheckHostApi`). The provider
factory (`AppCheckProviderWrapper.configure`) selects the native provider:

| Provider | tvOS | Notes |
| --- | --- | --- |
| DeviceCheck | ✅ | `DeviceCheckProvider` — the default Apple provider on tvOS 15+ |
| App Attest (+ DeviceCheck fallback) | ✅ | `AppAttestProvider`, guarded `#available(tvOS 15.0)` |
| Debug | ✅ | `AppCheckDebugProvider` — for the simulator |
| reCAPTCHA | ❌ | `RecaptchaProvider` is **unavailable in the tvOS Firebase SDK** — see addendum |

## Manual review items

1. **reCAPTCHA provider** — the source guarded `RecaptchaProvider(app:)` with
`#if (os(iOS) || os(tvOS))`, but that Firebase type is **iOS-only** (reCAPTCHA
App Check is not a tvOS provider). Fixed — see addendum.

---

Manual review complete (2026-08-14) — see the addendum below.

## Addendum: manual fixes + verification (2026-08-14)

Applied by hand:

- **Podspec:** depend on `Firebase/AppCheck '~> 12.15.0'` + `firebase_core_tvos`
(not upstream `firebase_core`); tvOS 15.0 floor; `static_framework`; no
Flutter-CocoaPod dependency (Flutter via `FRAMEWORK_SEARCH_PATHS`). DeviceCheck
is weak-linked transitively by `Firebase/AppCheck`.
- **`FirebaseAppCheckPlugin.swift`:** `#if canImport(firebase_core) … #else
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
changed from `#if (os(iOS) || os(tvOS))` to `#if os(iOS)`. The `case` is
**kept** (so Pigeon dispatch stays intact); on tvOS the provider is left
unconfigured so `getToken` surfaces an explicit error rather than failing
silently. 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.

**Verified (runtime):** on the tvOS simulator (26.2, Apple TV 4K) against a live
Firebase project — native `[FirebaseAppCheck] 12.15.0` initialized, the Debug
provider issued a token (`[AppCheckCore] App Check debug token: …`), and
`getToken` round-tripped through the Pigeon channel to the App Check backend
(`POST …/exchangeDebugToken`). The exchange returned the expected
"debug token not registered" error (a console-registration gap, not a plugin
defect), confirming the native provider → Dart → backend path works on tvOS.
`Platform.operatingSystem == "tvos"` / `Platform.isIOS == true`. DeviceCheck /
App Attest attestation runs only on real hardware — physical Apple TV pass
pending.
58 changes: 58 additions & 0 deletions packages/firebase_app_check_tvos/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# firebase_app_check_tvos

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
> `PORTING_REPORT.md`.

## Usage

Federated plugin implementation — no imports needed from app code; it registers
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)
```

Use the Apple providers that exist on tvOS 15+ — **DeviceCheck** or **App Attest**:

```dart
await FirebaseAppCheck.instance.activate(
providerApple: const AppleDeviceCheckProvider(),
// or: const AppleAppAttestProvider(), AppleAppAttestWithDeviceCheckFallbackProvider()
);
```

> **Version alignment matters.** This package's native code matches the
> `firebase_core_platform_interface` **7.1.0** train (`firebase_core 4.11.x`).
> Keep your whole Firebase stack on one consistent FlutterFire release, or Dart
> `initializeApp(options:)` can crash in `CoreFirebaseOptions.fromList` at launch
> (a `FirebaseOptions` field-count mismatch).

## tvOS provider support

| Provider | tvOS |
| --- | --- |
| **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. Requesting it on tvOS leaves the provider unconfigured and `getToken` surfaces an explicit error. |

DeviceCheck / App Attest attestation runs on **real Apple TV hardware** (not the
simulator — use the Debug provider there).

## Status

| 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 |

## License

fluttertv under a BSD-3-Clause license. See `LICENSE` for the full text.
7 changes: 7 additions & 0 deletions packages/firebase_app_check_tvos/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
include: package:flutter_lints/flutter.yaml

analyzer:
language:
strict-casts: true
strict-inference: true
strict-raw-types: true
35 changes: 35 additions & 0 deletions packages/firebase_app_check_tvos/example/lib/firebase_options.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// PLACEHOLDER — replace by running `flutterfire configure` in this example dir.
//
// On tvOS, `defaultTargetPlatform == TargetPlatform.iOS`, so the `ios` entry
// below is what the Apple TV build uses — i.e. your existing iOS Firebase app's
// config is reused for tvOS.
//
// ignore_for_file: lines_longer_than_80_chars
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
import 'package:flutter/foundation.dart'
show defaultTargetPlatform, kIsWeb, TargetPlatform;

class DefaultFirebaseOptions {
static FirebaseOptions get currentPlatform {
if (kIsWeb) {
throw UnsupportedError('This example targets Apple TV (tvOS) only.');
}
switch (defaultTargetPlatform) {
case TargetPlatform.iOS: // tvOS reports iOS
return ios;
default:
throw UnsupportedError('This example targets Apple TV (tvOS) only.');
}
}

// Replace with your real values — run `flutterfire configure`, or copy them
// from your iOS app's GoogleService-Info.plist / Firebase console.
static const FirebaseOptions ios = FirebaseOptions(
apiKey: 'REPLACE_ME',
appId: 'REPLACE_ME', // GOOGLE_APP_ID
messagingSenderId: 'REPLACE_ME', // GCM_SENDER_ID
projectId: 'REPLACE_ME',
storageBucket: 'REPLACE_ME',
iosBundleId: 'com.example.firebaseAppCheckExample',
);
}
97 changes: 97 additions & 0 deletions packages/firebase_app_check_tvos/example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:firebase_app_check/firebase_app_check.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';

import 'firebase_options.dart';

Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
runApp(const AppCheckExampleApp());
}

class AppCheckExampleApp extends StatelessWidget {
const AppCheckExampleApp({super.key});

@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'firebase_app_check tvOS example',
theme: ThemeData.dark(useMaterial3: true),
home: const AppCheckHomePage(),
);
}
}

class AppCheckHomePage extends StatefulWidget {
const AppCheckHomePage({super.key});

@override
State<AppCheckHomePage> createState() => _AppCheckHomePageState();
}

class _AppCheckHomePageState extends State<AppCheckHomePage> {
final _appCheck = FirebaseAppCheck.instance;
String _status = 'Ready.';
String _token = '(none yet)';

Future<void> _run(String label, Future<void> Function() action) async {
try {
await action();
setState(() => _status = '✅ $label — ok.');
} catch (e) {
setState(() => _status = '❌ $label — $e');
}
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('firebase_app_check · tvOS')),
body: Padding(
padding: const EdgeInsets.all(48),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(_status, style: const TextStyle(fontSize: 28)),
const SizedBox(height: 16),
Text('token = $_token', style: const TextStyle(fontSize: 20)),
const SizedBox(height: 32),
Wrap(
spacing: 24,
runSpacing: 24,
children: [
ElevatedButton(
autofocus: true,
onPressed: () => _run('activate (DeviceCheck)', () async {
// DeviceCheck + App Attest are the Apple providers available
// on tvOS 15+. Debug provider is handy for the simulator.
await _appCheck.activate(
providerApple: const AppleDeviceCheckProvider(),
);
}),
child: const Text('activate (DeviceCheck)'),
),
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)';
});
}),
child: const Text('get App Check token'),
),
],
),
],
),
),
);
}
}
28 changes: 28 additions & 0 deletions packages/firebase_app_check_tvos/example/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: firebase_app_check_example
description: Demonstrates how to use the firebase_app_check plugin on tvOS.
publish_to: none

environment:
sdk: '^3.6.0'
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_app_check_tvos:
path: ../
firebase_core_tvos:
path: ../../firebase_core_tvos
flutter:
sdk: flutter

dev_dependencies:
flutter_lints: ^4.0.0
flutter_test:
sdk: flutter

flutter:
uses-material-design: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Local development override for the example app. Forces firebase_core_tvos
# to the sibling package so the example resolves against the plugin's hosted
# `^0.0.1` constraint before that package is published. Gitignored; examples
# are not published. Remove once firebase_core_tvos 0.0.1 is on pub.dev.
dependency_overrides:
firebase_core_tvos:
path: ../../firebase_core_tvos
Loading