From ffa9d0ff455295966712b27f04ac7952ec00a3b7 Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Mon, 23 Jan 2023 08:10:17 +0100 Subject: [PATCH 01/11] feat(core): support TrustedType --- .../firebase_core/example/web/index.html | 57 ++++++- .../lib/firebase_core_web.dart | 5 +- .../lib/src/firebase_core_web.dart | 25 +++- .../firebase_core_web/lib/src/interop/js.dart | 141 ++++++++++++++++++ 4 files changed, 219 insertions(+), 9 deletions(-) create mode 100644 packages/firebase_core/firebase_core_web/lib/src/interop/js.dart diff --git a/packages/firebase_core/firebase_core/example/web/index.html b/packages/firebase_core/firebase_core/example/web/index.html index 1fa3be6941df..58971ce901ac 100644 --- a/packages/firebase_core/firebase_core/example/web/index.html +++ b/packages/firebase_core/firebase_core/example/web/index.html @@ -1,13 +1,56 @@ + + + + + + + + + + Firebase Core Example + + + + + + + + + diff --git a/packages/firebase_core/firebase_core_web/lib/firebase_core_web.dart b/packages/firebase_core/firebase_core_web/lib/firebase_core_web.dart index a2ae0d1bc33d..4e3f360568fa 100644 --- a/packages/firebase_core/firebase_core_web/lib/firebase_core_web.dart +++ b/packages/firebase_core/firebase_core_web/lib/firebase_core_web.dart @@ -10,13 +10,16 @@ import 'dart:html'; import 'dart:js'; import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart'; +import 'package:firebase_core_web/src/interop/js.dart'; import 'package:flutter_web_plugins/flutter_web_plugins.dart'; import 'package:js/js_util.dart' as js_util; + import 'src/interop/core.dart' as firebase; +import 'src/interop/js.dart' as js; part 'src/firebase_app_web.dart'; -part 'src/firebase_sdk_version.dart'; part 'src/firebase_core_web.dart'; +part 'src/firebase_sdk_version.dart'; /// Returns a [FirebaseAppWeb] instance from [firebase.App]. FirebaseAppPlatform _createFromJsApp(firebase.App jsApp) { diff --git a/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart b/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart index 86043dc396c3..6d90d300f3d7 100644 --- a/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart +++ b/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart @@ -96,20 +96,43 @@ class FirebaseCoreWeb extends FirebasePlatform { return []; } + final String _defaultTrustedPolicyName = 'flutterfire-'; + /// Injects a `script` with a `src` dynamically into the head of the current /// document. Future _injectSrcScript(String src, String windowVar) async { + DomTrustedScriptUrl? trustedUrl; + final trustedPolicyName = _defaultTrustedPolicyName + windowVar; + if (trustedTypes != null) { + console.debug( + 'TrustedTypes available. Creating policy:', + trustedPolicyName, + ); + final DomTrustedTypePolicyFactory factory = trustedTypes!; + try { + final DomTrustedTypePolicy policy = factory.createPolicy( + _defaultTrustedPolicyName, + DomTrustedTypePolicyOptions( + createScriptURL: allowInterop((String url) => src), + ), + ); + trustedUrl = policy.createScriptURL(src); + } catch (e) { + rethrow; + } + } ScriptElement script = ScriptElement(); script.type = 'text/javascript'; script.crossOrigin = 'anonymous'; script.text = ''' window.ff_trigger_$windowVar = async (callback) => { - callback(await import("$src")); + callback(await import("${trustedUrl?.toString() ?? src}")); }; '''; assert(document.head != null); document.head!.append(script); + Completer completer = Completer(); context.callMethod('ff_trigger_$windowVar', [ diff --git a/packages/firebase_core/firebase_core_web/lib/src/interop/js.dart b/packages/firebase_core/firebase_core_web/lib/src/interop/js.dart new file mode 100644 index 000000000000..0a720243449d --- /dev/null +++ b/packages/firebase_core/firebase_core_web/lib/src/interop/js.dart @@ -0,0 +1,141 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/* +// DOM shim. This file contains everything we need from the DOM API written as +// @staticInterop, so we don't need dart:html +// https://developer.mozilla.org/en-US/docs/Web/API/ +*/ + +import 'package:js/js.dart'; + +/// console interface +@JS() +@staticInterop +@anonymous +abstract class DomConsole {} + +/// The interface of window.console +extension DomConsoleExtension on DomConsole { + /// console.debug + external DomConsoleDumpFn get debug; + + /// console.info + external DomConsoleDumpFn get info; + + /// console.log + external DomConsoleDumpFn get log; + + /// console.warn + external DomConsoleDumpFn get warn; + + /// console.error + external DomConsoleDumpFn get error; +} + +/// Fakey variadic-type for console-dumping methods (like console.log or info). +typedef DomConsoleDumpFn = void Function( + Object? arg, [ + Object? arg2, + Object? arg3, + Object? arg4, + Object? arg5, + Object? arg6, + Object? arg7, + Object? arg8, + Object? arg9, + Object? arg10, +]); + +/// Error object +@JS('Error') +@staticInterop +abstract class DomError {} + +/// Methods on the error object +extension DomErrorExtension on DomError { + /// Error message. + external String? get message; + + /// Stack trace. + external String? get stack; + + /// Error name. This is determined by the constructor function. + external String get name; + + /// Error cause indicating the reason why the current error is thrown. + /// + /// This is usually another caught error, or the value provided as the `cause` + /// property of the Error constructor's second argument. + external Object? get cause; +} + +/* +// Trusted Types API (TrustedTypePolicy, TrustedScript, TrustedScriptURL) +// https://developer.mozilla.org/en-US/docs/Web/API/TrustedTypesAPI +*/ + +/// A factory to create `TrustedTypePolicy` objects. +@JS() +@staticInterop +@anonymous +abstract class DomTrustedTypePolicyFactory {} + +/// (Some) methods of the [DomTrustedTypePolicyFactory]: +extension DomTrustedTypePolicyFactoryExtension on DomTrustedTypePolicyFactory { + /// createPolicy + external DomTrustedTypePolicy createPolicy( + String policyName, + DomTrustedTypePolicyOptions? policyOptions, + ); +} + +/// Options to create a trusted type policy. +@JS() +@staticInterop +@anonymous +abstract class DomTrustedTypePolicyOptions { + /// Constructs a TrustedPolicyOptions object in JavaScript. + /// + /// The following properties need to be manually wrapped in [allowInterop] + /// before being passed to this constructor: [createScriptURL]. + external factory DomTrustedTypePolicyOptions({ + DomCreateScriptUrlOptionFn? createScriptURL, + }); +} + +/// Type of the function to configure createScriptURL +typedef DomCreateScriptUrlOptionFn = String Function(String input); + +/// An instance of a TrustedTypePolicy +@JS() +@staticInterop +@anonymous +abstract class DomTrustedTypePolicy {} + +/// (Some) methods of the [DomTrustedTypePolicy] +extension DomTrustedTypePolicyExtension on DomTrustedTypePolicy { + /// Create a `TrustedScriptURL` for the given [input]. + external DomTrustedScriptUrl createScriptURL(String input); +} + +/// An instance of a DomTrustedScriptUrl +@JS() +@staticInterop +@anonymous +abstract class DomTrustedScriptUrl {} + +// Getters + +/// window.trustedTypes (may or may not be supported by the browser) +@JS() +@staticInterop +@anonymous +external DomTrustedTypePolicyFactory? get trustedTypes; + +/// window.console +@JS() +@staticInterop +@anonymous +external DomConsole get console; From 0e42a9a2143f027ab947c3e0ed8dad0109e4f63e Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Mon, 23 Jan 2023 08:15:59 +0100 Subject: [PATCH 02/11] feat(core): support TrustedType --- .../firebase_core/firebase_core/example/web/index.html | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/firebase_core/firebase_core/example/web/index.html b/packages/firebase_core/firebase_core/example/web/index.html index 58971ce901ac..7ba0fe8597c6 100644 --- a/packages/firebase_core/firebase_core/example/web/index.html +++ b/packages/firebase_core/firebase_core/example/web/index.html @@ -19,10 +19,10 @@ - + /> --> Firebase Core Example @@ -36,6 +36,11 @@