From 369f0a341d5f44c917bbf81346d41a5247ef516e Mon Sep 17 00:00:00 2001 From: Harry Terkelsen Date: Thu, 21 Nov 2019 14:54:39 -0800 Subject: [PATCH 1/9] WIP on firebase_core_web --- .../firebase_core_web/CHANGELOG.md | 3 + .../firebase_core/firebase_core_web/LICENSE | 27 ++++++ .../firebase_core/firebase_core_web/README.md | 33 +++++++ .../lib/firebase_core_web.dart | 86 +++++++++++++++++++ .../lib/src/firebase_js.dart | 43 ++++++++++ .../firebase_core_web/pubspec.yaml | 32 +++++++ 6 files changed, 224 insertions(+) create mode 100644 packages/firebase_core/firebase_core_web/CHANGELOG.md create mode 100644 packages/firebase_core/firebase_core_web/LICENSE create mode 100644 packages/firebase_core/firebase_core_web/README.md create mode 100644 packages/firebase_core/firebase_core_web/lib/firebase_core_web.dart create mode 100644 packages/firebase_core/firebase_core_web/lib/src/firebase_js.dart create mode 100644 packages/firebase_core/firebase_core_web/pubspec.yaml diff --git a/packages/firebase_core/firebase_core_web/CHANGELOG.md b/packages/firebase_core/firebase_core_web/CHANGELOG.md new file mode 100644 index 000000000000..7be26166a1f2 --- /dev/null +++ b/packages/firebase_core/firebase_core_web/CHANGELOG.md @@ -0,0 +1,3 @@ +# 0.1.0 + +- Initial open-source release. diff --git a/packages/firebase_core/firebase_core_web/LICENSE b/packages/firebase_core/firebase_core_web/LICENSE new file mode 100644 index 000000000000..0c382ce171cc --- /dev/null +++ b/packages/firebase_core/firebase_core_web/LICENSE @@ -0,0 +1,27 @@ +// Copyright 2019 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. diff --git a/packages/firebase_core/firebase_core_web/README.md b/packages/firebase_core/firebase_core_web/README.md new file mode 100644 index 000000000000..42a255177ea1 --- /dev/null +++ b/packages/firebase_core/firebase_core_web/README.md @@ -0,0 +1,33 @@ +# firebase_core_web + +The web implementation of [`firebase_core`][1]. + +## Usage + +### Import the package + +To use this plugin in your Flutter app on the web, simply add it as a +dependency in your `pubspec.yaml` alongside the base `firebase_core` +plugin. + +_(This is only temporary: in the future we hope to make this package +an "endorsed" implementation of `firebase_core`, so it will automatically +be included in your app when you run your Flutter app on the web.)_ + +Add this to your `pubspec.yaml`: + +```yaml +... +dependencies: + ... + firebase_core: ^0.4.1 + firebase_core_web: ^0.1.0 + ... +``` + +### Using the plugin + +Once you have added the `firebase_core_web` dependency to your pubspec, +you can use `package:firebase_core` as normal. + +[1]: ../firebase_core/firebase_core 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 new file mode 100644 index 000000000000..eb0c8cbab34d --- /dev/null +++ b/packages/firebase_core/firebase_core_web/lib/firebase_core_web.dart @@ -0,0 +1,86 @@ +import 'dart:async'; +import 'dart:html' as html; + +import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart'; +import 'package:flutter_web_plugins/flutter_web_plugins.dart'; + +import 'src/firebase_js.dart'; + +const String _firebaseAppJs = + 'https://www.gstatic.com/firebasejs/7.4.0/firebase-app.js'; + +class FirebaseCoreWeb extends FirebaseCorePlatform { + static void registerWith(Registrar registrar) { + FirebaseCorePlatform.instance = FirebaseCoreWeb(); + } + + FirebaseCoreWeb() { + _isInitialized = _initJs(); + } + + Future _isInitialized; + + Future _initJs() { + final html.ScriptElement script = html.ScriptElement() + ..async = true + ..defer = true + ..src = _firebaseAppJs; + Completer _scriptLoaded = Completer(); + script.onLoad.first.then((_) { + _scriptLoaded.complete(); + }); + html.document.head.append(script); + return _scriptLoaded.future; + } + + @override + Future appNamed(String name) async { + await _isInitialized; + + final App jsApp = app(name); + return _createFromJsApp(jsApp); + } + + @override + Future configure(String name, FirebaseOptions options) async { + await _isInitialized; + + final App jsApp = initializeApp(_createFromFirebaseOptions(options), name); + } + + @override + Future> allApps() async { + await _isInitialized; + + List jsApps = apps; + return jsApps.map(_createFromJsApp).toList(); + } +} + +PlatformFirebaseApp _createFromJsApp(App jsApp) { + return PlatformFirebaseApp(jsApp.name, _createFromJsOptions(jsApp.options)); +} + +FirebaseOptions _createFromJsOptions(Options options) { + return FirebaseOptions( + apiKey: options.apiKey, + trackingID: options.measurementId, + gcmSenderID: options.messagingSenderId, + projectID: options.projectId, + googleAppID: options.appId, + databaseURL: options.databaseURL, + storageBucket: options.storageBucket, + ); +} + +Options _createFromFirebaseOptions(FirebaseOptions options) { + return Options( + apiKey: options.apiKey, + measurementId: options.trackingID, + messagingSenderId: options.gcmSenderID, + projectId: options.projectID, + appId: options.googleAppID, + databaseURL: options.databaseURL, + storageBucket: options.storageBucket, + ); +} diff --git a/packages/firebase_core/firebase_core_web/lib/src/firebase_js.dart b/packages/firebase_core/firebase_core_web/lib/src/firebase_js.dart new file mode 100644 index 000000000000..b5782998947d --- /dev/null +++ b/packages/firebase_core/firebase_core_web/lib/src/firebase_js.dart @@ -0,0 +1,43 @@ +@JS('firebase') +library firebase_js; + +import 'package:js/js.dart'; + +@JS() +class App { + external String get name; + external Options get options; +} + +@JS() +@anonymous +class Options { + external String get apiKey; + external String get authDomain; + external String get databaseURL; + external String get projectId; + external String get storageBucket; + external String get messagingSenderId; + external String get appId; + external String get measurementId; + + external factory Options({ + String apiKey, + String authDomain, + String databaseURL, + String projectId, + String storageBucket, + String messagingSenderId, + String appId, + String measurementId, + }); +} + +@JS() +external List get apps; + +@JS() +external App initializeApp(Options options, String name); + +@JS() +external App app(String name); diff --git a/packages/firebase_core/firebase_core_web/pubspec.yaml b/packages/firebase_core/firebase_core_web/pubspec.yaml new file mode 100644 index 000000000000..1426fdef9fce --- /dev/null +++ b/packages/firebase_core/firebase_core_web/pubspec.yaml @@ -0,0 +1,32 @@ +name: firebase_core_web +description: The web implementation of firebase_core +author: Flutter Team +homepage: https://github.com/FirebaseExtended/flutterfire/packages/firebase_core/firebase_core_web +version: 0.1.0 + +flutter: + plugin: + platforms: + web: + pluginClass: FirebaseCoreWeb + fileName: firebase_core_web.dart + +dependencies: + firebase_core_platform_interface: ^1.0.0 + flutter: + sdk: flutter + flutter_web_plugins: + sdk: flutter + meta: ^1.1.7 + js: ^0.6.1 + +dev_dependencies: + flutter_test: + sdk: flutter +# firebase_core: ^0.4.2 + firebase_core: + path: ../firebase_core + +environment: + sdk: ">=2.0.0-dev.28.0 <3.0.0" + flutter: ">=1.9.1+hotfix.2 <2.0.0" From f4b56bd406d1b6cf9bc0c3da7b47ff9bf4a46b2a Mon Sep 17 00:00:00 2001 From: Harry Terkelsen Date: Sat, 23 Nov 2019 15:00:42 -0800 Subject: [PATCH 2/9] Implement firebase_core --- .../lib/firebase_core_web.dart | 65 +++++++++---------- .../lib/src/firebase_js.dart | 4 ++ .../firebase_core_web/pubspec.yaml | 4 +- .../test/firebase_core_web_test.dart | 54 +++++++++++++++ 4 files changed, 90 insertions(+), 37 deletions(-) create mode 100644 packages/firebase_core/firebase_core_web/test/firebase_core_web_test.dart 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 eb0c8cbab34d..164c762746fa 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 @@ -1,67 +1,64 @@ +// 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 'dart:async'; import 'dart:html' as html; +import 'dart:js' as js; +import 'dart:js_util' as js_util; import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart'; import 'package:flutter_web_plugins/flutter_web_plugins.dart'; -import 'src/firebase_js.dart'; - -const String _firebaseAppJs = - 'https://www.gstatic.com/firebasejs/7.4.0/firebase-app.js'; +import 'src/firebase_js.dart' as firebase; +/// The implementation of `firebase_core` for web. class FirebaseCoreWeb extends FirebaseCorePlatform { static void registerWith(Registrar registrar) { FirebaseCorePlatform.instance = FirebaseCoreWeb(); } FirebaseCoreWeb() { - _isInitialized = _initJs(); - } - - Future _isInitialized; - - Future _initJs() { - final html.ScriptElement script = html.ScriptElement() - ..async = true - ..defer = true - ..src = _firebaseAppJs; - Completer _scriptLoaded = Completer(); - script.onLoad.first.then((_) { - _scriptLoaded.complete(); - }); - html.document.head.append(script); - return _scriptLoaded.future; + if (!js.context.hasProperty('firebase')) { + throw StateError('firebase.js has not been loaded'); + } } @override Future appNamed(String name) async { - await _isInitialized; - - final App jsApp = app(name); - return _createFromJsApp(jsApp); + try { + final firebase.App jsApp = firebase.app(name); + return _createFromJsApp(jsApp); + } catch (e) { + if (_isFirebaseError(e)) { + return null; + } + rethrow; + } } @override Future configure(String name, FirebaseOptions options) async { - await _isInitialized; - - final App jsApp = initializeApp(_createFromFirebaseOptions(options), name); + firebase.initializeApp(_createFromFirebaseOptions(options), name); } @override Future> allApps() async { - await _isInitialized; - - List jsApps = apps; + List jsApps = firebase.apps; return jsApps.map(_createFromJsApp).toList(); } } -PlatformFirebaseApp _createFromJsApp(App jsApp) { +/// Returns `true` if [e] is a `FirebaseError`. +bool _isFirebaseError(dynamic e) { + return js_util.getProperty(e, 'name') == 'FirebaseError'; +} + +PlatformFirebaseApp _createFromJsApp(firebase.App jsApp) { return PlatformFirebaseApp(jsApp.name, _createFromJsOptions(jsApp.options)); } -FirebaseOptions _createFromJsOptions(Options options) { +FirebaseOptions _createFromJsOptions(firebase.Options options) { return FirebaseOptions( apiKey: options.apiKey, trackingID: options.measurementId, @@ -73,8 +70,8 @@ FirebaseOptions _createFromJsOptions(Options options) { ); } -Options _createFromFirebaseOptions(FirebaseOptions options) { - return Options( +firebase.Options _createFromFirebaseOptions(FirebaseOptions options) { + return firebase.Options( apiKey: options.apiKey, measurementId: options.trackingID, messagingSenderId: options.gcmSenderID, diff --git a/packages/firebase_core/firebase_core_web/lib/src/firebase_js.dart b/packages/firebase_core/firebase_core_web/lib/src/firebase_js.dart index b5782998947d..a9b98d0effae 100644 --- a/packages/firebase_core/firebase_core_web/lib/src/firebase_js.dart +++ b/packages/firebase_core/firebase_core_web/lib/src/firebase_js.dart @@ -1,3 +1,7 @@ +// 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. + @JS('firebase') library firebase_js; diff --git a/packages/firebase_core/firebase_core_web/pubspec.yaml b/packages/firebase_core/firebase_core_web/pubspec.yaml index 1426fdef9fce..f45cbf22114e 100644 --- a/packages/firebase_core/firebase_core_web/pubspec.yaml +++ b/packages/firebase_core/firebase_core_web/pubspec.yaml @@ -23,9 +23,7 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter -# firebase_core: ^0.4.2 - firebase_core: - path: ../firebase_core + firebase_core: ^0.4.2 environment: sdk: ">=2.0.0-dev.28.0 <3.0.0" diff --git a/packages/firebase_core/firebase_core_web/test/firebase_core_web_test.dart b/packages/firebase_core/firebase_core_web/test/firebase_core_web_test.dart new file mode 100644 index 000000000000..1e3d3d96ec6b --- /dev/null +++ b/packages/firebase_core/firebase_core_web/test/firebase_core_web_test.dart @@ -0,0 +1,54 @@ +// 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. +@TestOn('browser') + +import 'dart:html' as html; +import 'dart:js' as js; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:firebase_core_web/firebase_core_web.dart'; +import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart'; +import 'package:firebase_core/firebase_core.dart'; + +import 'utils.dart'; + +void main() { + group('$FirebaseCoreWeb', () { + setUp(() async { + js.JsObject firebaseMock = js.JsObject.jsify({}); + js.context['firebase'] = firebaseMock; + FirebaseCorePlatform.instance = FirebaseCoreWeb(); + }); + + test('allApps() calls firebase.apps', () async { + js.context['firebase']['apps'] = js.JsArray(); + final List apps = await FirebaseApp.allApps(); + expect(apps, hasLength(0)); + }); + + test('appNamed() calls firebase.app', () async { + js.context['firebase']['app'] = js.allowInterop((String name) { + return js.JsObject.jsify({ + 'name': name, + 'options': {'appId': '123'}, + }); + }); + final FirebaseApp app = await FirebaseApp.appNamed('foo'); + expect(app.name, equals('foo')); + }); + + test('configure() calls firebase.initializeApp', () async { + js.context['firebase']['initializeApp'] = + js.allowInterop((js.JsObject options, String name) { + return js.JsObject.jsify({ + 'name': name, + 'options': options, + }); + }); + final FirebaseApp app = await FirebaseApp.configure( + name: 'foo', options: FirebaseOptions(googleAppID: '123')); + expect(app.name, equals('foo')); + }); + }); +} From e06e1c270ad3ea741f9a45cf205d134e9302ce82 Mon Sep 17 00:00:00 2001 From: Harry Terkelsen Date: Sat, 23 Nov 2019 15:20:12 -0800 Subject: [PATCH 3/9] Touch up tests in firebase_core_web --- .../firebase_core_web/pubspec.yaml | 1 - .../test/firebase_core_web_test.dart | 25 +++++++++++-------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/packages/firebase_core/firebase_core_web/pubspec.yaml b/packages/firebase_core/firebase_core_web/pubspec.yaml index f45cbf22114e..e6f6ec139c24 100644 --- a/packages/firebase_core/firebase_core_web/pubspec.yaml +++ b/packages/firebase_core/firebase_core_web/pubspec.yaml @@ -23,7 +23,6 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - firebase_core: ^0.4.2 environment: sdk: ">=2.0.0-dev.28.0 <3.0.0" diff --git a/packages/firebase_core/firebase_core_web/test/firebase_core_web_test.dart b/packages/firebase_core/firebase_core_web/test/firebase_core_web_test.dart index 1e3d3d96ec6b..a1c61240bdce 100644 --- a/packages/firebase_core/firebase_core_web/test/firebase_core_web_test.dart +++ b/packages/firebase_core/firebase_core_web/test/firebase_core_web_test.dart @@ -9,21 +9,19 @@ import 'dart:js' as js; import 'package:flutter_test/flutter_test.dart'; import 'package:firebase_core_web/firebase_core_web.dart'; import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart'; -import 'package:firebase_core/firebase_core.dart'; - -import 'utils.dart'; void main() { group('$FirebaseCoreWeb', () { + FirebaseCoreWeb firebaseCoreWeb; setUp(() async { js.JsObject firebaseMock = js.JsObject.jsify({}); js.context['firebase'] = firebaseMock; - FirebaseCorePlatform.instance = FirebaseCoreWeb(); + firebaseCoreWeb = FirebaseCoreWeb(); }); test('allApps() calls firebase.apps', () async { - js.context['firebase']['apps'] = js.JsArray(); - final List apps = await FirebaseApp.allApps(); + js.context['firebase']['apps'] = js.JsArray(); + final List apps = await firebaseCoreWeb.allApps(); expect(apps, hasLength(0)); }); @@ -34,21 +32,28 @@ void main() { 'options': {'appId': '123'}, }); }); - final FirebaseApp app = await FirebaseApp.appNamed('foo'); + final PlatformFirebaseApp app = await firebaseCoreWeb.appNamed('foo'); expect(app.name, equals('foo')); + expect(app.options.googleAppID, equals('123')); }); test('configure() calls firebase.initializeApp', () async { + String appName; + js.JsObject appOptions; + js.context['firebase']['initializeApp'] = js.allowInterop((js.JsObject options, String name) { + appName = name; + appOptions = options; return js.JsObject.jsify({ 'name': name, 'options': options, }); }); - final FirebaseApp app = await FirebaseApp.configure( - name: 'foo', options: FirebaseOptions(googleAppID: '123')); - expect(app.name, equals('foo')); + firebaseCoreWeb.configure( + 'foo', const FirebaseOptions(googleAppID: '123')); + expect(appName, equals('foo')); + expect(appOptions['appId'], equals('123')); }); }); } From 873010e09c2d1d217c561adc42b6c1299dadb8ff Mon Sep 17 00:00:00 2001 From: Harry Terkelsen Date: Sat, 23 Nov 2019 15:29:11 -0800 Subject: [PATCH 4/9] Update README.md to include instructions to add js script --- .../firebase_core/firebase_core_web/README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/packages/firebase_core/firebase_core_web/README.md b/packages/firebase_core/firebase_core_web/README.md index 42a255177ea1..87303f0375f6 100644 --- a/packages/firebase_core/firebase_core_web/README.md +++ b/packages/firebase_core/firebase_core_web/README.md @@ -25,9 +25,27 @@ dependencies: ... ``` +### Updating `index.html` + +Due to [this bug in dartdevc][2], you will need to manually add the Firebase +JavaScript file to you `index.html` file. + +In your app directory, edit `web/index.html` to add the line: + +```html + + ... + + + + + +``` + ### Using the plugin Once you have added the `firebase_core_web` dependency to your pubspec, you can use `package:firebase_core` as normal. [1]: ../firebase_core/firebase_core +[2]: https://github.com/dart-lang/sdk/issues/33979 From 76d924586720799a55de597cbcaae461a697c0f8 Mon Sep 17 00:00:00 2001 From: Harry Terkelsen Date: Sat, 23 Nov 2019 16:04:57 -0800 Subject: [PATCH 5/9] Fix analyzer errors --- .../lib/firebase_core_web.dart | 11 +++++------ .../firebase_core_web/lib/src/firebase_js.dart | 18 +++++++++--------- .../test/firebase_core_web_test.dart | 3 +-- 3 files changed, 15 insertions(+), 17 deletions(-) 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 164c762746fa..56bc11ed7af3 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 @@ -3,7 +3,6 @@ // found in the LICENSE file. import 'dart:async'; -import 'dart:html' as html; import 'dart:js' as js; import 'dart:js_util' as js_util; @@ -14,16 +13,16 @@ import 'src/firebase_js.dart' as firebase; /// The implementation of `firebase_core` for web. class FirebaseCoreWeb extends FirebaseCorePlatform { - static void registerWith(Registrar registrar) { - FirebaseCorePlatform.instance = FirebaseCoreWeb(); - } - FirebaseCoreWeb() { if (!js.context.hasProperty('firebase')) { throw StateError('firebase.js has not been loaded'); } } + static void registerWith(Registrar registrar) { + FirebaseCorePlatform.instance = FirebaseCoreWeb(); + } + @override Future appNamed(String name) async { try { @@ -44,7 +43,7 @@ class FirebaseCoreWeb extends FirebaseCorePlatform { @override Future> allApps() async { - List jsApps = firebase.apps; + final List jsApps = firebase.apps; return jsApps.map(_createFromJsApp).toList(); } } diff --git a/packages/firebase_core/firebase_core_web/lib/src/firebase_js.dart b/packages/firebase_core/firebase_core_web/lib/src/firebase_js.dart index a9b98d0effae..167e629f7fa3 100644 --- a/packages/firebase_core/firebase_core_web/lib/src/firebase_js.dart +++ b/packages/firebase_core/firebase_core_web/lib/src/firebase_js.dart @@ -16,15 +16,6 @@ class App { @JS() @anonymous class Options { - external String get apiKey; - external String get authDomain; - external String get databaseURL; - external String get projectId; - external String get storageBucket; - external String get messagingSenderId; - external String get appId; - external String get measurementId; - external factory Options({ String apiKey, String authDomain, @@ -35,6 +26,15 @@ class Options { String appId, String measurementId, }); + + external String get apiKey; + external String get authDomain; + external String get databaseURL; + external String get projectId; + external String get storageBucket; + external String get messagingSenderId; + external String get appId; + external String get measurementId; } @JS() diff --git a/packages/firebase_core/firebase_core_web/test/firebase_core_web_test.dart b/packages/firebase_core/firebase_core_web/test/firebase_core_web_test.dart index a1c61240bdce..0f78ae78cf1a 100644 --- a/packages/firebase_core/firebase_core_web/test/firebase_core_web_test.dart +++ b/packages/firebase_core/firebase_core_web/test/firebase_core_web_test.dart @@ -3,7 +3,6 @@ // found in the LICENSE file. @TestOn('browser') -import 'dart:html' as html; import 'dart:js' as js; import 'package:flutter_test/flutter_test.dart'; @@ -14,7 +13,7 @@ void main() { group('$FirebaseCoreWeb', () { FirebaseCoreWeb firebaseCoreWeb; setUp(() async { - js.JsObject firebaseMock = js.JsObject.jsify({}); + final js.JsObject firebaseMock = js.JsObject.jsify({}); js.context['firebase'] = firebaseMock; firebaseCoreWeb = FirebaseCoreWeb(); }); From 43ca6773d489ee79cc78fa9fb308fe8fad3dcc6a Mon Sep 17 00:00:00 2001 From: Harry Terkelsen Date: Tue, 26 Nov 2019 17:57:26 -0800 Subject: [PATCH 6/9] Update tests --- .../lib/firebase_core_web.dart | 22 +++++---- .../lib/src/firebase_js.dart | 13 +++--- .../firebase_core_web/pubspec.yaml | 1 + .../test/firebase_core_web_test.dart | 46 ++++++++++++------- 4 files changed, 50 insertions(+), 32 deletions(-) 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 56bc11ed7af3..671acc6619c3 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 @@ -3,18 +3,17 @@ // found in the LICENSE file. import 'dart:async'; -import 'dart:js' as js; -import 'dart:js_util' as js_util; import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart'; import 'package:flutter_web_plugins/flutter_web_plugins.dart'; +import 'package:js/js_util.dart' as js_util; -import 'src/firebase_js.dart' as firebase; +import 'src/firebase_js.dart'; /// The implementation of `firebase_core` for web. class FirebaseCoreWeb extends FirebaseCorePlatform { FirebaseCoreWeb() { - if (!js.context.hasProperty('firebase')) { + if (firebase == null) { throw StateError('firebase.js has not been loaded'); } } @@ -26,7 +25,10 @@ class FirebaseCoreWeb extends FirebaseCorePlatform { @override Future appNamed(String name) async { try { - final firebase.App jsApp = firebase.app(name); + final App jsApp = firebase.app(name); + if (jsApp == null) { + return null; + } return _createFromJsApp(jsApp); } catch (e) { if (_isFirebaseError(e)) { @@ -43,7 +45,7 @@ class FirebaseCoreWeb extends FirebaseCorePlatform { @override Future> allApps() async { - final List jsApps = firebase.apps; + final List jsApps = firebase.apps; return jsApps.map(_createFromJsApp).toList(); } } @@ -53,11 +55,11 @@ bool _isFirebaseError(dynamic e) { return js_util.getProperty(e, 'name') == 'FirebaseError'; } -PlatformFirebaseApp _createFromJsApp(firebase.App jsApp) { +PlatformFirebaseApp _createFromJsApp(App jsApp) { return PlatformFirebaseApp(jsApp.name, _createFromJsOptions(jsApp.options)); } -FirebaseOptions _createFromJsOptions(firebase.Options options) { +FirebaseOptions _createFromJsOptions(Options options) { return FirebaseOptions( apiKey: options.apiKey, trackingID: options.measurementId, @@ -69,8 +71,8 @@ FirebaseOptions _createFromJsOptions(firebase.Options options) { ); } -firebase.Options _createFromFirebaseOptions(FirebaseOptions options) { - return firebase.Options( +Options _createFromFirebaseOptions(FirebaseOptions options) { + return Options( apiKey: options.apiKey, measurementId: options.trackingID, messagingSenderId: options.gcmSenderID, diff --git a/packages/firebase_core/firebase_core_web/lib/src/firebase_js.dart b/packages/firebase_core/firebase_core_web/lib/src/firebase_js.dart index 167e629f7fa3..54e5041835fc 100644 --- a/packages/firebase_core/firebase_core_web/lib/src/firebase_js.dart +++ b/packages/firebase_core/firebase_core_web/lib/src/firebase_js.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -@JS('firebase') +@JS() library firebase_js; import 'package:js/js.dart'; @@ -38,10 +38,11 @@ class Options { } @JS() -external List get apps; - -@JS() -external App initializeApp(Options options, String name); +class FirebaseCore { + external List get apps; + external App initializeApp(Options options, String name); + external App app(String name); +} @JS() -external App app(String name); +external FirebaseCore get firebase; diff --git a/packages/firebase_core/firebase_core_web/pubspec.yaml b/packages/firebase_core/firebase_core_web/pubspec.yaml index e6f6ec139c24..ca39fd5d1b8f 100644 --- a/packages/firebase_core/firebase_core_web/pubspec.yaml +++ b/packages/firebase_core/firebase_core_web/pubspec.yaml @@ -23,6 +23,7 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter + firebase_core: ^0.4.2+1 environment: sdk: ">=2.0.0-dev.28.0 <3.0.0" diff --git a/packages/firebase_core/firebase_core_web/test/firebase_core_web_test.dart b/packages/firebase_core/firebase_core_web/test/firebase_core_web_test.dart index 0f78ae78cf1a..f2bd164a07b4 100644 --- a/packages/firebase_core/firebase_core_web/test/firebase_core_web_test.dart +++ b/packages/firebase_core/firebase_core_web/test/firebase_core_web_test.dart @@ -6,53 +6,67 @@ import 'dart:js' as js; import 'package:flutter_test/flutter_test.dart'; +import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_core_web/firebase_core_web.dart'; import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart'; void main() { group('$FirebaseCoreWeb', () { - FirebaseCoreWeb firebaseCoreWeb; setUp(() async { final js.JsObject firebaseMock = js.JsObject.jsify({}); js.context['firebase'] = firebaseMock; - firebaseCoreWeb = FirebaseCoreWeb(); + FirebaseCorePlatform.instance = FirebaseCoreWeb(); }); - test('allApps() calls firebase.apps', () async { + test('FirebaseApp.allApps() calls firebase.apps', () async { js.context['firebase']['apps'] = js.JsArray(); - final List apps = await firebaseCoreWeb.allApps(); + final List apps = await FirebaseApp.allApps(); expect(apps, hasLength(0)); }); - test('appNamed() calls firebase.app', () async { + test('FirebaseApp.appNamed() calls firebase.app', () async { js.context['firebase']['app'] = js.allowInterop((String name) { return js.JsObject.jsify({ 'name': name, 'options': {'appId': '123'}, }); }); - final PlatformFirebaseApp app = await firebaseCoreWeb.appNamed('foo'); + final FirebaseApp app = await FirebaseApp.appNamed('foo'); expect(app.name, equals('foo')); - expect(app.options.googleAppID, equals('123')); + + final FirebaseOptions options = await app.options; + expect(options.googleAppID, equals('123')); }); - test('configure() calls firebase.initializeApp', () async { - String appName; - js.JsObject appOptions; + test('FirebaseApp.configure() calls firebase.initializeApp', () async { + bool appConfigured = false; + js.context['firebase']['app'] = js.allowInterop((String name) { + if (appConfigured) { + return js.JsObject.jsify({ + 'name': name, + 'options': {'appId': '123'}, + }); + } else { + return null; + } + }); js.context['firebase']['initializeApp'] = js.allowInterop((js.JsObject options, String name) { - appName = name; - appOptions = options; + appConfigured = true; return js.JsObject.jsify({ 'name': name, 'options': options, }); }); - firebaseCoreWeb.configure( - 'foo', const FirebaseOptions(googleAppID: '123')); - expect(appName, equals('foo')); - expect(appOptions['appId'], equals('123')); + final FirebaseApp app = await FirebaseApp.configure( + name: 'foo', + options: const FirebaseOptions(googleAppID: '123'), + ); + expect(app.name, equals('foo')); + + final FirebaseOptions options = await app.options; + expect(options.googleAppID, equals('123')); }); }); } From e91ae463fb5ea25a6a26420295b00f9e362a2c23 Mon Sep 17 00:00:00 2001 From: Harry Terkelsen Date: Wed, 27 Nov 2019 10:20:10 -0800 Subject: [PATCH 7/9] Add documentation --- .../lib/src/firebase_js.dart | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/packages/firebase_core/firebase_core_web/lib/src/firebase_js.dart b/packages/firebase_core/firebase_core_web/lib/src/firebase_js.dart index 54e5041835fc..0d3a7281e5a1 100644 --- a/packages/firebase_core/firebase_core_web/lib/src/firebase_js.dart +++ b/packages/firebase_core/firebase_core_web/lib/src/firebase_js.dart @@ -7,15 +7,21 @@ library firebase_js; import 'package:js/js.dart'; +/// A Firebase app. @JS() class App { + /// The name of the app. external String get name; + + /// The options that the app was configured with. external Options get options; } +/// Options for configuring an app. @JS() @anonymous class Options { + /// Creates an options JavaScript object. external factory Options({ String apiKey, String authDomain, @@ -27,22 +33,44 @@ class Options { String measurementId, }); + /// The API key used to authenticate requests. external String get apiKey; + + /// Domain for authentication. external String get authDomain; + + /// Realtime Database URL. external String get databaseURL; + + /// The Google Cloud project ID. external String get projectId; + + /// The Google Cloud Storage bucket name. external String get storageBucket; + + /// The project number used to configure Messaging. external String get messagingSenderId; + + /// The Google App ID that uniquely identifies an app instance. external String get appId; + + /// An ID used for analytics. external String get measurementId; } +/// The `firebase` namespace. @JS() class FirebaseCore { + /// Returns a list of initialized apps. external List get apps; + + /// Initializes the app named [name] with the given [options]. external App initializeApp(Options options, String name); + + /// Returns the already-initialized app with the given [name]. external App app(String name); } +/// Return the `firebase` object. @JS() external FirebaseCore get firebase; From c5cdc10f3bbb3e267a99c6f71b9f51e67c3c999f Mon Sep 17 00:00:00 2001 From: Harry Terkelsen Date: Wed, 27 Nov 2019 10:30:57 -0800 Subject: [PATCH 8/9] Add more docs. Dartfmt --- .../firebase_core/firebase_core_web/lib/firebase_core_web.dart | 2 ++ .../firebase_core/firebase_core_web/lib/src/firebase_js.dart | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) 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 671acc6619c3..75ae87075aa6 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 @@ -12,12 +12,14 @@ import 'src/firebase_js.dart'; /// The implementation of `firebase_core` for web. class FirebaseCoreWeb extends FirebaseCorePlatform { + /// Creates a new instance of [FirebaseCoreWeb]. FirebaseCoreWeb() { if (firebase == null) { throw StateError('firebase.js has not been loaded'); } } + /// Registers that [FirebaseCoreWeb] is the platform implementation. static void registerWith(Registrar registrar) { FirebaseCorePlatform.instance = FirebaseCoreWeb(); } diff --git a/packages/firebase_core/firebase_core_web/lib/src/firebase_js.dart b/packages/firebase_core/firebase_core_web/lib/src/firebase_js.dart index 0d3a7281e5a1..d7323c874b27 100644 --- a/packages/firebase_core/firebase_core_web/lib/src/firebase_js.dart +++ b/packages/firebase_core/firebase_core_web/lib/src/firebase_js.dart @@ -66,7 +66,7 @@ class FirebaseCore { /// Initializes the app named [name] with the given [options]. external App initializeApp(Options options, String name); - + /// Returns the already-initialized app with the given [name]. external App app(String name); } From 19165d912057ae98e29261d52979c6b47fad55ea Mon Sep 17 00:00:00 2001 From: Harry Terkelsen Date: Wed, 27 Nov 2019 15:53:42 -0800 Subject: [PATCH 9/9] Add dummy podspec so ios doesn't break --- .../ios/firebase_core_web.podspec | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 packages/firebase_core/firebase_core_web/ios/firebase_core_web.podspec diff --git a/packages/firebase_core/firebase_core_web/ios/firebase_core_web.podspec b/packages/firebase_core/firebase_core_web/ios/firebase_core_web.podspec new file mode 100644 index 000000000000..c6e11ef16e16 --- /dev/null +++ b/packages/firebase_core/firebase_core_web/ios/firebase_core_web.podspec @@ -0,0 +1,21 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html +# +Pod::Spec.new do |s| + s.name = 'firebase_core_web' + s.version = '0.1.0' + s.summary = 'No-op implementation of firebase_core_web web plugin to avoid build issues on iOS' + s.description = <<-DESC + temp fake google_sign_in_web plugin + DESC + s.homepage = 'https://github.com/FirebaseExtended/flutterfire/tree/master/packages/firebase_core/firebase_core_web' + s.license = { :file => '../LICENSE' } + s.author = { 'Flutter Team' => 'flutter-dev@googlegroups.com' } + s.source = { :path => '.' } + s.source_files = 'Classes/**/*' + s.public_header_files = 'Classes/**/*.h' + s.dependency 'Flutter' + + s.ios.deployment_target = '8.0' + end +