Skip to content

Commit 09d03aa

Browse files
authored
fix: a bug with the demoProjectId arg to Firebase.initializeApp() (#17703)
1 parent 4e7f800 commit 09d03aa

File tree

3 files changed

+63
-14
lines changed

3 files changed

+63
-14
lines changed

packages/firebase_core/firebase_core/lib/src/firebase.dart

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,15 @@ class Firebase {
2828
return _delegate.apps.map(FirebaseApp._).toList(growable: false);
2929
}
3030

31-
/// Initializes a new [FirebaseApp] instance by [name] and [options] and returns
32-
/// the created app. This method should be called before any usage of FlutterFire plugins.
31+
/// Initializes a new [FirebaseApp] instance by [name] and [options] and
32+
/// returns the created app. This method should be called before any usage of
33+
/// FlutterFire plugins.
34+
///
35+
/// If a [demoProjectId] is provided, a new [FirebaseApp] instance will be
36+
/// initialized with a set of default options for demo projects, overriding
37+
/// the [options] argument. If no [name] is provided alongside a
38+
/// [demoProjectId], the [demoProjectId] will be used as the app name. By
39+
/// convention, the [demoProjectId] should begin with "demo-".
3340
///
3441
/// The default app instance can be initialized here simply by passing no "name" as an argument
3542
/// in both Dart & manual initialization flows.
@@ -52,16 +59,21 @@ class Firebase {
5259
// We use 'web' as the default platform for unknown platforms.
5360
platformString = 'web';
5461
}
55-
FirebaseAppPlatform app = await _delegate.initializeApp(
56-
options: FirebaseOptions(
57-
apiKey: '',
58-
appId: '1:1:$platformString:1',
59-
messagingSenderId: '',
60-
projectId: demoProjectId,
61-
),
62+
// A name must be set, otherwise [DEFAULT] will be used and the options
63+
// we've provided will be ignored if any platform specific configuration
64+
// files exist (i.e. GoogleService-Info.plist for iOS).
65+
name ??= demoProjectId;
66+
// The user should not set any options if they specify a demo project
67+
// id, but it was allowed when this API was first added, so we allow it
68+
// for backwards compatibility and simply override the user-provided
69+
// options.
70+
options = FirebaseOptions(
71+
apiKey: '12345',
72+
appId: '1:1:$platformString:1',
73+
messagingSenderId: '',
74+
projectId: demoProjectId,
6275
);
63-
64-
return FirebaseApp._(app);
76+
// Now fall through to the normal initialization logic.
6577
}
6678
FirebaseAppPlatform app = await _delegate.initializeApp(
6779
name: name,

packages/firebase_core/firebase_core/test/firebase_core_test.dart

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,45 @@ void main() {
6565
]);
6666
});
6767
});
68+
69+
test('.initializeApp() with demoProjectId', () async {
70+
const String demoProjectId = 'demo-project-id';
71+
const String expectedName = demoProjectId;
72+
const FirebaseOptions expectedOptions = FirebaseOptions(
73+
apiKey: '12345',
74+
// Flutter tests use android as the default platform.
75+
appId: '1:1:android:1',
76+
messagingSenderId: '',
77+
projectId: demoProjectId,
78+
);
79+
80+
final mock = MockFirebaseCore();
81+
Firebase.delegatePackingProperty = mock;
82+
83+
final FirebaseAppPlatform platformApp =
84+
FirebaseAppPlatform(expectedName, expectedOptions);
85+
86+
when(mock.apps).thenReturn([platformApp]);
87+
when(mock.app(expectedName)).thenReturn(platformApp);
88+
when(mock.initializeApp(name: expectedName, options: expectedOptions))
89+
.thenAnswer((_) => Future.value(platformApp));
90+
91+
// Initialize the app with only a demo project id. The implementation will
92+
// set the name and options accordingly.
93+
FirebaseApp initializedApp = await Firebase.initializeApp(
94+
demoProjectId: demoProjectId,
95+
);
96+
FirebaseApp app = Firebase.app(expectedName);
97+
98+
expect(initializedApp, app);
99+
verifyInOrder([
100+
mock.initializeApp(
101+
name: expectedName,
102+
options: expectedOptions,
103+
),
104+
mock.app(expectedName),
105+
]);
106+
});
68107
}
69108

70109
class MockFirebaseCore extends Mock

packages/firebase_core/firebase_core_platform_interface/lib/src/method_channel/method_channel_firebase.dart

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,7 @@ class MethodChannelFirebase extends FirebasePlatform {
121121
// check to see if options are roughly identical (so we don't unnecessarily
122122
// throw on minor differences such as platform specific keys missing
123123
// e.g. hot reloads/restarts).
124-
if (defaultApp != null &&
125-
_options != null &&
126-
!_options.projectId.startsWith('demo-')) {
124+
if (defaultApp != null && _options != null) {
127125
if (_options.apiKey != defaultApp.options.apiKey ||
128126
(_options.databaseURL != null &&
129127
_options.databaseURL != defaultApp.options.databaseURL) ||

0 commit comments

Comments
 (0)