Skip to content

Commit dea12ce

Browse files
committed
fix: cache GoogleProvider in state to prevent double initWithParams on web
On web, GoogleSignIn calls initWithParams eagerly in its constructor. The provider getter previously created a new GoogleProvider (and thus a new GoogleSignIn) on every access, and build() called it twice — once for AuthFlowBuilder and once for OAuthProviderButtonBase. Both called initWithParams on the singleton GoogleSignInPlugin, triggering a 'Future already completed' race condition. Fix: convert _GoogleSignInButton to StatefulWidget and create the GoogleProvider once in initState.
1 parent 405bbe7 commit dea12ce

1 file changed

Lines changed: 29 additions & 21 deletions

File tree

packages/firebase_ui_oauth_google/lib/firebase_ui_oauth_google.dart

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ void setMockGoogleProvider(GoogleProvider provider) {
6060
_mockProvider = provider;
6161
}
6262

63-
class _GoogleSignInButton extends StatelessWidget {
63+
class _GoogleSignInButton extends StatefulWidget {
6464
final String label;
6565
final Widget loadingIndicator;
6666
final void Function()? onTap;
@@ -102,37 +102,45 @@ class _GoogleSignInButton extends StatelessWidget {
102102
overrideDefaultTapAction = overrideDefaultTapAction ?? false,
103103
size = size ?? 19;
104104

105-
GoogleProvider get provider {
106-
if (_mockProvider != null) return _mockProvider!;
105+
@override
106+
State<_GoogleSignInButton> createState() => _GoogleSignInButtonState();
107+
}
107108

108-
return GoogleProvider(
109-
clientId: clientId,
110-
redirectUri: redirectUri,
111-
scopes: scopes ?? [],
112-
);
109+
class _GoogleSignInButtonState extends State<_GoogleSignInButton> {
110+
late final GoogleProvider _provider;
111+
112+
@override
113+
void initState() {
114+
super.initState();
115+
_provider = _mockProvider ??
116+
GoogleProvider(
117+
clientId: widget.clientId,
118+
redirectUri: widget.redirectUri,
119+
scopes: widget.scopes ?? [],
120+
);
113121
}
114122

115123
@override
116124
Widget build(BuildContext context) {
117125
return AuthFlowBuilder<OAuthController>(
118-
provider: provider,
119-
action: action,
120-
auth: auth,
126+
provider: _provider,
127+
action: widget.action,
128+
auth: widget.auth,
121129
builder: (context, state, ctrl, child) {
122130
return OAuthProviderButtonBase(
123-
provider: provider,
124-
label: label,
131+
provider: _provider,
132+
label: widget.label,
125133
onTap: () => ctrl.signIn(Theme.of(context).platform),
126-
loadingIndicator: loadingIndicator,
134+
loadingIndicator: widget.loadingIndicator,
127135
isLoading: state is SigningIn || state is CredentialReceived,
128-
action: action,
129-
auth: auth ?? fba.FirebaseAuth.instance,
130-
onDifferentProvidersFound: onDifferentProvidersFound,
131-
onSignedIn: onSignedIn,
136+
action: widget.action,
137+
auth: widget.auth ?? fba.FirebaseAuth.instance,
138+
onDifferentProvidersFound: widget.onDifferentProvidersFound,
139+
onSignedIn: widget.onSignedIn,
132140
overrideDefaultTapAction: true,
133-
size: size,
134-
onError: onError,
135-
onCancelled: onCanceled,
141+
size: widget.size,
142+
onError: widget.onError,
143+
onCancelled: widget.onCanceled,
136144
);
137145
},
138146
);

0 commit comments

Comments
 (0)