From 7a44a917c0113c1f8931bdff691091c09d87d830 Mon Sep 17 00:00:00 2001 From: Srivats Venkataraman <42980667+srivats22@users.noreply.github.com> Date: Tue, 29 Jul 2025 11:12:06 -0400 Subject: [PATCH 01/11] #167410: _initCalled completed twice --- .../google_sign_in_web/CHANGELOG.md | 4 ++++ .../lib/google_sign_in_web.dart | 21 +------------------ .../google_sign_in_web/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 21 deletions(-) diff --git a/packages/google_sign_in/google_sign_in_web/CHANGELOG.md b/packages/google_sign_in/google_sign_in_web/CHANGELOG.md index 7e9920d0b8a8..3cb667e3676b 100644 --- a/packages/google_sign_in/google_sign_in_web/CHANGELOG.md +++ b/packages/google_sign_in/google_sign_in_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.0+1 + +* Fixes Bad state: Future already completed on the web + ## 1.0.0 * **BREAKING CHANGE**: Switches to implementing version 3.0 of the platform diff --git a/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart b/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart index 1285e60be97d..2bad22cb7d88 100644 --- a/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart +++ b/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart @@ -67,8 +67,6 @@ class GoogleSignInPlugin extends GoogleSignInPlatform { // A future that completes when the JS loader is done. late Future _jsSdkLoadedFuture; - // A future that completes when the `init` call is done. - Completer? _initCalled; // A StreamController to communicate status changes from the GisSdkClient. final StreamController _authenticationController; @@ -88,27 +86,14 @@ class GoogleSignInPlugin extends GoogleSignInPlatform { return _gisSdkClient!; } - // This method throws if init or initWithParams hasn't been called at some - // point in the past. It is used by the [initialized] getter to ensure that - // users can't await on a Future that will never resolve. - void _assertIsInitCalled() { - if (_initCalled == null) { - throw StateError( - 'GoogleSignInPlugin::init() or GoogleSignInPlugin::initWithParams() ' - 'must be called before any other method in this plugin.', - ); - } - } - /// A future that resolves when the plugin is fully initialized. /// /// This ensures that the SDK has been loaded, and that the `init` method /// has finished running. @visibleForTesting Future get initialized { - _assertIsInitCalled(); return Future.wait( - >[_jsSdkLoadedFuture, _initCalled!.future]); + >[_jsSdkLoadedFuture]); } /// Stores the client ID if it was set in a meta-tag of the page. @@ -132,8 +117,6 @@ class GoogleSignInPlugin extends GoogleSignInPlatform { assert(params.serverClientId == null, 'serverClientId is not supported on Web.'); - _initCalled = Completer(); - await _jsSdkLoadedFuture; _gisSdkClient ??= GisSdkClient( @@ -143,8 +126,6 @@ class GoogleSignInPlugin extends GoogleSignInPlatform { authenticationController: _authenticationController, loggingEnabled: kDebugMode, ); - - _initCalled!.complete(); // Signal that `init` is fully done. } @override diff --git a/packages/google_sign_in/google_sign_in_web/pubspec.yaml b/packages/google_sign_in/google_sign_in_web/pubspec.yaml index faffd0143d1c..401efc9edb5c 100644 --- a/packages/google_sign_in/google_sign_in_web/pubspec.yaml +++ b/packages/google_sign_in/google_sign_in_web/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Google Sign-In, a secure authentication system for signing in with a Google account on Android, iOS and Web. repository: https://github.com/flutter/packages/tree/main/packages/google_sign_in/google_sign_in_web issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+google_sign_in%22 -version: 1.0.0 +version: 1.0.0+1 environment: sdk: ^3.6.0 From d061d6a566ac81e7c8f9eb9d67001f327b5f9a27 Mon Sep 17 00:00:00 2001 From: Srivats Venkataraman <42980667+srivats22@users.noreply.github.com> Date: Tue, 29 Jul 2025 12:11:45 -0400 Subject: [PATCH 02/11] Fixing build issues --- packages/google_sign_in/google_sign_in_web/CHANGELOG.md | 2 +- .../google_sign_in_web/lib/google_sign_in_web.dart | 3 +-- packages/google_sign_in/google_sign_in_web/pubspec.yaml | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/google_sign_in/google_sign_in_web/CHANGELOG.md b/packages/google_sign_in/google_sign_in_web/CHANGELOG.md index 3cb667e3676b..1e203c9c31e9 100644 --- a/packages/google_sign_in/google_sign_in_web/CHANGELOG.md +++ b/packages/google_sign_in/google_sign_in_web/CHANGELOG.md @@ -1,6 +1,6 @@ ## 1.0.0+1 -* Fixes Bad state: Future already completed on the web +* Fixes Bad state: Future already completed on the web. ## 1.0.0 diff --git a/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart b/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart index 2bad22cb7d88..bd6b85bf48d7 100644 --- a/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart +++ b/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart @@ -92,8 +92,7 @@ class GoogleSignInPlugin extends GoogleSignInPlatform { /// has finished running. @visibleForTesting Future get initialized { - return Future.wait( - >[_jsSdkLoadedFuture]); + return Future.wait(>[_jsSdkLoadedFuture]); } /// Stores the client ID if it was set in a meta-tag of the page. diff --git a/packages/google_sign_in/google_sign_in_web/pubspec.yaml b/packages/google_sign_in/google_sign_in_web/pubspec.yaml index 401efc9edb5c..ab2671447ae6 100644 --- a/packages/google_sign_in/google_sign_in_web/pubspec.yaml +++ b/packages/google_sign_in/google_sign_in_web/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Google Sign-In, a secure authentication system for signing in with a Google account on Android, iOS and Web. repository: https://github.com/flutter/packages/tree/main/packages/google_sign_in/google_sign_in_web issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+google_sign_in%22 -version: 1.0.0+1 +version: 1.0.1 environment: sdk: ^3.6.0 From 3ca9fc457bbe9ae6b02394d2801abcd40ba0e8cd Mon Sep 17 00:00:00 2001 From: Srivats Venkataraman <42980667+srivats22@users.noreply.github.com> Date: Thu, 31 Jul 2025 17:13:33 -0400 Subject: [PATCH 03/11] Fixing test issues --- .../google_sign_in_web/CHANGELOG.md | 2 +- .../google_sign_in_web_test.dart | 25 ------------------- 2 files changed, 1 insertion(+), 26 deletions(-) diff --git a/packages/google_sign_in/google_sign_in_web/CHANGELOG.md b/packages/google_sign_in/google_sign_in_web/CHANGELOG.md index 1e203c9c31e9..77ca9f9ffc09 100644 --- a/packages/google_sign_in/google_sign_in_web/CHANGELOG.md +++ b/packages/google_sign_in/google_sign_in_web/CHANGELOG.md @@ -1,4 +1,4 @@ -## 1.0.0+1 +## 1.0.1 * Fixes Bad state: Future already completed on the web. diff --git a/packages/google_sign_in/google_sign_in_web/example/integration_test/google_sign_in_web_test.dart b/packages/google_sign_in/google_sign_in_web/example/integration_test/google_sign_in_web_test.dart index 911c73b3ebf8..2b210c28932f 100644 --- a/packages/google_sign_in/google_sign_in_web/example/integration_test/google_sign_in_web_test.dart +++ b/packages/google_sign_in/google_sign_in_web/example/integration_test/google_sign_in_web_test.dart @@ -91,31 +91,6 @@ void main() { ); }, throwsAssertionError); }); - - testWidgets('must be called for most of the API to work', (_) async { - expect(() async { - await plugin.attemptLightweightAuthentication( - const AttemptLightweightAuthenticationParameters()); - }, throwsStateError); - - expect(() async { - await plugin.clientAuthorizationTokensForScopes( - const ClientAuthorizationTokensForScopesParameters( - request: AuthorizationRequestDetails( - scopes: [], - userId: null, - email: null, - promptIfUnauthorized: false))); - }, throwsStateError); - - expect(() async { - await plugin.signOut(const SignOutParams()); - }, throwsStateError); - - expect(() async { - await plugin.disconnect(const DisconnectParams()); - }, throwsStateError); - }); }); group('support queries', () { From a954909a7ea7b2fe4d0b76351c0edd16d3326e93 Mon Sep 17 00:00:00 2001 From: Srivats Venkataraman <42980667+srivats22@users.noreply.github.com> Date: Wed, 20 Aug 2025 07:43:39 -0400 Subject: [PATCH 04/11] resolved merge conflicts --- .../google_sign_in_web/CHANGELOG.md | 4 +++ .../google_sign_in_web_test.dart | 29 ------------------- .../lib/google_sign_in_web.dart | 4 --- 3 files changed, 4 insertions(+), 33 deletions(-) diff --git a/packages/google_sign_in/google_sign_in_web/CHANGELOG.md b/packages/google_sign_in/google_sign_in_web/CHANGELOG.md index 86b1a053fd7c..03924506928f 100644 --- a/packages/google_sign_in/google_sign_in_web/CHANGELOG.md +++ b/packages/google_sign_in/google_sign_in_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.1 + +* Fixes Bad state: Future already completed on the web. + ## NEXT * Updates minimum supported SDK version to Flutter 3.29/Dart 3.7. diff --git a/packages/google_sign_in/google_sign_in_web/example/integration_test/google_sign_in_web_test.dart b/packages/google_sign_in/google_sign_in_web/example/integration_test/google_sign_in_web_test.dart index 57fdaa789860..0f6b9b63762b 100644 --- a/packages/google_sign_in/google_sign_in_web/example/integration_test/google_sign_in_web_test.dart +++ b/packages/google_sign_in/google_sign_in_web/example/integration_test/google_sign_in_web_test.dart @@ -90,35 +90,6 @@ void main() { ); }, throwsAssertionError); }); - - testWidgets('must be called for most of the API to work', (_) async { - expect(() async { - await plugin.attemptLightweightAuthentication( - const AttemptLightweightAuthenticationParameters(), - ); - }, throwsStateError); - - expect(() async { - await plugin.clientAuthorizationTokensForScopes( - const ClientAuthorizationTokensForScopesParameters( - request: AuthorizationRequestDetails( - scopes: [], - userId: null, - email: null, - promptIfUnauthorized: false, - ), - ), - ); - }, throwsStateError); - - expect(() async { - await plugin.signOut(const SignOutParams()); - }, throwsStateError); - - expect(() async { - await plugin.disconnect(const DisconnectParams()); - }, throwsStateError); - }); }); group('support queries', () { diff --git a/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart b/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart index 6732b7ff568a..351e2abc093c 100644 --- a/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart +++ b/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart @@ -93,10 +93,8 @@ class GoogleSignInPlugin extends GoogleSignInPlatform { /// has finished running. @visibleForTesting Future get initialized { - _assertIsInitCalled(); return Future.wait(>[ _jsSdkLoadedFuture, - _initCalled!.future, ]); } @@ -122,8 +120,6 @@ class GoogleSignInPlugin extends GoogleSignInPlatform { assert(params.serverClientId == null, 'serverClientId is not supported on Web.'); - _initCalled = Completer(); - await _jsSdkLoadedFuture; _gisSdkClient ??= GisSdkClient( From 6ef759f6f971b7bdc8d2aff6d8a0bdc5e3e4d493 Mon Sep 17 00:00:00 2001 From: Srivats Venkataraman <42980667+srivats22@users.noreply.github.com> Date: Wed, 20 Aug 2025 07:45:18 -0400 Subject: [PATCH 05/11] dart format --- .../google_sign_in_web/lib/google_sign_in_web.dart | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart b/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart index 351e2abc093c..bf75c0505d62 100644 --- a/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart +++ b/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart @@ -49,10 +49,9 @@ class GoogleSignInPlugin extends GoogleSignInPlatform { @visibleForTesting GisSdkClient? debugOverrideGisSdkClient, @visibleForTesting StreamController? debugAuthenticationController, - }) : _gisSdkClient = debugOverrideGisSdkClient, - _authenticationController = - debugAuthenticationController ?? - StreamController.broadcast() { + }) : _gisSdkClient = debugOverrideGisSdkClient, + _authenticationController = debugAuthenticationController ?? + StreamController.broadcast() { autoDetectedClientId = web.document .querySelector(clientIdMetaSelector) ?.getAttribute(clientIdAttributeName); From 3ff7372a99bf1242515b834e9c2970099c66f3ee Mon Sep 17 00:00:00 2001 From: Srivats Venkataraman <42980667+srivats22@users.noreply.github.com> Date: Tue, 4 Nov 2025 07:39:06 -0500 Subject: [PATCH 06/11] PR update based on review comment --- .../google_sign_in_web_test.dart | 14 +++- .../lib/google_sign_in_web.dart | 82 +++++++++++-------- 2 files changed, 62 insertions(+), 34 deletions(-) diff --git a/packages/google_sign_in/google_sign_in_web/example/integration_test/google_sign_in_web_test.dart b/packages/google_sign_in/google_sign_in_web/example/integration_test/google_sign_in_web_test.dart index 0f6b9b63762b..5758df089c45 100644 --- a/packages/google_sign_in/google_sign_in_web/example/integration_test/google_sign_in_web_test.dart +++ b/packages/google_sign_in/google_sign_in_web/example/integration_test/google_sign_in_web_test.dart @@ -70,8 +70,20 @@ void main() { await plugin.init( const InitParameters(clientId: 'some-non-null-client-id'), ); + }); - expect(plugin.initialized, completes); + testWidgets('throws if init is called twice', (_) async { + await plugin.init( + const InitParameters(clientId: 'some-non-null-client-id'), + ); + + // Calling init() a second time should throw state error + expect( + () => plugin.init( + const InitParameters(clientId: 'some-non-null-client-id'), + ), + throwsStateError, + ); }); testWidgets('asserts clientId is not null', (_) async { diff --git a/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart b/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart index bf75c0505d62..16f167bc3b4e 100644 --- a/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart +++ b/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart @@ -49,9 +49,14 @@ class GoogleSignInPlugin extends GoogleSignInPlatform { @visibleForTesting GisSdkClient? debugOverrideGisSdkClient, @visibleForTesting StreamController? debugAuthenticationController, - }) : _gisSdkClient = debugOverrideGisSdkClient, - _authenticationController = debugAuthenticationController ?? - StreamController.broadcast() { + }) : _authenticationController = + debugAuthenticationController ?? + StreamController.broadcast() { + // Only set _gisSdkClient if debugOverrideGisSdkClient is provided + if (debugOverrideGisSdkClient != null) { + _gisSdkClient = debugOverrideGisSdkClient; + } + autoDetectedClientId = web.document .querySelector(clientIdMetaSelector) ?.getAttribute(clientIdAttributeName); @@ -68,32 +73,27 @@ class GoogleSignInPlugin extends GoogleSignInPlatform { // A future that completes when the JS loader is done. late Future _jsSdkLoadedFuture; + /// A completer used to track whether [init] has been called. + /// + /// Completes when [init] finishes, and is used to prevent multiple + /// initialization calls. + final Completer _initCalled = Completer(); + // A StreamController to communicate status changes from the GisSdkClient. final StreamController _authenticationController; // The instance of [GisSdkClient] backing the plugin. - GisSdkClient? _gisSdkClient; - - // A convenience getter to avoid using ! when accessing _gisSdkClient, and - // providing a slightly better error message when it is Null. - GisSdkClient get _gisClient { - assert( - _gisSdkClient != null, - 'GIS Client not initialized. ' - 'GoogleSignInPlugin::init() or GoogleSignInPlugin::initWithParams() ' - 'must be called before any other method in this plugin.', - ); - return _gisSdkClient!; - } + // Using late final ensures it can only be set once and throws if accessed before initialization. + late final GisSdkClient _gisSdkClient; /// A future that resolves when the plugin is fully initialized. /// /// This ensures that the SDK has been loaded, and that the `init` method /// has finished running. - @visibleForTesting - Future get initialized { + Future get _initialized { return Future.wait(>[ _jsSdkLoadedFuture, + _initCalled.future, ]); } @@ -108,6 +108,13 @@ class GoogleSignInPlugin extends GoogleSignInPlatform { @override Future init(InitParameters params) async { + // Throw if init() is called more than once + if (_initCalled.isCompleted) { + throw StateError( + 'init() has already been called. Calling init() more than once results in undefined behavior.', + ); + } + final String? appClientId = params.clientId ?? autoDetectedClientId; assert( appClientId != null, @@ -116,26 +123,33 @@ class GoogleSignInPlugin extends GoogleSignInPlatform { ' or pass clientId when initializing GoogleSignIn', ); - assert(params.serverClientId == null, - 'serverClientId is not supported on Web.'); + assert( + params.serverClientId == null, + 'serverClientId is not supported on Web.', + ); await _jsSdkLoadedFuture; - _gisSdkClient ??= GisSdkClient( + _gisSdkClient = GisSdkClient( clientId: appClientId!, nonce: params.nonce, hostedDomain: params.hostedDomain, authenticationController: _authenticationController, loggingEnabled: kDebugMode, ); + + _initCalled.complete(); + + // Return the initialized future for external users + return _initialized; } @override Future? attemptLightweightAuthentication( AttemptLightweightAuthenticationParameters params, ) { - initialized.then((void value) { - _gisClient.requestOneTap(); + _initialized.then((void value) { + _gisSdkClient.requestOneTap(); }); // One tap does not necessarily return immediately, and may never return, // so clients should not await it. Return null to signal that. @@ -160,26 +174,26 @@ class GoogleSignInPlugin extends GoogleSignInPlatform { @override Future signOut(SignOutParams params) async { - await initialized; + await _initialized; - await _gisClient.signOut(); + await _gisSdkClient.signOut(); } @override Future disconnect(DisconnectParams params) async { - await initialized; + await _initialized; - await _gisClient.disconnect(); + await _gisSdkClient.disconnect(); } @override Future clientAuthorizationTokensForScopes( ClientAuthorizationTokensForScopesParameters params, ) async { - await initialized; + await _initialized; _validateScopes(params.request.scopes); - final String? token = await _gisClient.requestScopes( + final String? token = await _gisSdkClient.requestScopes( params.request.scopes, promptIfUnauthorized: params.request.promptIfUnauthorized, userHint: params.request.userId, @@ -193,7 +207,7 @@ class GoogleSignInPlugin extends GoogleSignInPlatform { Future serverAuthorizationTokensForScopes( ServerAuthorizationTokensForScopesParameters params, ) async { - await initialized; + await _initialized; _validateScopes(params.request.scopes); // There is no way to know whether the flow will prompt in advance, so @@ -202,7 +216,9 @@ class GoogleSignInPlugin extends GoogleSignInPlatform { return null; } - final String? code = await _gisClient.requestServerAuthCode(params.request); + final String? code = await _gisSdkClient.requestServerAuthCode( + params.request, + ); return code == null ? null : ServerAuthorizationTokenData(serverAuthCode: code); @@ -247,13 +263,13 @@ class GoogleSignInPlugin extends GoogleSignInPlatform { configuration ?? GSIButtonConfiguration(); return FutureBuilder( key: Key(config.hashCode.toString()), - future: initialized, + future: _initialized, builder: (BuildContext context, AsyncSnapshot snapshot) { if (snapshot.hasData) { return FlexHtmlElementView( viewType: 'gsi_login_button', onElementCreated: (Object element) { - _gisClient.renderButton(element, config); + _gisSdkClient.renderButton(element, config); }, ); } From b9ac25cefcce059e4cee838916d77ef7d3fae5f7 Mon Sep 17 00:00:00 2001 From: Srivats Venkataraman <42980667+srivats22@users.noreply.github.com> Date: Wed, 3 Dec 2025 10:45:03 -0500 Subject: [PATCH 07/11] Addressing PR comments --- .../google_sign_in_web/CHANGELOG.md | 8 +++---- .../lib/google_sign_in_web.dart | 23 +++++++++---------- .../google_sign_in_web/pubspec.yaml | 2 +- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/packages/google_sign_in/google_sign_in_web/CHANGELOG.md b/packages/google_sign_in/google_sign_in_web/CHANGELOG.md index 0c5b937cab53..4ec23420c78b 100644 --- a/packages/google_sign_in/google_sign_in_web/CHANGELOG.md +++ b/packages/google_sign_in/google_sign_in_web/CHANGELOG.md @@ -1,11 +1,11 @@ -## 1.0.1 - -* Fixes Bad state: Future already completed on the web. - ## NEXT * Updates minimum supported SDK version to Flutter 3.32/Dart 3.8. +## 1.1.1 + +* Fixes Bad state: Future already completed on the web. + ## 1.1.0 * Adds support for the `clearAuthorizationToken` method. diff --git a/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart b/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart index 184418f10467..709df98d2819 100644 --- a/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart +++ b/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart @@ -79,6 +79,12 @@ class GoogleSignInPlugin extends GoogleSignInPlatform { /// initialization calls. final Completer _initCalled = Completer(); + /// A boolean flag to track if [init] has been called. + /// + /// This is used to prevent race conditions when [init] is called multiple + /// times without awaiting. + bool _isInitCalled = false; + // A StreamController to communicate status changes from the GisSdkClient. final StreamController _authenticationController; @@ -90,12 +96,7 @@ class GoogleSignInPlugin extends GoogleSignInPlatform { /// /// This ensures that the SDK has been loaded, and that the `init` method /// has finished running. - Future get _initialized { - return Future.wait(>[ - _jsSdkLoadedFuture, - _initCalled.future, - ]); - } + Future get _initialized => _initCalled.future; /// Stores the client ID if it was set in a meta-tag of the page. @visibleForTesting @@ -109,11 +110,12 @@ class GoogleSignInPlugin extends GoogleSignInPlatform { @override Future init(InitParameters params) async { // Throw if init() is called more than once - if (_initCalled.isCompleted) { + if (_isInitCalled) { throw StateError( 'init() has already been called. Calling init() more than once results in undefined behavior.', ); } + _isInitCalled = true; final String? appClientId = params.clientId ?? autoDetectedClientId; assert( @@ -139,9 +141,6 @@ class GoogleSignInPlugin extends GoogleSignInPlatform { ); _initCalled.complete(); - - // Return the initialized future for external users - return _initialized; } @override @@ -240,8 +239,8 @@ class GoogleSignInPlugin extends GoogleSignInPlatform { Future clearAuthorizationToken( ClearAuthorizationTokenParams params, ) async { - await initialized; - return _gisClient.clearAuthorizationToken(params.accessToken); + await _initialized; + return _gisSdkClient.clearAuthorizationToken(params.accessToken); } @override diff --git a/packages/google_sign_in/google_sign_in_web/pubspec.yaml b/packages/google_sign_in/google_sign_in_web/pubspec.yaml index cd849dcdc5cc..bcb4222e1eac 100644 --- a/packages/google_sign_in/google_sign_in_web/pubspec.yaml +++ b/packages/google_sign_in/google_sign_in_web/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Google Sign-In, a secure authentication system for signing in with a Google account on Android, iOS and Web. repository: https://github.com/flutter/packages/tree/main/packages/google_sign_in/google_sign_in_web issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+google_sign_in%22 -version: 1.1.0 +version: 1.1.1 environment: sdk: ^3.8.0 From 777c0eb004ee3a545d9096b54266cf4ef2a534c2 Mon Sep 17 00:00:00 2001 From: Srivats Venkataraman <42980667+srivats22@users.noreply.github.com> Date: Wed, 3 Dec 2025 11:30:32 -0500 Subject: [PATCH 08/11] Update packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart Co-authored-by: Mouad Debbar --- .../google_sign_in_web/lib/google_sign_in_web.dart | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart b/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart index 709df98d2819..7e16c260aff5 100644 --- a/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart +++ b/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart @@ -73,10 +73,7 @@ class GoogleSignInPlugin extends GoogleSignInPlatform { // A future that completes when the JS loader is done. late Future _jsSdkLoadedFuture; - /// A completer used to track whether [init] has been called. - /// - /// Completes when [init] finishes, and is used to prevent multiple - /// initialization calls. + /// A completer used to track whether [init] has finished. final Completer _initCalled = Completer(); /// A boolean flag to track if [init] has been called. From 5900a70273a630f1f1c96aa5b1dc91f1d21a913b Mon Sep 17 00:00:00 2001 From: Srivats Venkataraman <42980667+srivats22@users.noreply.github.com> Date: Thu, 4 Dec 2025 11:02:55 -0500 Subject: [PATCH 09/11] Updating changelog --- packages/google_sign_in/google_sign_in_web/CHANGELOG.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/google_sign_in/google_sign_in_web/CHANGELOG.md b/packages/google_sign_in/google_sign_in_web/CHANGELOG.md index 4ec23420c78b..09cc300520f9 100644 --- a/packages/google_sign_in/google_sign_in_web/CHANGELOG.md +++ b/packages/google_sign_in/google_sign_in_web/CHANGELOG.md @@ -1,10 +1,10 @@ -## NEXT +## 1.1.1 -* Updates minimum supported SDK version to Flutter 3.32/Dart 3.8. +* Throws a more actionable error when init is called more than once -## 1.1.1 +## NEXT -* Fixes Bad state: Future already completed on the web. +* Updates minimum supported SDK version to Flutter 3.32/Dart 3.8. ## 1.1.0 From 5905948aecd76226e143aa6861b4be902d444b8c Mon Sep 17 00:00:00 2001 From: Srivats Venkataraman <42980667+srivats22@users.noreply.github.com> Date: Fri, 5 Dec 2025 10:59:08 -0500 Subject: [PATCH 10/11] fix test failiure and add new test --- .../google_sign_in_web/CHANGELOG.md | 1 + .../google_sign_in_web_test.dart | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/packages/google_sign_in/google_sign_in_web/CHANGELOG.md b/packages/google_sign_in/google_sign_in_web/CHANGELOG.md index 09cc300520f9..683a4d601eb6 100644 --- a/packages/google_sign_in/google_sign_in_web/CHANGELOG.md +++ b/packages/google_sign_in/google_sign_in_web/CHANGELOG.md @@ -1,6 +1,7 @@ ## 1.1.1 * Throws a more actionable error when init is called more than once +* Updates minimum supported SDK version to Flutter 3.32/Dart 3.8. ## NEXT diff --git a/packages/google_sign_in/google_sign_in_web/example/integration_test/google_sign_in_web_test.dart b/packages/google_sign_in/google_sign_in_web/example/integration_test/google_sign_in_web_test.dart index 40cf8fe54784..e102d6521175 100644 --- a/packages/google_sign_in/google_sign_in_web/example/integration_test/google_sign_in_web_test.dart +++ b/packages/google_sign_in/google_sign_in_web/example/integration_test/google_sign_in_web_test.dart @@ -81,6 +81,22 @@ void main() { ); }); + testWidgets('throws if init is called twice synchronously', (_) async { + final Future firstInit = plugin.init( + const InitParameters(clientId: 'some-non-null-client-id'), + ); + + // Calling init() a second time synchronously should throw state error + expect( + () => plugin.init( + const InitParameters(clientId: 'some-non-null-client-id'), + ), + throwsStateError, + ); + + await firstInit; + }); + testWidgets('asserts clientId is not null', (_) async { expect(() async { await plugin.init(const InitParameters()); From 192a39604194de352aefb3f40dc6f4162e89eaa9 Mon Sep 17 00:00:00 2001 From: Srivats Venkataraman <42980667+srivats22@users.noreply.github.com> Date: Thu, 8 Jan 2026 08:11:56 -0500 Subject: [PATCH 11/11] Fixing CI Faliur --- .../google_sign_in_web/CHANGELOG.md | 4 --- .../lib/google_sign_in_web.dart | 27 ++++++++++--------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/packages/google_sign_in/google_sign_in_web/CHANGELOG.md b/packages/google_sign_in/google_sign_in_web/CHANGELOG.md index 683a4d601eb6..31fd8b92565f 100644 --- a/packages/google_sign_in/google_sign_in_web/CHANGELOG.md +++ b/packages/google_sign_in/google_sign_in_web/CHANGELOG.md @@ -3,10 +3,6 @@ * Throws a more actionable error when init is called more than once * Updates minimum supported SDK version to Flutter 3.32/Dart 3.8. -## NEXT - -* Updates minimum supported SDK version to Flutter 3.32/Dart 3.8. - ## 1.1.0 * Adds support for the `clearAuthorizationToken` method. diff --git a/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart b/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart index 7e16c260aff5..8358f5d1ff47 100644 --- a/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart +++ b/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart @@ -49,14 +49,10 @@ class GoogleSignInPlugin extends GoogleSignInPlatform { @visibleForTesting GisSdkClient? debugOverrideGisSdkClient, @visibleForTesting StreamController? debugAuthenticationController, - }) : _authenticationController = + }) : _debugOverrideGisSdkClient = debugOverrideGisSdkClient, + _authenticationController = debugAuthenticationController ?? StreamController.broadcast() { - // Only set _gisSdkClient if debugOverrideGisSdkClient is provided - if (debugOverrideGisSdkClient != null) { - _gisSdkClient = debugOverrideGisSdkClient; - } - autoDetectedClientId = web.document .querySelector(clientIdMetaSelector) ?.getAttribute(clientIdAttributeName); @@ -89,6 +85,9 @@ class GoogleSignInPlugin extends GoogleSignInPlatform { // Using late final ensures it can only be set once and throws if accessed before initialization. late final GisSdkClient _gisSdkClient; + // An optional override for the GisSdkClient, used for testing. + final GisSdkClient? _debugOverrideGisSdkClient; + /// A future that resolves when the plugin is fully initialized. /// /// This ensures that the SDK has been loaded, and that the `init` method @@ -129,13 +128,15 @@ class GoogleSignInPlugin extends GoogleSignInPlatform { await _jsSdkLoadedFuture; - _gisSdkClient = GisSdkClient( - clientId: appClientId!, - nonce: params.nonce, - hostedDomain: params.hostedDomain, - authenticationController: _authenticationController, - loggingEnabled: kDebugMode, - ); + _gisSdkClient = + _debugOverrideGisSdkClient ?? + GisSdkClient( + clientId: appClientId!, + nonce: params.nonce, + hostedDomain: params.hostedDomain, + authenticationController: _authenticationController, + loggingEnabled: kDebugMode, + ); _initCalled.complete(); }