diff --git a/packages/google_sign_in/google_sign_in_ios/CHANGELOG.md b/packages/google_sign_in/google_sign_in_ios/CHANGELOG.md index 8081c058091c..5da10877ac7e 100644 --- a/packages/google_sign_in/google_sign_in_ios/CHANGELOG.md +++ b/packages/google_sign_in/google_sign_in_ios/CHANGELOG.md @@ -1,5 +1,6 @@ -## NEXT +## 6.3.6 +* Converts the Pigeon host API from Objective-C to Swift. * Updates minimum supported SDK version to Flutter 3.41/Dart 3.11. ## 6.3.5 diff --git a/packages/google_sign_in/google_sign_in_ios/darwin/Tests/GoogleSignInTests.swift b/packages/google_sign_in/google_sign_in_ios/darwin/Tests/GoogleSignInTests.swift index 9c7721b0313c..67fa950e8f37 100644 --- a/packages/google_sign_in/google_sign_in_ios/darwin/Tests/GoogleSignInTests.swift +++ b/packages/google_sign_in/google_sign_in_ios/darwin/Tests/GoogleSignInTests.swift @@ -7,11 +7,7 @@ import Testing @testable import google_sign_in_ios -#if canImport(google_sign_in_ios_objc) - @testable import google_sign_in_ios_objc -#endif - -#if os(OSX) +#if os(macOS) import FlutterMacOS #else import Flutter @@ -19,7 +15,7 @@ import Testing // Test implementation of ViewProvider. class TestViewProvider: ViewProvider { - #if os(OSX) + #if os(macOS) // The view containing the Flutter content. var view: NSView? #else @@ -63,7 +59,7 @@ class TestSignIn: NSObject, GIDSignInProtocol { } func restorePreviousSignIn(completion: (((any GIDGoogleUserProtocol)?, Error?) -> Void)?) { - if let exception = exception { + if let exception { exception.raise() } if let user { @@ -78,7 +74,7 @@ class TestSignIn: NSObject, GIDSignInProtocol { } func disconnect(completion: ((Error?) -> Void)?) { - if let exception = exception { + if let exception { exception.raise() } completion?(error) @@ -92,7 +88,7 @@ class TestSignIn: NSObject, GIDSignInProtocol { nonce: String?, completion: ((GIDSignInResultProtocol?, Error?) -> Void)? ) { - if let exception = exception { + if let exception { exception.raise() } self.presentingViewController = presentingViewController @@ -113,7 +109,7 @@ class TestSignIn: NSObject, GIDSignInProtocol { nonce: String?, completion: (((any GIDSignInResultProtocol)?, Error?) -> Void)? ) { - if let exception = exception { + if let exception { exception.raise() } self.presentingWindow = presentingWindow @@ -130,10 +126,10 @@ class TestSignIn: NSObject, GIDSignInProtocol { } // Test implementation of GIDProfileDataProtocol. -class TestProfileData: NSObject, GIDProfileDataProtocol { +class TestProfileData: GIDProfileDataProtocol { var email: String var name: String - // A URL to return from imageURLWithDimension:. + // A URL to return from imageURL(withDimension:). var imageURL: URL? init(name: String, email: String, imageURL: URL?) { @@ -152,7 +148,7 @@ class TestProfileData: NSObject, GIDProfileDataProtocol { } // Test implementation of GIDTokenProtocol. -final class TestToken: NSObject, GIDTokenProtocol { +final class TestToken: GIDTokenProtocol { let tokenString: String let expirationDate: Date? @@ -163,7 +159,7 @@ final class TestToken: NSObject, GIDTokenProtocol { } // Test implementation of GIDSignInResultProtocol. -class TestSignInResult: NSObject, GIDSignInResultProtocol { +class TestSignInResult: GIDSignInResultProtocol { var user: any GIDGoogleUserProtocol var serverAuthCode: String? @@ -174,7 +170,7 @@ class TestSignInResult: NSObject, GIDSignInResultProtocol { } // Test implementation of GIDGoogleUserProtocol. -class TestGoogleUser: NSObject, GIDGoogleUserProtocol { +class TestGoogleUser: GIDGoogleUserProtocol { var userID: String? var profile: (any GIDProfileDataProtocol)? var grantedScopes: [String]? @@ -185,7 +181,7 @@ class TestGoogleUser: NSObject, GIDGoogleUserProtocol { // An exception to throw from methods. var exception: NSException? - // The result to return from addScopes:presentingViewController:completion:. + // The result to return from addScopes(_:presenting:completion:). var result: (any GIDSignInResultProtocol)? // The error to return from methods. @@ -204,7 +200,7 @@ class TestGoogleUser: NSObject, GIDGoogleUserProtocol { } func refreshTokensIfNeeded(completion: @escaping ((any GIDGoogleUserProtocol)?, Error?) -> Void) { - if let exception = exception { + if let exception { exception.raise() } completion(self.error == nil ? self : nil, self.error) @@ -218,12 +214,12 @@ class TestGoogleUser: NSObject, GIDGoogleUserProtocol { ) { self.requestedScopes = scopes self.presentingViewController = presentingViewController - if let exception = exception { + if let exception { exception.raise() } completion?(self.error == nil ? self.result : nil, self.error) } - #elseif os(OSX) + #elseif os(macOS) func addScopes( _ scopes: [String], presenting presentingWindow: NSWindow?, @@ -231,7 +227,7 @@ class TestGoogleUser: NSObject, GIDGoogleUserProtocol { ) { self.requestedScopes = scopes self.presentingWindow = presentingWindow - if let exception = exception { + if let exception { exception.raise() } completion?(self.error == nil ? self.result : nil, self.error) @@ -240,35 +236,36 @@ class TestGoogleUser: NSObject, GIDGoogleUserProtocol { } struct GoogleSignInPluginTests { - @Test func signOut() { + @Test func signOut() throws { let (plugin, fakeSignIn) = createTestPlugin() - var error: FlutterError? - plugin.signOutWithError(&error) + try plugin.signOut() #expect(fakeSignIn.signOutCalled == true) - #expect(error == nil) } @Test func disconnect() async { let (plugin, _) = createTestPlugin() await confirmation("expect result returns true") { confirmed in - plugin.disconnect { error in - #expect(error == nil) + plugin.disconnect { result in + switch result { + case .success: + break + case .failure(let error): + Issue.record("Unexpected error: \(error)") + } confirmed() } } } @Suite("configure") struct ConfigureTests { - @Test func configureFromAppInfoPlist() { + @Test func configureFromAppInfoPlist() throws { let (plugin, fakeSignIn) = createTestPlugin() - let params = FSIPlatformConfigurationParams.make( - withClientId: nil, + let params = PlatformConfigurationParams( + clientId: nil, serverClientId: nil, hostedDomain: "example.com") - var error: FlutterError? - plugin.configure(withParameters: params, error: &error) - #expect(error == nil) + try plugin.configure(params: params) // No configuration should be set, allowing the SDK to use its default behavior // (which is to load configuration information from the app's Info.plist). #expect(fakeSignIn.configuration == nil) @@ -288,12 +285,12 @@ struct GoogleSignInPluginTests { dynamicServerClientId: String?, dynamicHostedDomain: String?, useGoogleServiceInfoPlist: Bool - ) + ) throws { let (plugin, fakeSignIn) = createTestPlugin( googleServiceProperties: useGoogleServiceInfoPlist ? loadGoogleServiceInfo() : nil) - let params = FSIPlatformConfigurationParams.make( - withClientId: dynamicClientId, + let params = PlatformConfigurationParams( + clientId: dynamicClientId, serverClientId: dynamicServerClientId, hostedDomain: dynamicHostedDomain) @@ -316,9 +313,7 @@ struct GoogleSignInPluginTests { expectedDomain = dynamicHostedDomain } - var error: FlutterError? - plugin.configure(withParameters: params, error: &error) - #expect(error == nil) + try plugin.configure(params: params) #expect( fakeSignIn.configuration?.clientID == expectedClientId) @@ -342,16 +337,22 @@ struct GoogleSignInPluginTests { fakeSignIn.user = fakeUser await confirmation("completion called") { confirmed in - plugin.restorePreviousSignIn { result, error in - #expect(error == nil) - #expect(result?.error == nil) - #expect(result?.success != nil) - #expect(result?.success?.user.displayName == name) - #expect(result?.success?.user.email == email) - #expect(result?.success?.user.userId == userID) - #expect(result?.success?.user.photoUrl == imageURLString) - #expect(result?.success?.accessToken == accessToken) - #expect(result?.success?.serverAuthCode == nil) + plugin.restorePreviousSignIn { result in + switch result { + case .success(let signInResult): + guard let success = signInResult as? SignInSuccess else { + Issue.record("Unexpected type for \(signInResult)") + break + } + #expect(success.user.displayName == name) + #expect(success.user.email == email) + #expect(success.user.userId == userID) + #expect(success.user.photoUrl == imageURLString) + #expect(success.accessToken == accessToken) + #expect(success.serverAuthCode == nil) + case .failure(let error): + Issue.record("Unexpected error: \(error)") + } confirmed() } } @@ -365,10 +366,17 @@ struct GoogleSignInPluginTests { fakeSignIn.error = sdkError await confirmation("completion called") { confirmed in - plugin.restorePreviousSignIn { result, error in - #expect(error == nil) - #expect(result?.success == nil) - #expect(result?.error?.type == FSIGoogleSignInErrorCode.noAuthInKeychain) + plugin.restorePreviousSignIn { result in + switch result { + case .success(let signInResult): + guard let failure = signInResult as? SignInFailure else { + Issue.record("Unexpected type for \(signInResult)") + break + } + #expect(failure.type == GoogleSignInErrorCode.noAuthInKeychain) + case .failure(let error): + Issue.record("Unexpected error: \(error)") + } confirmed() } } @@ -381,23 +389,37 @@ struct GoogleSignInPluginTests { fakeSignIn.user = fakeUser await confirmation("completion called") { confirmed in - plugin.restorePreviousSignIn { result, error in - #expect(result == nil) - #expect(error?.code == "google_sign_in") - #expect(error?.message == "Google Sign-In succeeded without a user ID.") + plugin.restorePreviousSignIn { result in + switch result { + case .success(let signInResult): + Issue.record("Unexpected success: \(signInResult)") + case .failure(let error): + let pigeonError = error as! PigeonError + #expect(pigeonError.code == "google_sign_in") + #expect(pigeonError.message == "Google Sign-In succeeded without a user ID.") + } confirmed() } } } - @Test func restorePreviousSignInNeitherUserNorError() async { + @Test func restorePreviousSignInWithoutUserOrError() async { let (plugin, _) = createTestPlugin() await confirmation("completion called") { confirmed in - plugin.restorePreviousSignIn { result, error in - #expect(result == nil) - #expect(error?.code == "(null): 0") - #expect(error?.details as? String == "[Unsupported type: (null)]") + plugin.restorePreviousSignIn { result in + switch result { + case .success: + Issue.record("Expected a PigeonError when the SDK returns neither a user nor an error") + case .failure(let error): + guard let pigeonError = error as? PigeonError else { + Issue.record("Expected PigeonError, got \(error)") + break + } + #expect(pigeonError.code == "google_sign_in") + #expect(pigeonError.message == "Sign-in completed without a user or an error.") + #expect(pigeonError.details == nil) + } confirmed() } } @@ -422,29 +444,34 @@ struct GoogleSignInPluginTests { fakeSignIn.signInResult = fakeSignInResult await confirmation("completion called") { confirmed in - plugin.signIn(withScopeHint: [], nonce: nil) { result, error in - #expect(error == nil) - #expect(result?.success?.user.displayName == "mockDisplay") - #expect(result?.success?.user.email == "mock@example.com") - #expect(result?.success?.user.userId == "mockID") - #expect(result?.success?.user.photoUrl == "https://example.com/profile.png") - #expect(result?.success?.accessToken == accessToken) - #expect(result?.success?.serverAuthCode == serverAuthCode) + plugin.signIn(scopeHint: [], nonce: nil) { result in + switch result { + case .success(let signInResult): + guard let success = signInResult as? SignInSuccess else { + Issue.record("Unexpected type for \(signInResult)") + break + } + #expect(success.user.displayName == "mockDisplay") + #expect(success.user.email == "mock@example.com") + #expect(success.user.userId == "mockID") + #expect(success.user.photoUrl == "https://example.com/profile.png") + #expect(success.accessToken == accessToken) + #expect(success.serverAuthCode == serverAuthCode) + case .failure(let error): + Issue.record("Unexpected error: \(error)") + } confirmed() } } } - @Test func signInWithScopeHint() async { + @Test func signInWithScopeHint() async throws { let (plugin, fakeSignIn) = createTestPlugin() - var initializationError: FlutterError? - plugin.configure( - withParameters: FSIPlatformConfigurationParams.make( - withClientId: nil, + try plugin.configure( + params: PlatformConfigurationParams( + clientId: nil, serverClientId: nil, - hostedDomain: nil), - error: &initializationError) - #expect(initializationError == nil) + hostedDomain: nil)) let fakeUser = TestGoogleUser("mockID") let fakeSignInResult = TestSignInResult(user: fakeUser) @@ -453,10 +480,17 @@ struct GoogleSignInPluginTests { fakeSignIn.signInResult = fakeSignInResult await confirmation("completion called") { confirmed in - plugin.signIn(withScopeHint: requestedScopes, nonce: nil) { result, error in - #expect(error == nil) - #expect(result?.error == nil) - #expect(result?.success?.user.userId == "mockID") + plugin.signIn(scopeHint: requestedScopes, nonce: nil) { result in + switch result { + case .success(let signInResult): + guard let success = signInResult as? SignInSuccess else { + Issue.record("Unexpected type for \(signInResult)") + break + } + #expect(success.user.userId == "mockID") + case .failure(let error): + Issue.record("Unexpected error: \(error)") + } confirmed() } } @@ -464,16 +498,13 @@ struct GoogleSignInPluginTests { #expect(Set(fakeSignIn.additionalScopes ?? []) == Set(requestedScopes)) } - @Test func signInWithNonce() async { + @Test func signInWithNonce() async throws { let (plugin, fakeSignIn) = createTestPlugin() - var initializationError: FlutterError? - plugin.configure( - withParameters: FSIPlatformConfigurationParams.make( - withClientId: nil, + try plugin.configure( + params: PlatformConfigurationParams( + clientId: nil, serverClientId: nil, - hostedDomain: nil), - error: &initializationError) - #expect(initializationError == nil) + hostedDomain: nil)) let fakeUser = TestGoogleUser("mockID") let fakeSignInResult = TestSignInResult(user: fakeUser) @@ -482,10 +513,17 @@ struct GoogleSignInPluginTests { fakeSignIn.signInResult = fakeSignInResult await confirmation("completion called") { confirmed in - plugin.signIn(withScopeHint: [], nonce: nonce) { result, error in - #expect(error == nil) - #expect(result?.error == nil) - #expect(result?.success?.user.userId == "mockID") + plugin.signIn(scopeHint: [], nonce: nonce) { result in + switch result { + case .success(let signInResult): + guard let success = signInResult as? SignInSuccess else { + Issue.record("Unexpected type for \(signInResult)") + break + } + #expect(success.user.userId == "mockID") + case .failure(let error): + Issue.record("Unexpected error: \(error)") + } confirmed() } } @@ -506,10 +544,17 @@ struct GoogleSignInPluginTests { fakeSignIn.error = sdkError await confirmation("completion called") { confirmed in - plugin.signIn(withScopeHint: [], nonce: nil) { result, error in - #expect(error == nil) - #expect(result?.error == nil) - #expect(result?.success?.user.userId == "mockID") + plugin.signIn(scopeHint: [], nonce: nil) { result in + switch result { + case .success(let signInResult): + guard let success = signInResult as? SignInSuccess else { + Issue.record("Unexpected type for \(signInResult)") + break + } + #expect(success.user.userId == "mockID") + case .failure(let error): + Issue.record("Unexpected error: \(error)") + } confirmed() } } @@ -522,12 +567,19 @@ struct GoogleSignInPluginTests { fakeSignIn.error = sdkError await confirmation("completion called") { confirmed in - plugin.signIn(withScopeHint: [], nonce: nil) { result, error in - // Known errors from the SDK are returned as structured data, not - // FlutterError. - #expect(error == nil) - #expect(result?.success == nil) - #expect(result?.error?.type == .canceled) + plugin.signIn(scopeHint: [], nonce: nil) { result in + switch result { + case .success(let signInResult): + // Known errors from the SDK are returned as structured data, not + // PigeonError. + guard let failure = signInResult as? SignInFailure else { + Issue.record("Unexpected type for \(signInResult)") + break + } + #expect(failure.type == .canceled) + case .failure(let error): + Issue.record("Unexpected error: \(error)") + } confirmed() } } @@ -541,13 +593,21 @@ struct GoogleSignInPluginTests { userInfo: nil) await confirmation("completion called") { confirmed in - plugin.signIn(withScopeHint: [], nonce: nil) { result, error in - // Unexpected errors, such as runtime exceptions, are returned as - // FlutterError. - #expect(result == nil) - #expect(error?.code == "google_sign_in") - #expect(error?.message == "MockReason") - #expect(error?.details as? String == "MockName") + plugin.signIn(scopeHint: [], nonce: nil) { result in + switch result { + case .success: + Issue.record("Expected a PigeonError for the runtime exception") + case .failure(let error): + // Unexpected errors, such as runtime exceptions, are returned as + // PigeonError. + guard let pigeonError = error as? PigeonError else { + Issue.record("Expected PigeonError, got \(error)") + break + } + #expect(pigeonError.code == "google_sign_in") + #expect(pigeonError.message == "MockReason") + #expect(pigeonError.details as? String == "MockName") + } confirmed() } } @@ -564,11 +624,18 @@ struct GoogleSignInPluginTests { fakeUser.accessToken = TestToken("mockAccessToken") await confirmation("completion called") { confirmed in - plugin.refreshedAuthorizationTokens(forUser: fakeUser.userID!) { result, error in - #expect(error == nil) - #expect(result?.error == nil) - #expect(result?.success?.user.idToken == "mockIdToken") - #expect(result?.success?.accessToken == "mockAccessToken") + plugin.getRefreshedAuthorizationTokens(userId: fakeUser.userID!) { result in + switch result { + case .success(let signInResult): + guard let success = signInResult as? SignInSuccess else { + Issue.record("Unexpected type for \(signInResult)") + break + } + #expect(success.user.idToken == "mockIdToken") + #expect(success.accessToken == "mockAccessToken") + case .failure(let error): + Issue.record("Unexpected error: \(error)") + } confirmed() } } @@ -577,22 +644,29 @@ struct GoogleSignInPluginTests { @Test func refreshTokensUnkownUser() async { let (plugin, _) = createTestPlugin() await confirmation("completion called") { confirmed in - plugin.refreshedAuthorizationTokens(forUser: "unknownUser") { result, error in - #expect(error == nil) - #expect(result?.success == nil) - #expect(result?.error?.type == .userMismatch) - #expect(result?.error?.message == "The user is no longer signed in.") + plugin.getRefreshedAuthorizationTokens(userId: "unknownUser") { result in + switch result { + case .success(let signInResult): + guard let failure = signInResult as? SignInFailure else { + Issue.record("Unexpected type for \(signInResult)") + break + } + #expect(failure.type == .userMismatch) + #expect(failure.message == "The user is no longer signed in.") + case .failure(let error): + Issue.record("Unexpected error: \(error)") + } confirmed() } } } @Test(arguments: [ - (GIDSignInError.hasNoAuthInKeychain.rawValue, FSIGoogleSignInErrorCode.noAuthInKeychain), - (GIDSignInError.canceled.rawValue, .canceled), + (GIDSignInError.hasNoAuthInKeychain.rawValue, GoogleSignInErrorCode.noAuthInKeychain), + (GIDSignInError.canceled.rawValue, GoogleSignInErrorCode.canceled), ]) func refreshTokensGIDSignInErrorDomainErrors( signInSDKErrorCode: Int, - expectedPigeonErrorCode: FSIGoogleSignInErrorCode + expectedPigeonErrorCode: GoogleSignInErrorCode ) async { let (plugin, _) = createTestPlugin() let fakeUser = addSignedInUser(to: plugin) @@ -603,10 +677,17 @@ struct GoogleSignInPluginTests { fakeUser.error = sdkError await confirmation("completion called") { confirmed in - plugin.refreshedAuthorizationTokens(forUser: fakeUser.userID!) { result, error in - #expect(error == nil) - #expect(result?.success == nil) - #expect(result?.error?.type == expectedPigeonErrorCode) + plugin.getRefreshedAuthorizationTokens(userId: fakeUser.userID!) { result in + switch result { + case .success(let signInResult): + guard let failure = signInResult as? SignInFailure else { + Issue.record("Unexpected type for \(signInResult)") + break + } + #expect(failure.type == expectedPigeonErrorCode) + case .failure(let error): + Issue.record("Unexpected error: \(error)") + } confirmed() } } @@ -626,11 +707,18 @@ struct GoogleSignInPluginTests { fakeUser.error = sdkError await confirmation("completion called") { confirmed in - plugin.refreshedAuthorizationTokens(forUser: fakeUser.userID!) { result, error in - #expect(result?.error == nil) - #expect(result?.success == nil) - let expectedCode = "\(errorDomain): \(errorCode)" - #expect(error?.code == expectedCode) + plugin.getRefreshedAuthorizationTokens(userId: fakeUser.userID!) { result in + switch result { + case .success: + Issue.record("Expected a PigeonError for a non-GID error domain") + case .failure(let error): + guard let pigeonError = error as? PigeonError else { + Issue.record("Expected PigeonError, got \(error)") + break + } + let expectedCode = "\(errorDomain): \(errorCode)" + #expect(pigeonError.code == expectedCode) + } confirmed() } } @@ -649,9 +737,16 @@ struct GoogleSignInPluginTests { let scopes = ["mockScope1"] await confirmation("completion called") { confirmed in - plugin.addScopes(scopes, forUser: fakeUser.userID!) { result, error in - #expect(error == nil) - #expect(result?.success != nil) + plugin.addScopes(scopes, forUser: fakeUser.userID!) { result in + switch result { + case .success(let signInResult): + guard signInResult is SignInSuccess else { + Issue.record("Unexpected type for \(signInResult)") + break + } + case .failure(let error): + Issue.record("Unexpected error: \(error)") + } confirmed() } } @@ -661,21 +756,28 @@ struct GoogleSignInPluginTests { @Test func addScopesErrorsIfNotSignedIn() async { let (plugin, _) = createTestPlugin() await confirmation("completion called") { confirmed in - plugin.addScopes(["mockScope1"], forUser: "unknownUser") { result, error in - #expect(error == nil) - #expect(result?.success == nil) - #expect(result?.error?.type == .userMismatch) + plugin.addScopes(["mockScope1"], forUser: "unknownUser") { result in + switch result { + case .success(let signInResult): + guard let failure = signInResult as? SignInFailure else { + Issue.record("Unexpected type for \(signInResult)") + break + } + #expect(failure.type == .userMismatch) + case .failure(let error): + Issue.record("Unexpected error: \(error)") + } confirmed() } } } @Test(arguments: [ - (GIDSignInError.scopesAlreadyGranted.rawValue, FSIGoogleSignInErrorCode.scopesAlreadyGranted), - (GIDSignInError.mismatchWithCurrentUser.rawValue, FSIGoogleSignInErrorCode.userMismatch), + (GIDSignInError.scopesAlreadyGranted.rawValue, GoogleSignInErrorCode.scopesAlreadyGranted), + (GIDSignInError.mismatchWithCurrentUser.rawValue, GoogleSignInErrorCode.userMismatch), ]) func addScopesGIDSignInErrorDomainErrors( signInSDKErrorCode: Int, - expectedPigeonErrorCode: FSIGoogleSignInErrorCode + expectedPigeonErrorCode: GoogleSignInErrorCode ) async { let (plugin, _) = createTestPlugin() let fakeUser = addSignedInUser(to: plugin) @@ -686,10 +788,17 @@ struct GoogleSignInPluginTests { fakeUser.error = sdkError await confirmation("completion called") { confirmed in - plugin.addScopes(["mockScope1"], forUser: fakeUser.userID!) { result, error in - #expect(error == nil) - #expect(result?.success == nil) - #expect(result?.error?.type == expectedPigeonErrorCode) + plugin.addScopes(["mockScope1"], forUser: fakeUser.userID!) { result in + switch result { + case .success(let signInResult): + guard let failure = signInResult as? SignInFailure else { + Issue.record("Unexpected type for \(signInResult)") + break + } + #expect(failure.type == expectedPigeonErrorCode) + case .failure(let error): + Issue.record("Unexpected error: \(error)") + } confirmed() } } @@ -703,9 +812,17 @@ struct GoogleSignInPluginTests { fakeUser.error = sdkError await confirmation("completion called") { confirmed in - plugin.addScopes(["mockScope1"], forUser: fakeUser.userID!) { result, error in - #expect(result == nil) - #expect(error?.code == "BogusDomain: 42") + plugin.addScopes(["mockScope1"], forUser: fakeUser.userID!) { result in + switch result { + case .success: + Issue.record("Expected a PigeonError for an unknown error domain") + case .failure(let error): + guard let pigeonError = error as? PigeonError else { + Issue.record("Expected PigeonError, got \(error)") + break + } + #expect(pigeonError.code == "BogusDomain: 42") + } confirmed() } } @@ -721,11 +838,19 @@ struct GoogleSignInPluginTests { userInfo: nil) await confirmation("completion called") { confirmed in - plugin.addScopes([], forUser: fakeUser.userID!) { result, error in - #expect(result == nil) - #expect(error?.code == "request_scopes") - #expect(error?.message == "MockReason") - #expect(error?.details as? String == "MockName") + plugin.addScopes([], forUser: fakeUser.userID!) { result in + switch result { + case .success: + Issue.record("Expected a PigeonError for the runtime exception") + case .failure(let error): + guard let pigeonError = error as? PigeonError else { + Issue.record("Expected PigeonError, got \(error)") + break + } + #expect(pigeonError.code == "request_scopes") + #expect(pigeonError.message == "MockReason") + #expect(pigeonError.details as? String == "MockName") + } confirmed() } } @@ -784,24 +909,31 @@ struct GoogleSignInPluginTests { @Suite("errorMapping") struct ErrorMappingTests { @Test(arguments: [ - (GIDSignInError.keychain.rawValue, FSIGoogleSignInErrorCode.keychainError), - (GIDSignInError.EMM.rawValue, FSIGoogleSignInErrorCode.eemError), - (GIDSignInError.unknown.rawValue, FSIGoogleSignInErrorCode.unknown), + (GIDSignInError.keychain.rawValue, GoogleSignInErrorCode.keychainError), + (GIDSignInError.EMM.rawValue, GoogleSignInErrorCode.eemError), + (GIDSignInError.unknown.rawValue, GoogleSignInErrorCode.unknown), // Unrecognized SDK codes fall through to the default → unknown. - (12_345, FSIGoogleSignInErrorCode.unknown), + (12_345, GoogleSignInErrorCode.unknown), ]) func mapsRemainingGIDSignInErrorCodes( signInSDKErrorCode: Int, - expectedPigeonErrorCode: FSIGoogleSignInErrorCode + expectedPigeonErrorCode: GoogleSignInErrorCode ) async { let (plugin, fakeSignIn) = createTestPlugin() fakeSignIn.error = NSError( domain: kGIDSignInErrorDomain, code: signInSDKErrorCode, userInfo: nil) await confirmation("completion called") { confirmed in - plugin.signIn(withScopeHint: [], nonce: nil) { result, error in - #expect(error == nil) - #expect(result?.success == nil) - #expect(result?.error?.type == expectedPigeonErrorCode) + plugin.signIn(scopeHint: [], nonce: nil) { result in + switch result { + case .success(let signInResult): + guard let failure = signInResult as? SignInFailure else { + Issue.record("Unexpected type for \(signInResult)") + break + } + #expect(failure.type == expectedPigeonErrorCode) + case .failure(let error): + Issue.record("Unexpected error: \(error)") + } confirmed() } } @@ -823,20 +955,28 @@ struct GoogleSignInPluginTests { fakeUser.error = NSError(domain: "BogusDomain", code: 7, userInfo: userInfo) await confirmation("completion called") { confirmed in - plugin.refreshedAuthorizationTokens(forUser: fakeUser.userID!) { result, error in - #expect(result == nil) - #expect(error?.code == "BogusDomain: 7") - let details = error?.details as? [String: Any] - #expect(details?["string"] as? String == "ok") - #expect(details?["number"] as? NSNumber == NSNumber(value: 42)) - #expect(details?["url"] as? String == "https://example.com/path") - #expect((details?["array"] as? [Any])?.count == 2) - #expect((details?["dict"] as? [String: Any])?["inner"] as? String == "value") - let nestedDetails = details?[NSUnderlyingErrorKey] as? [String: Any] - #expect(nestedDetails?["domain"] as? String == "NestedDomain") - #expect(nestedDetails?["code"] as? String == "99") - let unsupported = details?["unsupported"] as? String - #expect(unsupported?.contains("Unsupported type:") == true) + plugin.getRefreshedAuthorizationTokens(userId: fakeUser.userID!) { result in + switch result { + case .success: + Issue.record("Expected a PigeonError for a non-GID error domain") + case .failure(let error): + guard let pigeonError = error as? PigeonError else { + Issue.record("Expected PigeonError, got \(error)") + break + } + #expect(pigeonError.code == "BogusDomain: 7") + let details = pigeonError.details as? [String: any Sendable] + #expect(details?["string"] as? String == "ok") + #expect(details?["number"] as? NSNumber == NSNumber(value: 42)) + #expect(details?["url"] as? String == "https://example.com/path") + #expect((details?["array"] as? [any Sendable])?.count == 2) + #expect((details?["dict"] as? [String: any Sendable])?["inner"] as? String == "value") + let nestedDetails = details?[NSUnderlyingErrorKey] as? [String: any Sendable] + #expect(nestedDetails?["domain"] as? String == "NestedDomain") + #expect(nestedDetails?["code"] as? String == "99") + let unsupported = details?["unsupported"] as? String + #expect(unsupported?.contains("Unsupported type:") == true) + } confirmed() } } @@ -850,9 +990,18 @@ struct GoogleSignInPluginTests { domain: "DisconnectDomain", code: 3, userInfo: ["reason": "failed"]) await confirmation("completion called") { confirmed in - plugin.disconnect { error in - #expect(error?.code == "DisconnectDomain: 3") - #expect((error?.details as? [String: Any])?["reason"] as? String == "failed") + plugin.disconnect { result in + switch result { + case .success: + Issue.record("Expected a PigeonError for a failed disconnect") + case .failure(let error): + guard let pigeonError = error as? PigeonError else { + Issue.record("Expected PigeonError, got \(error)") + break + } + #expect(pigeonError.code == "DisconnectDomain: 3") + #expect((pigeonError.details as? [String: Any])?["reason"] as? String == "failed") + } confirmed() } } @@ -867,10 +1016,18 @@ struct GoogleSignInPluginTests { fakeSignIn.signInResult = TestSignInResult(user: fakeUser) await confirmation("completion called") { confirmed in - plugin.signIn(withScopeHint: [], nonce: nil) { result, error in - #expect(error == nil) - #expect(result?.success?.user.photoUrl == nil) - #expect(result?.success?.user.displayName == "Name") + plugin.signIn(scopeHint: [], nonce: nil) { result in + switch result { + case .success(let signInResult): + guard let success = signInResult as? SignInSuccess else { + Issue.record("Unexpected type for \(signInResult)") + break + } + #expect(success.user.photoUrl == nil) + #expect(success.user.displayName == "Name") + case .failure(let error): + Issue.record("Unexpected error: \(error)") + } confirmed() } } @@ -899,10 +1056,18 @@ struct GoogleSignInPluginTests { let plugin = GoogleSignInPlugin( signIn: GIDSignInWrapper(), viewProvider: TestViewProvider()) await confirmation("completion called") { confirmed in - plugin.signIn(withScopeHint: [], nonce: nil) { result, error in - #expect(result == nil) - #expect(error?.code == "google_sign_in: 0") - #expect(error?.message == "No host view available to present Google Sign-In.") + plugin.signIn(scopeHint: [], nonce: nil) { result in + switch result { + case .success: + Issue.record("Expected a PigeonError when no presenter is available") + case .failure(let error): + guard let pigeonError = error as? PigeonError else { + Issue.record("Expected PigeonError, got \(error)") + break + } + #expect(pigeonError.code == "google_sign_in: 0") + #expect(pigeonError.message == "No host view available to present Google Sign-In.") + } confirmed() } } @@ -925,7 +1090,7 @@ struct GoogleSignInPluginTests { fakeSignIn.signInResult = TestSignInResult(user: TestGoogleUser("id")) await confirmation("completion called") { confirmed in - plugin.signIn(withScopeHint: [], nonce: nil) { _, _ in confirmed() } + plugin.signIn(scopeHint: [], nonce: nil) { _ in confirmed() } } #expect(fakeSignIn.presentingViewController === top) } @@ -943,7 +1108,7 @@ struct GoogleSignInPluginTests { fakeSignIn.signInResult = TestSignInResult(user: TestGoogleUser("id")) await confirmation("completion called") { confirmed in - plugin.signIn(withScopeHint: [], nonce: nil) { _, _ in confirmed() } + plugin.signIn(scopeHint: [], nonce: nil) { _ in confirmed() } } #expect(fakeSignIn.presentingViewController === selected) } @@ -958,7 +1123,7 @@ struct GoogleSignInPluginTests { fakeSignIn.signInResult = TestSignInResult(user: TestGoogleUser("id")) await confirmation("completion called") { confirmed in - plugin.signIn(withScopeHint: [], nonce: nil) { _, _ in confirmed() } + plugin.signIn(scopeHint: [], nonce: nil) { _ in confirmed() } } #expect(fakeSignIn.presentingViewController === presented) } diff --git a/packages/google_sign_in/google_sign_in_ios/darwin/google_sign_in_ios.podspec b/packages/google_sign_in/google_sign_in_ios/darwin/google_sign_in_ios.podspec index 0664dd087f1f..fe7352b798ea 100644 --- a/packages/google_sign_in/google_sign_in_ios/darwin/google_sign_in_ios.podspec +++ b/packages/google_sign_in/google_sign_in_ios/darwin/google_sign_in_ios.podspec @@ -12,8 +12,9 @@ Enables Google Sign-In in Flutter apps. s.license = { :type => 'BSD', :file => '../LICENSE' } s.author = { 'Flutter Team' => 'flutter-dev@googlegroups.com' } s.source = { :http => 'https://github.com/flutter/packages/tree/main/packages/google_sign_in/google_sign_in_ios' } - # Combine google_sign_in_ios and google_sign_in_ios_objc sources into a single - # pod, unlike SwiftPM, where separate Swift and Objective-C targets are required. + # Remaining Objective-C is ExceptionCatcher (NSException can't be caught from + # Swift) plus a CocoaPods placeholder header. SwiftPM needs a separate Obj-C + # target; CocoaPods compiles both into one pod. s.source_files = 'google_sign_in_ios/Sources/google_sign_in_ios*/**/*.{h,m,swift}' s.public_header_files = 'google_sign_in_ios/Sources/google_sign_in_ios_objc/include/**/*.h' s.swift_version = '5.0' diff --git a/packages/google_sign_in/google_sign_in_ios/darwin/google_sign_in_ios/Package.swift b/packages/google_sign_in/google_sign_in_ios/darwin/google_sign_in_ios/Package.swift index f3aa7ff0c04e..2c22d1072a9d 100644 --- a/packages/google_sign_in/google_sign_in_ios/darwin/google_sign_in_ios/Package.swift +++ b/packages/google_sign_in/google_sign_in_ios/darwin/google_sign_in_ios/Package.swift @@ -31,13 +31,12 @@ let package = Package( .process("Resources") ] ), + // Swift cannot catch NSException, so ExceptionCatcher.m stays in a separate + // Objective-C target. That target also holds the CocoaPods placeholder + // header required to import google_sign_in_ios.h. .target( name: "google_sign_in_ios_objc", - publicHeadersPath: "include", - cSettings: [ - .headerSearchPath("include/google_sign_in_ios"), - .headerSearchPath("include/google_sign_in_ios_objc"), - ] + publicHeadersPath: "include/google_sign_in_ios_objc" ), ] ) diff --git a/packages/google_sign_in/google_sign_in_ios/darwin/google_sign_in_ios/Sources/google_sign_in_ios/GoogleSignInPlugin.swift b/packages/google_sign_in/google_sign_in_ios/darwin/google_sign_in_ios/Sources/google_sign_in_ios/GoogleSignInPlugin.swift index eaa5bdb069da..11c64a864f07 100644 --- a/packages/google_sign_in/google_sign_in_ios/darwin/google_sign_in_ios/Sources/google_sign_in_ios/GoogleSignInPlugin.swift +++ b/packages/google_sign_in/google_sign_in_ios/darwin/google_sign_in_ios/Sources/google_sign_in_ios/GoogleSignInPlugin.swift @@ -31,17 +31,17 @@ private func loadGoogleServiceInfo() -> [String: Any]? { return NSDictionary(contentsOfFile: plistPath) as? [String: Any] } -/// Deep-converts values to something that can be safely encoded with the standard message codec, -/// for use in making NSError userInfo values safe to send as FlutterError details. -private func sanitizedUserInfo(_ value: Any?) -> Any { +/// Deep-converts a value to something that can be encoded with the standard +/// message codec, for use as Pigeon error details. +private func sanitizedCodecValue(_ value: Any) -> any Sendable { switch value { case let error as NSError: return [ "domain": error.domain, "code": "\(error.code)", "localizedDescription": error.localizedDescription, - "userInfo": sanitizedUserInfo(error.userInfo), - ] + "userInfo": sanitizedCodecDictionary(error.userInfo), + ] as [String: any Sendable] case let string as String: return string case let url as URL: @@ -49,35 +49,39 @@ private func sanitizedUserInfo(_ value: Any?) -> Any { case let number as NSNumber: return number case let array as [Any]: - return array.map { sanitizedUserInfo($0) } + return array.map { sanitizedCodecValue($0) } case let dict as [AnyHashable: Any]: - var safeValues: [AnyHashable: Any] = [:] - safeValues.reserveCapacity(dict.count) - for (key, nestedValue) in dict { - safeValues[key] = sanitizedUserInfo(nestedValue) - } - return safeValues + return sanitizedCodecDictionary(dict) default: - guard let value else { - return "[Unsupported type: (null)]" - } return "[Unsupported type: \(String(describing: type(of: value)))]" } } -/// Maps an NSError to a corresponding FlutterError. -/// -/// This should only be used when an error can't be recognized and mapped to a -/// GoogleSignInErrorCode. -private func flutterError(from error: NSError?) -> FlutterError { - return FlutterError( - code: String(format: "%@: %ld", error?.domain ?? "(null)", error?.code ?? 0), - message: error?.localizedDescription, - details: sanitizedUserInfo(error?.userInfo)) +private func sanitizedCodecDictionary(_ dict: [AnyHashable: Any]) -> [String: any Sendable] { + var safeValues: [String: any Sendable] = [:] + safeValues.reserveCapacity(dict.count) + for (key, nestedValue) in dict { + let stringKey = key as? String ?? String(describing: key) + safeValues[stringKey] = sanitizedCodecValue(nestedValue) + } + return safeValues +} + +extension PigeonError { + /// Maps an NSError to a corresponding PigeonError. + /// + /// This should only be used when an error can't be recognized and mapped to a + /// GoogleSignInErrorCode. + static func make(from error: NSError) -> PigeonError { + return PigeonError( + code: "\(error.domain): \(error.code)", + message: error.localizedDescription, + details: sanitizedCodecDictionary(error.userInfo)) + } } /// Maps a GIDSignInErrorCode to the corresponding Pigeon GoogleSignInErrorCode. -private func pigeonErrorCode(for gidSignInErrorCode: Int) -> FSIGoogleSignInErrorCode { +private func pigeonErrorCode(for gidSignInErrorCode: Int) -> GoogleSignInErrorCode { switch gidSignInErrorCode { case GIDSignInError.keychain.rawValue: return .keychainError @@ -96,7 +100,7 @@ private func pigeonErrorCode(for gidSignInErrorCode: Int) -> FSIGoogleSignInErro } } -public final class GoogleSignInPlugin: NSObject, FlutterPlugin, FSIGoogleSignInApi { +public final class GoogleSignInPlugin: NSObject, FlutterPlugin, GoogleSignInApi { /// Instance used to manage Google Sign In authentication including /// sign in, sign out, and requesting additional scopes. let signIn: any GIDSignInProtocol @@ -120,7 +124,7 @@ public final class GoogleSignInPlugin: NSObject, FlutterPlugin, FSIGoogleSignInA #else let messenger = registrar.messenger #endif - SetUpFSIGoogleSignInApi(messenger, instance) + GoogleSignInApiSetup.setUp(binaryMessenger: messenger, api: instance) } /// Inject view provider for testing. @@ -177,12 +181,9 @@ public final class GoogleSignInPlugin: NSObject, FlutterPlugin, FSIGoogleSignInA return handled } - // MARK: - FSIGoogleSignInApi + // MARK: - GoogleSignInApi - public func configure( - withParameters params: FSIPlatformConfigurationParams, - error: AutoreleasingUnsafeMutablePointer - ) { + func configure(params: PlatformConfigurationParams) throws { // If configuration information was passed from Dart, or present in GoogleService-Info.plist, // use that. Otherwise, keep the default configuration, which GIDSignIn will automatically // populate from Info.plist values (the recommended configuration method). @@ -195,19 +196,17 @@ public final class GoogleSignInPlugin: NSObject, FlutterPlugin, FSIGoogleSignInA } } - public func restorePreviousSignIn( - completion: @escaping (FSISignInResult?, FlutterError?) -> Void - ) { + func restorePreviousSignIn(completion: @escaping (Result) -> Void) { signIn.restorePreviousSignIn { [weak self] user, error in self?.handleAuthResult( user: user, serverAuthCode: nil, error: error, completion: completion) } } - public func signIn( - withScopeHint scopeHint: [String], + func signIn( + scopeHint: [String], nonce: String?, - completion: @escaping (FSISignInResult?, FlutterError?) -> Void + completion: @escaping (Result) -> Void ) { let exception = performSignIn(hint: nil, additionalScopes: scopeHint, nonce: nonce) { [weak self] signInResult, error in @@ -219,25 +218,23 @@ public final class GoogleSignInPlugin: NSObject, FlutterPlugin, FSIGoogleSignInA } if let exception { completion( - nil, - FlutterError( - code: "google_sign_in", message: exception.reason, details: exception.name.rawValue)) + .failure( + PigeonError( + code: "google_sign_in", message: exception.reason, details: exception.name.rawValue))) } } - public func refreshedAuthorizationTokens( - forUser userId: String, - completion: @escaping (FSISignInResult?, FlutterError?) -> Void + func getRefreshedAuthorizationTokens( + userId: String, + completion: @escaping (Result) -> Void ) { guard let user = usersByIdentifier[userId] else { completion( - FSISignInResult.make( - with: nil, - error: FSISignInFailure.make( - withType: .userMismatch, + .success( + SignInFailure( + type: .userMismatch, message: "The user is no longer signed in.", - details: nil)), - nil) + details: nil))) return } @@ -247,20 +244,18 @@ public final class GoogleSignInPlugin: NSObject, FlutterPlugin, FSIGoogleSignInA } } - public func addScopes( + func addScopes( _ scopes: [String], forUser userId: String, - completion: @escaping (FSISignInResult?, FlutterError?) -> Void + completion: @escaping (Result) -> Void ) { guard let user = usersByIdentifier[userId] else { completion( - FSISignInResult.make( - with: nil, - error: FSISignInFailure.make( - withType: .userMismatch, + .success( + SignInFailure( + type: .userMismatch, message: "The user is no longer signed in.", - details: nil)), - nil) + details: nil))) return } @@ -273,25 +268,25 @@ public final class GoogleSignInPlugin: NSObject, FlutterPlugin, FSIGoogleSignInA } if let exception { completion( - nil, - FlutterError( - code: "request_scopes", message: exception.reason, details: exception.name.rawValue)) + .failure( + PigeonError( + code: "request_scopes", message: exception.reason, details: exception.name.rawValue))) } } - public func signOutWithError(_ error: AutoreleasingUnsafeMutablePointer) { + func signOut() throws { signIn.signOut() // usersByIdentifier is left populated, because the SDK may still support some operations on the // GIDGoogleUser object (e.g., returning existing, non-expired tokens). Operations that the SDK // doesn't support will return SDK errors that we can handle as normal. } - public func disconnect(completion: @escaping (FlutterError?) -> Void) { + func disconnect(completion: @escaping (Result) -> Void) { signIn.disconnect { error in if let error { - completion(flutterError(from: error as NSError)) + completion(.failure(PigeonError.make(from: error as NSError))) } else { - completion(nil) + completion(.success(())) } } } @@ -372,7 +367,7 @@ public final class GoogleSignInPlugin: NSObject, FlutterPlugin, FSIGoogleSignInA user: (any GIDGoogleUserProtocol)?, serverAuthCode: String?, error: Error?, - completion: @escaping (FSISignInResult?, FlutterError?) -> Void + completion: @escaping (Result) -> Void ) { if let user { didSignIn(for: user, serverAuthCode: serverAuthCode, completion: completion) @@ -384,30 +379,37 @@ public final class GoogleSignInPlugin: NSObject, FlutterPlugin, FSIGoogleSignInA let nsError = error as NSError? if let nsError, nsError.domain == kGIDSignInErrorDomain { completion( - FSISignInResult.make( - with: nil, - error: FSISignInFailure.make( - withType: pigeonErrorCode(for: nsError.code), + .success( + SignInFailure( + type: pigeonErrorCode(for: nsError.code), message: nsError.localizedDescription, - details: sanitizedUserInfo(nsError.userInfo))), - nil) + details: sanitizedCodecDictionary(nsError.userInfo)))) + } else if let nsError { + completion(.failure(PigeonError.make(from: nsError))) } else { - completion(nil, flutterError(from: nsError)) + // GIDSignIn is expected to provide a user or an error. Keep a defensive + // fallback with a clear message rather than reporting a codec placeholder. + completion( + .failure( + PigeonError( + code: "google_sign_in", + message: "Sign-in completed without a user or an error.", + details: nil))) } } private func didSignIn( for user: any GIDGoogleUserProtocol, serverAuthCode: String?, - completion: @escaping (FSISignInResult?, FlutterError?) -> Void + completion: @escaping (Result) -> Void ) { guard let userID = user.userID else { completion( - nil, - FlutterError( - code: "google_sign_in", - message: "Google Sign-In succeeded without a user ID.", - details: nil)) + .failure( + PigeonError( + code: "google_sign_in", + message: "Google Sign-In succeeded without a user ID.", + details: nil))) return } usersByIdentifier[userID] = user @@ -418,20 +420,19 @@ public final class GoogleSignInPlugin: NSObject, FlutterPlugin, FSIGoogleSignInA photoURL = user.profile?.imageURL(withDimension: 1337) } - let userData = FSIUserData.make( - withDisplayName: user.profile?.name, + let userData = UserData( + displayName: user.profile?.name, email: user.profile?.email ?? "", userId: userID, photoUrl: photoURL?.absoluteString, idToken: user.idToken?.tokenString) - let result = FSISignInResult.make( - with: FSISignInSuccess.make( - withUser: userData, - accessToken: user.accessToken.tokenString, - grantedScopes: user.grantedScopes ?? [], - serverAuthCode: serverAuthCode), - error: nil) - completion(result, nil) + completion( + .success( + SignInSuccess( + user: userData, + accessToken: user.accessToken.tokenString, + grantedScopes: user.grantedScopes ?? [], + serverAuthCode: serverAuthCode))) } #if os(iOS) diff --git a/packages/google_sign_in/google_sign_in_ios/darwin/google_sign_in_ios/Sources/google_sign_in_ios/messages.g.swift b/packages/google_sign_in/google_sign_in_ios/darwin/google_sign_in_ios/Sources/google_sign_in_ios/messages.g.swift new file mode 100644 index 000000000000..5e01d19c4ad4 --- /dev/null +++ b/packages/google_sign_in/google_sign_in_ios/darwin/google_sign_in_ios/Sources/google_sign_in_ios/messages.g.swift @@ -0,0 +1,673 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v27.3.2), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +import Foundation + +#if os(iOS) + import Flutter +#elseif os(macOS) + import FlutterMacOS +#else + #error("Unsupported platform.") +#endif + +/// Error class for passing custom error details to Dart side. +final class PigeonError: Error { + let code: String + let message: String? + let details: Sendable? + + init(code: String, message: String?, details: Sendable?) { + self.code = code + self.message = message + self.details = details + } + + var localizedDescription: String { + return + "PigeonError(code: \(code), message: \(message ?? ""), details: \(details ?? "")" + } +} + +private func wrapResult(_ result: Any?) -> [Any?] { + return [result] +} + +private func wrapError(_ error: Any) -> [Any?] { + if let pigeonError = error as? PigeonError { + return [ + pigeonError.code, + pigeonError.message, + pigeonError.details, + ] + } + if let flutterError = error as? FlutterError { + return [ + flutterError.code, + flutterError.message, + flutterError.details, + ] + } + return [ + "\(error)", + "\(Swift.type(of: error))", + "Stacktrace: \(Thread.callStackSymbols)", + ] +} + +enum MessagesPigeonInternal { + static func isNullish(_ value: Any?) -> Bool { + guard let innerValue = value else { + return true + } + + if case Optional.some(Optional.none) = value { + return true + } + + return innerValue is NSNull + } + static func doubleEquals(_ lhs: Double, _ rhs: Double) -> Bool { + return (lhs.isNaN && rhs.isNaN) || lhs == rhs + } + + static func doubleHash(_ value: Double, _ hasher: inout Hasher) { + if value.isNaN { + hasher.combine(0x7FF8_0000_0000_0000) + } else { + // Normalize -0.0 to 0.0 + hasher.combine(value == 0 ? 0 : value) + } + } + + static func deepEquals(_ lhs: Any?, _ rhs: Any?) -> Bool { + let cleanLhs = nilOrValue(lhs) as Any? + let cleanRhs = nilOrValue(rhs) as Any? + switch (cleanLhs, cleanRhs) { + case (nil, nil): + return true + + case (nil, _), (_, nil): + return false + + case (let lhs as AnyObject, let rhs as AnyObject) where lhs === rhs: + return true + + case is (Void, Void): + return true + + case (let lhsArray, let rhsArray) as ([Any?], [Any?]): + guard lhsArray.count == rhsArray.count else { return false } + for (index, element) in lhsArray.enumerated() { + if !deepEquals(element, rhsArray[index]) { + return false + } + } + return true + + case (let lhsArray, let rhsArray) as ([Double], [Double]): + guard lhsArray.count == rhsArray.count else { return false } + for (index, element) in lhsArray.enumerated() { + if !doubleEquals(element, rhsArray[index]) { + return false + } + } + return true + + case (let lhsDictionary, let rhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]): + guard lhsDictionary.count == rhsDictionary.count else { return false } + for (lhsKey, lhsValue) in lhsDictionary { + var found = false + for (rhsKey, rhsValue) in rhsDictionary { + if deepEquals(lhsKey, rhsKey) { + if deepEquals(lhsValue, rhsValue) { + found = true + break + } else { + return false + } + } + } + if !found { return false } + } + return true + + case (let lhs as Double, let rhs as Double): + return doubleEquals(lhs, rhs) + + case (let lhsHashable, let rhsHashable) as (AnyHashable, AnyHashable): + return lhsHashable == rhsHashable + + default: + return false + } + } + + static func deepHash(value: Any?, hasher: inout Hasher) { + let cleanValue = nilOrValue(value) as Any? + if let cleanValue = cleanValue { + if let doubleValue = cleanValue as? Double { + doubleHash(doubleValue, &hasher) + } else if let valueList = cleanValue as? [Any?] { + for item in valueList { + deepHash(value: item, hasher: &hasher) + } + } else if let valueList = cleanValue as? [Double] { + for item in valueList { + doubleHash(item, &hasher) + } + } else if let valueDict = cleanValue as? [AnyHashable: Any?] { + var result = 0 + for (key, value) in valueDict { + var entryKeyHasher = Hasher() + deepHash(value: key, hasher: &entryKeyHasher) + var entryValueHasher = Hasher() + deepHash(value: value, hasher: &entryValueHasher) + result = result &+ ((entryKeyHasher.finalize() &* 31) ^ entryValueHasher.finalize()) + } + hasher.combine(result) + } else if let hashableValue = cleanValue as? AnyHashable { + hasher.combine(hashableValue) + } else { + hasher.combine(String(describing: cleanValue)) + } + } else { + hasher.combine(0) + } + } + +} + +private func nilOrValue(_ value: Any?) -> T? { + if value is NSNull { return nil } + return value as! T? +} + +/// Enum mapping of known codes from +/// https://developers.google.com/identity/sign-in/ios/reference/Enums/GIDSignInErrorCode +enum GoogleSignInErrorCode: Int, CaseIterable { + /// Either the underlying kGIDSignInErrorCodeUnknown, or a code that isn't + /// a known code mapped to a value below. + case unknown = 0 + /// kGIDSignInErrorCodeKeychain; an error reading or writing to keychain. + case keychainError = 1 + /// kGIDSignInErrorCodeHasNoAuthInKeychain; no auth present in the keychain. + /// + /// For restorePreviousSignIn, this indicates that there is no sign in to + /// restore. + case noAuthInKeychain = 2 + /// kGIDSignInErrorCodeCanceled; the request was canceled by the user. + case canceled = 3 + /// kGIDSignInErrorCodeEMM; an enterprise management error occurred. + case eemError = 4 + /// kGIDSignInErrorCodeScopesAlreadyGranted; the requested scopes have already + /// been granted. + case scopesAlreadyGranted = 5 + /// kGIDSignInErrorCodeMismatchWithCurrentUser; an operation was requested on + /// a non-current user. + case userMismatch = 6 +} + +/// Generated class from Pigeon that represents data sent in messages. +struct PlatformConfigurationParams: Hashable, CustomStringConvertible { + var clientId: String? = nil + var serverClientId: String? = nil + var hostedDomain: String? = nil + + // swift-format-ignore: AlwaysUseLowerCamelCase + static func fromList(_ pigeonVar_list: [Any?]) -> PlatformConfigurationParams? { + let clientId: String? = nilOrValue(pigeonVar_list[0]) + let serverClientId: String? = nilOrValue(pigeonVar_list[1]) + let hostedDomain: String? = nilOrValue(pigeonVar_list[2]) + + return PlatformConfigurationParams( + clientId: clientId, + serverClientId: serverClientId, + hostedDomain: hostedDomain + ) + } + func toList() -> [Any?] { + return [ + clientId, + serverClientId, + hostedDomain, + ] + } + static func == (lhs: PlatformConfigurationParams, rhs: PlatformConfigurationParams) -> Bool { + if Swift.type(of: lhs) != Swift.type(of: rhs) { + return false + } + return MessagesPigeonInternal.deepEquals(lhs.clientId, rhs.clientId) + && MessagesPigeonInternal.deepEquals(lhs.serverClientId, rhs.serverClientId) + && MessagesPigeonInternal.deepEquals(lhs.hostedDomain, rhs.hostedDomain) + } + + func hash(into hasher: inout Hasher) { + hasher.combine("PlatformConfigurationParams") + MessagesPigeonInternal.deepHash(value: clientId, hasher: &hasher) + MessagesPigeonInternal.deepHash(value: serverClientId, hasher: &hasher) + MessagesPigeonInternal.deepHash(value: hostedDomain, hasher: &hasher) + } + + public var description: String { + return + "PlatformConfigurationParams(clientId: \(String(describing: clientId)), serverClientId: \(String(describing: serverClientId)), hostedDomain: \(String(describing: hostedDomain)))" + } +} + +/// Pigeon version of GoogleSignInUserData + AuthenticationTokenData. +/// +/// See GoogleSignInUserData and AuthenticationTokenData for details. +/// +/// Generated class from Pigeon that represents data sent in messages. +struct UserData: Hashable, CustomStringConvertible { + var displayName: String? = nil + var email: String + var userId: String + var photoUrl: String? = nil + var idToken: String? = nil + + // swift-format-ignore: AlwaysUseLowerCamelCase + static func fromList(_ pigeonVar_list: [Any?]) -> UserData? { + let displayName: String? = nilOrValue(pigeonVar_list[0]) + let email = pigeonVar_list[1] as! String + let userId = pigeonVar_list[2] as! String + let photoUrl: String? = nilOrValue(pigeonVar_list[3]) + let idToken: String? = nilOrValue(pigeonVar_list[4]) + + return UserData( + displayName: displayName, + email: email, + userId: userId, + photoUrl: photoUrl, + idToken: idToken + ) + } + func toList() -> [Any?] { + return [ + displayName, + email, + userId, + photoUrl, + idToken, + ] + } + static func == (lhs: UserData, rhs: UserData) -> Bool { + if Swift.type(of: lhs) != Swift.type(of: rhs) { + return false + } + return MessagesPigeonInternal.deepEquals(lhs.displayName, rhs.displayName) + && MessagesPigeonInternal.deepEquals(lhs.email, rhs.email) + && MessagesPigeonInternal.deepEquals(lhs.userId, rhs.userId) + && MessagesPigeonInternal.deepEquals(lhs.photoUrl, rhs.photoUrl) + && MessagesPigeonInternal.deepEquals(lhs.idToken, rhs.idToken) + } + + func hash(into hasher: inout Hasher) { + hasher.combine("UserData") + MessagesPigeonInternal.deepHash(value: displayName, hasher: &hasher) + MessagesPigeonInternal.deepHash(value: email, hasher: &hasher) + MessagesPigeonInternal.deepHash(value: userId, hasher: &hasher) + MessagesPigeonInternal.deepHash(value: photoUrl, hasher: &hasher) + MessagesPigeonInternal.deepHash(value: idToken, hasher: &hasher) + } + + public var description: String { + return + "UserData(displayName: \(String(describing: displayName)), email: \(String(describing: email)), userId: \(String(describing: userId)), photoUrl: \(String(describing: photoUrl)), idToken: \(String(describing: idToken)))" + } +} + +/// The response from an auth call. +/// +/// Generated class from Pigeon that represents data sent in messages. +/// This protocol should not be extended by any user class outside of the generated file. +protocol SignInResult { + +} + +/// A sign in failure. +/// +/// Generated class from Pigeon that represents data sent in messages. +struct SignInFailure: SignInResult { + /// The type of failure. + var type: GoogleSignInErrorCode + /// The message associated with the failure, if any. + var message: String? = nil + /// Extra details about the failure, if any. + var details: Any? = nil + + // swift-format-ignore: AlwaysUseLowerCamelCase + static func fromList(_ pigeonVar_list: [Any?]) -> SignInFailure? { + let type = pigeonVar_list[0] as! GoogleSignInErrorCode + let message: String? = nilOrValue(pigeonVar_list[1]) + let details: Any? = pigeonVar_list[2] + + return SignInFailure( + type: type, + message: message, + details: details + ) + } + func toList() -> [Any?] { + return [ + type, + message, + details, + ] + } + static func == (lhs: SignInFailure, rhs: SignInFailure) -> Bool { + if Swift.type(of: lhs) != Swift.type(of: rhs) { + return false + } + return MessagesPigeonInternal.deepEquals(lhs.type, rhs.type) + && MessagesPigeonInternal.deepEquals(lhs.message, rhs.message) + && MessagesPigeonInternal.deepEquals(lhs.details, rhs.details) + } + + func hash(into hasher: inout Hasher) { + hasher.combine("SignInFailure") + MessagesPigeonInternal.deepHash(value: type, hasher: &hasher) + MessagesPigeonInternal.deepHash(value: message, hasher: &hasher) + MessagesPigeonInternal.deepHash(value: details, hasher: &hasher) + } + + public var description: String { + return + "SignInFailure(type: \(String(describing: type)), message: \(String(describing: message)), details: \(String(describing: details)))" + } +} + +/// A successful auth result. +/// +/// Corresponds to the information in a native GIDSignInResult. Because of the +/// structure of the Google Sign In SDK, this has information corresponding to +/// both authn and authz steps, even though incremental authorization is +/// supported. +/// +/// Generated class from Pigeon that represents data sent in messages. +struct SignInSuccess: SignInResult { + var user: UserData + var accessToken: String + var grantedScopes: [String] + var serverAuthCode: String? = nil + + // swift-format-ignore: AlwaysUseLowerCamelCase + static func fromList(_ pigeonVar_list: [Any?]) -> SignInSuccess? { + let user = pigeonVar_list[0] as! UserData + let accessToken = pigeonVar_list[1] as! String + let grantedScopes = pigeonVar_list[2] as! [String] + let serverAuthCode: String? = nilOrValue(pigeonVar_list[3]) + + return SignInSuccess( + user: user, + accessToken: accessToken, + grantedScopes: grantedScopes, + serverAuthCode: serverAuthCode + ) + } + func toList() -> [Any?] { + return [ + user, + accessToken, + grantedScopes, + serverAuthCode, + ] + } + static func == (lhs: SignInSuccess, rhs: SignInSuccess) -> Bool { + if Swift.type(of: lhs) != Swift.type(of: rhs) { + return false + } + return MessagesPigeonInternal.deepEquals(lhs.user, rhs.user) + && MessagesPigeonInternal.deepEquals(lhs.accessToken, rhs.accessToken) + && MessagesPigeonInternal.deepEquals(lhs.grantedScopes, rhs.grantedScopes) + && MessagesPigeonInternal.deepEquals(lhs.serverAuthCode, rhs.serverAuthCode) + } + + func hash(into hasher: inout Hasher) { + hasher.combine("SignInSuccess") + MessagesPigeonInternal.deepHash(value: user, hasher: &hasher) + MessagesPigeonInternal.deepHash(value: accessToken, hasher: &hasher) + MessagesPigeonInternal.deepHash(value: grantedScopes, hasher: &hasher) + MessagesPigeonInternal.deepHash(value: serverAuthCode, hasher: &hasher) + } + + public var description: String { + return + "SignInSuccess(user: \(String(describing: user)), accessToken: \(String(describing: accessToken)), grantedScopes: \(String(describing: grantedScopes)), serverAuthCode: \(String(describing: serverAuthCode)))" + } +} + +private class MessagesPigeonCodecReader: FlutterStandardReader { + override func readValue(ofType type: UInt8) -> Any? { + switch type { + case 129: + let enumResultAsInt: Int? = nilOrValue(self.readValue() as! Int?) + if let enumResultAsInt = enumResultAsInt { + return GoogleSignInErrorCode(rawValue: enumResultAsInt) + } + return nil + case 130: + return PlatformConfigurationParams.fromList(self.readValue() as! [Any?]) + case 131: + return UserData.fromList(self.readValue() as! [Any?]) + case 132: + return SignInFailure.fromList(self.readValue() as! [Any?]) + case 133: + return SignInSuccess.fromList(self.readValue() as! [Any?]) + default: + return super.readValue(ofType: type) + } + } +} + +private class MessagesPigeonCodecWriter: FlutterStandardWriter { + override func writeValue(_ value: Any) { + if let value = value as? GoogleSignInErrorCode { + super.writeByte(129) + super.writeValue(value.rawValue) + } else if let value = value as? PlatformConfigurationParams { + super.writeByte(130) + super.writeValue(value.toList()) + } else if let value = value as? UserData { + super.writeByte(131) + super.writeValue(value.toList()) + } else if let value = value as? SignInFailure { + super.writeByte(132) + super.writeValue(value.toList()) + } else if let value = value as? SignInSuccess { + super.writeByte(133) + super.writeValue(value.toList()) + } else { + super.writeValue(value) + } + } +} + +private class MessagesPigeonCodecReaderWriter: FlutterStandardReaderWriter { + override func reader(with data: Data) -> FlutterStandardReader { + return MessagesPigeonCodecReader(data: data) + } + + override func writer(with data: NSMutableData) -> FlutterStandardWriter { + return MessagesPigeonCodecWriter(data: data) + } +} + +class MessagesPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { + static let shared = MessagesPigeonCodec(readerWriter: MessagesPigeonCodecReaderWriter()) +} + +/// Generated protocol from Pigeon that represents a handler of messages from Flutter. +protocol GoogleSignInApi { + /// Configures the sign in object with application-level parameters. + func configure(params: PlatformConfigurationParams) throws + /// Attempts to restore an existing sign-in, if any, with minimal user + /// interaction. + func restorePreviousSignIn(completion: @escaping (Result) -> Void) + /// Starts a sign in with user interaction. + func signIn( + scopeHint: [String], nonce: String?, completion: @escaping (Result) -> Void + ) + /// Requests the access token for the current sign in. + func getRefreshedAuthorizationTokens( + userId: String, completion: @escaping (Result) -> Void) + /// Requests authorization of the given additional scopes. + func addScopes( + _ scopes: [String], forUser userId: String, + completion: @escaping (Result) -> Void) + /// Signs out the current user. + func signOut() throws + /// Revokes scope grants to the application. + func disconnect(completion: @escaping (Result) -> Void) +} + +/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. +class GoogleSignInApiSetup { + static var codec: FlutterStandardMessageCodec { MessagesPigeonCodec.shared } + /// Sets up an instance of `GoogleSignInApi` to handle messages through the `binaryMessenger`. + static func setUp( + binaryMessenger: FlutterBinaryMessenger, api: GoogleSignInApi?, + messageChannelSuffix: String = "" + ) { + let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" + /// Configures the sign in object with application-level parameters. + let configureChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_sign_in_ios.GoogleSignInApi.configure\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + configureChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let paramsArg = args[0] as! PlatformConfigurationParams + do { + try api.configure(params: paramsArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + configureChannel.setMessageHandler(nil) + } + /// Attempts to restore an existing sign-in, if any, with minimal user + /// interaction. + let restorePreviousSignInChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.google_sign_in_ios.GoogleSignInApi.restorePreviousSignIn\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + restorePreviousSignInChannel.setMessageHandler { _, reply in + api.restorePreviousSignIn { result in + switch result { + case .success(let res): + reply(wrapResult(res)) + case .failure(let error): + reply(wrapError(error)) + } + } + } + } else { + restorePreviousSignInChannel.setMessageHandler(nil) + } + /// Starts a sign in with user interaction. + let signInChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_sign_in_ios.GoogleSignInApi.signIn\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + signInChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let scopeHintArg = args[0] as! [String] + let nonceArg: String? = nilOrValue(args[1]) + api.signIn(scopeHint: scopeHintArg, nonce: nonceArg) { result in + switch result { + case .success(let res): + reply(wrapResult(res)) + case .failure(let error): + reply(wrapError(error)) + } + } + } + } else { + signInChannel.setMessageHandler(nil) + } + /// Requests the access token for the current sign in. + let getRefreshedAuthorizationTokensChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.google_sign_in_ios.GoogleSignInApi.getRefreshedAuthorizationTokens\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + getRefreshedAuthorizationTokensChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let userIdArg = args[0] as! String + api.getRefreshedAuthorizationTokens(userId: userIdArg) { result in + switch result { + case .success(let res): + reply(wrapResult(res)) + case .failure(let error): + reply(wrapError(error)) + } + } + } + } else { + getRefreshedAuthorizationTokensChannel.setMessageHandler(nil) + } + /// Requests authorization of the given additional scopes. + let addScopesChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_sign_in_ios.GoogleSignInApi.addScopes\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + addScopesChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let scopesArg = args[0] as! [String] + let userIdArg = args[1] as! String + api.addScopes(scopesArg, forUser: userIdArg) { result in + switch result { + case .success(let res): + reply(wrapResult(res)) + case .failure(let error): + reply(wrapError(error)) + } + } + } + } else { + addScopesChannel.setMessageHandler(nil) + } + /// Signs out the current user. + let signOutChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_sign_in_ios.GoogleSignInApi.signOut\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + signOutChannel.setMessageHandler { _, reply in + do { + try api.signOut() + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + signOutChannel.setMessageHandler(nil) + } + /// Revokes scope grants to the application. + let disconnectChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_sign_in_ios.GoogleSignInApi.disconnect\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + disconnectChannel.setMessageHandler { _, reply in + api.disconnect { result in + switch result { + case .success: + reply(wrapResult(nil)) + case .failure(let error): + reply(wrapError(error)) + } + } + } + } else { + disconnectChannel.setMessageHandler(nil) + } + } +} diff --git a/packages/google_sign_in/google_sign_in_ios/darwin/google_sign_in_ios/Sources/google_sign_in_ios_objc/include/google_sign_in_ios/messages.g.h b/packages/google_sign_in/google_sign_in_ios/darwin/google_sign_in_ios/Sources/google_sign_in_ios_objc/include/google_sign_in_ios/messages.g.h deleted file mode 100644 index 8a42064cd2cc..000000000000 --- a/packages/google_sign_in/google_sign_in_ios/darwin/google_sign_in_ios/Sources/google_sign_in_ios_objc/include/google_sign_in_ios/messages.g.h +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// Autogenerated from Pigeon (v27.3.2), do not edit directly. -// See also: https://pub.dev/packages/pigeon - -@import Foundation; - -@protocol FlutterBinaryMessenger; -@protocol FlutterMessageCodec; -@class FlutterError; -@class FlutterStandardTypedData; - -NS_ASSUME_NONNULL_BEGIN - -/// Enum mapping of known codes from -/// https://developers.google.com/identity/sign-in/ios/reference/Enums/GIDSignInErrorCode -typedef NS_ENUM(NSUInteger, FSIGoogleSignInErrorCode) { - /// Either the underlying kGIDSignInErrorCodeUnknown, or a code that isn't - /// a known code mapped to a value below. - FSIGoogleSignInErrorCodeUnknown = 0, - /// kGIDSignInErrorCodeKeychain; an error reading or writing to keychain. - FSIGoogleSignInErrorCodeKeychainError = 1, - /// kGIDSignInErrorCodeHasNoAuthInKeychain; no auth present in the keychain. - /// - /// For restorePreviousSignIn, this indicates that there is no sign in to - /// restore. - FSIGoogleSignInErrorCodeNoAuthInKeychain = 2, - /// kGIDSignInErrorCodeCanceled; the request was canceled by the user. - FSIGoogleSignInErrorCodeCanceled = 3, - /// kGIDSignInErrorCodeEMM; an enterprise management error occurred. - FSIGoogleSignInErrorCodeEemError = 4, - /// kGIDSignInErrorCodeScopesAlreadyGranted; the requested scopes have already - /// been granted. - FSIGoogleSignInErrorCodeScopesAlreadyGranted = 5, - /// kGIDSignInErrorCodeMismatchWithCurrentUser; an operation was requested on - /// a non-current user. - FSIGoogleSignInErrorCodeUserMismatch = 6, -}; - -/// Wrapper for FSIGoogleSignInErrorCode to allow for nullability. -@interface FSIGoogleSignInErrorCodeBox : NSObject -@property(nonatomic, assign) FSIGoogleSignInErrorCode value; -- (instancetype)initWithValue:(FSIGoogleSignInErrorCode)value; -@end - -@class FSIPlatformConfigurationParams; -@class FSIUserData; -@class FSISignInResult; -@class FSISignInFailure; -@class FSISignInSuccess; - -@interface FSIPlatformConfigurationParams : NSObject -+ (instancetype)makeWithClientId:(nullable NSString *)clientId - serverClientId:(nullable NSString *)serverClientId - hostedDomain:(nullable NSString *)hostedDomain; -@property(nonatomic, copy, nullable) NSString *clientId; -@property(nonatomic, copy, nullable) NSString *serverClientId; -@property(nonatomic, copy, nullable) NSString *hostedDomain; -@end - -/// Pigeon version of GoogleSignInUserData + AuthenticationTokenData. -/// -/// See GoogleSignInUserData and AuthenticationTokenData for details. -@interface FSIUserData : NSObject -/// `init` unavailable to enforce nonnull fields, see the `make` class method. -- (instancetype)init NS_UNAVAILABLE; -+ (instancetype)makeWithDisplayName:(nullable NSString *)displayName - email:(NSString *)email - userId:(NSString *)userId - photoUrl:(nullable NSString *)photoUrl - idToken:(nullable NSString *)idToken; -@property(nonatomic, copy, nullable) NSString *displayName; -@property(nonatomic, copy) NSString *email; -@property(nonatomic, copy) NSString *userId; -@property(nonatomic, copy, nullable) NSString *photoUrl; -@property(nonatomic, copy, nullable) NSString *idToken; -@end - -/// The response from an auth call. -@interface FSISignInResult : NSObject -+ (instancetype)makeWithSuccess:(nullable FSISignInSuccess *)success - error:(nullable FSISignInFailure *)error; -/// The success result, if any. -/// -/// Exactly one of success and error will be non-nil. -@property(nonatomic, strong, nullable) FSISignInSuccess *success; -/// The error result, if any. -/// -/// Exactly one of success and error will be non-nil. -@property(nonatomic, strong, nullable) FSISignInFailure *error; -@end - -/// An sign in failure. -@interface FSISignInFailure : NSObject -/// `init` unavailable to enforce nonnull fields, see the `make` class method. -- (instancetype)init NS_UNAVAILABLE; -+ (instancetype)makeWithType:(FSIGoogleSignInErrorCode)type - message:(nullable NSString *)message - details:(nullable id)details; -/// The type of failure. -@property(nonatomic, assign) FSIGoogleSignInErrorCode type; -/// The message associated with the failure, if any. -@property(nonatomic, copy, nullable) NSString *message; -/// Extra details about the failure, if any. -@property(nonatomic, strong, nullable) id details; -@end - -/// A successful auth result. -/// -/// Corresponds to the information in a native GIDSignInResult. Because of the -/// structure of the Google Sign In SDK, this has information corresponding to -/// both authn and authz steps, even though incremental authorization is -/// supported. -@interface FSISignInSuccess : NSObject -/// `init` unavailable to enforce nonnull fields, see the `make` class method. -- (instancetype)init NS_UNAVAILABLE; -+ (instancetype)makeWithUser:(FSIUserData *)user - accessToken:(NSString *)accessToken - grantedScopes:(NSArray *)grantedScopes - serverAuthCode:(nullable NSString *)serverAuthCode; -@property(nonatomic, strong) FSIUserData *user; -@property(nonatomic, copy) NSString *accessToken; -@property(nonatomic, copy) NSArray *grantedScopes; -@property(nonatomic, copy, nullable) NSString *serverAuthCode; -@end - -/// The codec used by all APIs. -NSObject *FSIGetMessagesCodec(void); - -@protocol FSIGoogleSignInApi -/// Configures the sign in object with application-level parameters. -- (void)configureWithParameters:(FSIPlatformConfigurationParams *)params - error:(FlutterError *_Nullable *_Nonnull)error; -/// Attempts to restore an existing sign-in, if any, with minimal user -/// interaction. -- (void)restorePreviousSignInWithCompletion:(void (^)(FSISignInResult *_Nullable, - FlutterError *_Nullable))completion; -/// Starts a sign in with user interaction. -- (void)signInWithScopeHint:(NSArray *)scopeHint - nonce:(nullable NSString *)nonce - completion: - (void (^)(FSISignInResult *_Nullable, FlutterError *_Nullable))completion; -/// Requests the access token for the current sign in. -- (void)refreshedAuthorizationTokensForUser:(NSString *)userId - completion:(void (^)(FSISignInResult *_Nullable, - FlutterError *_Nullable))completion; -/// Requests authorization of the given additional scopes. -- (void)addScopes:(NSArray *)scopes - forUser:(NSString *)userId - completion:(void (^)(FSISignInResult *_Nullable, FlutterError *_Nullable))completion; -/// Signs out the current user. -- (void)signOutWithError:(FlutterError *_Nullable *_Nonnull)error; -/// Revokes scope grants to the application. -- (void)disconnectWithCompletion:(void (^)(FlutterError *_Nullable))completion; -@end - -extern void SetUpFSIGoogleSignInApi(id binaryMessenger, - NSObject *_Nullable api); - -extern void SetUpFSIGoogleSignInApiWithSuffix(id binaryMessenger, - NSObject *_Nullable api, - NSString *messageChannelSuffix); - -NS_ASSUME_NONNULL_END diff --git a/packages/google_sign_in/google_sign_in_ios/darwin/google_sign_in_ios/Sources/google_sign_in_ios_objc/messages.g.m b/packages/google_sign_in/google_sign_in_ios/darwin/google_sign_in_ios/Sources/google_sign_in_ios_objc/messages.g.m deleted file mode 100644 index 21a8e10bc3af..000000000000 --- a/packages/google_sign_in/google_sign_in_ios/darwin/google_sign_in_ios/Sources/google_sign_in_ios_objc/messages.g.m +++ /dev/null @@ -1,718 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// Autogenerated from Pigeon (v27.3.2), do not edit directly. -// See also: https://pub.dev/packages/pigeon - -#import "./include/google_sign_in_ios/messages.g.h" - -#if TARGET_OS_OSX -@import FlutterMacOS; -#else -@import Flutter; -#endif - -static BOOL __attribute__((unused)) FLTPigeonDeepEquals(id _Nullable a, id _Nullable b) { - if (a == b) { - return YES; - } - if (a == nil) { - return b == [NSNull null]; - } - if (b == nil) { - return a == [NSNull null]; - } - if ([a isKindOfClass:[NSNumber class]] && [b isKindOfClass:[NSNumber class]]) { - return - [a isEqual:b] || (isnan([(NSNumber *)a doubleValue]) && isnan([(NSNumber *)b doubleValue])); - } - if ([a isKindOfClass:[NSArray class]] && [b isKindOfClass:[NSArray class]]) { - NSArray *arrayA = (NSArray *)a; - NSArray *arrayB = (NSArray *)b; - if (arrayA.count != arrayB.count) { - return NO; - } - for (NSUInteger i = 0; i < arrayA.count; i++) { - if (!FLTPigeonDeepEquals(arrayA[i], arrayB[i])) { - return NO; - } - } - return YES; - } - if ([a isKindOfClass:[NSDictionary class]] && [b isKindOfClass:[NSDictionary class]]) { - NSDictionary *dictA = (NSDictionary *)a; - NSDictionary *dictB = (NSDictionary *)b; - if (dictA.count != dictB.count) { - return NO; - } - for (id keyA in dictA) { - id valueA = dictA[keyA]; - BOOL found = NO; - for (id keyB in dictB) { - if (FLTPigeonDeepEquals(keyA, keyB)) { - id valueB = dictB[keyB]; - if (FLTPigeonDeepEquals(valueA, valueB)) { - found = YES; - break; - } else { - return NO; - } - } - } - if (!found) { - return NO; - } - } - return YES; - } - return [a isEqual:b]; -} - -static NSUInteger __attribute__((unused)) FLTPigeonDeepHash(id _Nullable value) { - if (value == nil || value == (id)[NSNull null]) { - return 0; - } - if ([value isKindOfClass:[NSNumber class]]) { - NSNumber *n = (NSNumber *)value; - double d = n.doubleValue; - if (isnan(d)) { - // Normalize NaN to a consistent hash. - return (NSUInteger)0x7FF8000000000000; - } - if (d == 0.0) { - // Normalize -0.0 to 0.0 so they have the same hash code. - d = 0.0; - } - return @(d).hash; - } - if ([value isKindOfClass:[NSArray class]]) { - NSUInteger result = 1; - for (id item in (NSArray *)value) { - result = result * 31 + FLTPigeonDeepHash(item); - } - return result; - } - if ([value isKindOfClass:[NSDictionary class]]) { - NSUInteger result = 0; - NSDictionary *dict = (NSDictionary *)value; - for (id key in dict) { - result += ((FLTPigeonDeepHash(key) * 31) ^ FLTPigeonDeepHash(dict[key])); - } - return result; - } - return [value hash]; -} - -static NSArray *wrapResult(id result, FlutterError *error) { - if (error) { - return @[ - error.code ?: [NSNull null], error.message ?: [NSNull null], error.details ?: [NSNull null] - ]; - } - return @[ result ?: [NSNull null] ]; -} - -static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) { - id result = array[key]; - return (result == [NSNull null]) ? nil : result; -} - -/// Enum mapping of known codes from -/// https://developers.google.com/identity/sign-in/ios/reference/Enums/GIDSignInErrorCode -@implementation FSIGoogleSignInErrorCodeBox -- (instancetype)initWithValue:(FSIGoogleSignInErrorCode)value { - self = [super init]; - if (self) { - _value = value; - } - return self; -} -@end - -@interface FSIPlatformConfigurationParams () -+ (FSIPlatformConfigurationParams *)fromList:(NSArray *)list; -+ (nullable FSIPlatformConfigurationParams *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; -@end - -@interface FSIUserData () -+ (FSIUserData *)fromList:(NSArray *)list; -+ (nullable FSIUserData *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; -@end - -@interface FSISignInResult () -+ (FSISignInResult *)fromList:(NSArray *)list; -+ (nullable FSISignInResult *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; -@end - -@interface FSISignInFailure () -+ (FSISignInFailure *)fromList:(NSArray *)list; -+ (nullable FSISignInFailure *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; -@end - -@interface FSISignInSuccess () -+ (FSISignInSuccess *)fromList:(NSArray *)list; -+ (nullable FSISignInSuccess *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; -@end - -@implementation FSIPlatformConfigurationParams -+ (instancetype)makeWithClientId:(nullable NSString *)clientId - serverClientId:(nullable NSString *)serverClientId - hostedDomain:(nullable NSString *)hostedDomain { - FSIPlatformConfigurationParams *pigeonResult = [[FSIPlatformConfigurationParams alloc] init]; - pigeonResult.clientId = clientId; - pigeonResult.serverClientId = serverClientId; - pigeonResult.hostedDomain = hostedDomain; - return pigeonResult; -} -+ (FSIPlatformConfigurationParams *)fromList:(NSArray *)list { - FSIPlatformConfigurationParams *pigeonResult = [[FSIPlatformConfigurationParams alloc] init]; - pigeonResult.clientId = GetNullableObjectAtIndex(list, 0); - pigeonResult.serverClientId = GetNullableObjectAtIndex(list, 1); - pigeonResult.hostedDomain = GetNullableObjectAtIndex(list, 2); - return pigeonResult; -} -+ (nullable FSIPlatformConfigurationParams *)nullableFromList:(NSArray *)list { - return (list) ? [FSIPlatformConfigurationParams fromList:list] : nil; -} -- (NSArray *)toList { - return @[ - self.clientId ?: [NSNull null], - self.serverClientId ?: [NSNull null], - self.hostedDomain ?: [NSNull null], - ]; -} -- (BOOL)isEqual:(id)object { - if (self == object) { - return YES; - } - if (![object isKindOfClass:[self class]]) { - return NO; - } - FSIPlatformConfigurationParams *other = (FSIPlatformConfigurationParams *)object; - return FLTPigeonDeepEquals(self.clientId, other.clientId) && - FLTPigeonDeepEquals(self.serverClientId, other.serverClientId) && - FLTPigeonDeepEquals(self.hostedDomain, other.hostedDomain); -} - -- (NSUInteger)hash { - NSUInteger result = [self class].hash; - result = result * 31 + FLTPigeonDeepHash(self.clientId); - result = result * 31 + FLTPigeonDeepHash(self.serverClientId); - result = result * 31 + FLTPigeonDeepHash(self.hostedDomain); - return result; -} -- (NSString *)description { - return [NSString - stringWithFormat: - @"FSIPlatformConfigurationParams(clientId: %@, serverClientId: %@, hostedDomain: %@)", - self.clientId, self.serverClientId, self.hostedDomain]; -} -@end - -@implementation FSIUserData -+ (instancetype)makeWithDisplayName:(nullable NSString *)displayName - email:(NSString *)email - userId:(NSString *)userId - photoUrl:(nullable NSString *)photoUrl - idToken:(nullable NSString *)idToken { - FSIUserData *pigeonResult = [[FSIUserData alloc] init]; - pigeonResult.displayName = displayName; - pigeonResult.email = email; - pigeonResult.userId = userId; - pigeonResult.photoUrl = photoUrl; - pigeonResult.idToken = idToken; - return pigeonResult; -} -+ (FSIUserData *)fromList:(NSArray *)list { - FSIUserData *pigeonResult = [[FSIUserData alloc] init]; - pigeonResult.displayName = GetNullableObjectAtIndex(list, 0); - pigeonResult.email = GetNullableObjectAtIndex(list, 1); - pigeonResult.userId = GetNullableObjectAtIndex(list, 2); - pigeonResult.photoUrl = GetNullableObjectAtIndex(list, 3); - pigeonResult.idToken = GetNullableObjectAtIndex(list, 4); - return pigeonResult; -} -+ (nullable FSIUserData *)nullableFromList:(NSArray *)list { - return (list) ? [FSIUserData fromList:list] : nil; -} -- (NSArray *)toList { - return @[ - self.displayName ?: [NSNull null], - self.email ?: [NSNull null], - self.userId ?: [NSNull null], - self.photoUrl ?: [NSNull null], - self.idToken ?: [NSNull null], - ]; -} -- (BOOL)isEqual:(id)object { - if (self == object) { - return YES; - } - if (![object isKindOfClass:[self class]]) { - return NO; - } - FSIUserData *other = (FSIUserData *)object; - return FLTPigeonDeepEquals(self.displayName, other.displayName) && - FLTPigeonDeepEquals(self.email, other.email) && - FLTPigeonDeepEquals(self.userId, other.userId) && - FLTPigeonDeepEquals(self.photoUrl, other.photoUrl) && - FLTPigeonDeepEquals(self.idToken, other.idToken); -} - -- (NSUInteger)hash { - NSUInteger result = [self class].hash; - result = result * 31 + FLTPigeonDeepHash(self.displayName); - result = result * 31 + FLTPigeonDeepHash(self.email); - result = result * 31 + FLTPigeonDeepHash(self.userId); - result = result * 31 + FLTPigeonDeepHash(self.photoUrl); - result = result * 31 + FLTPigeonDeepHash(self.idToken); - return result; -} -- (NSString *)description { - return [NSString - stringWithFormat: - @"FSIUserData(displayName: %@, email: %@, userId: %@, photoUrl: %@, idToken: %@)", - self.displayName, self.email, self.userId, self.photoUrl, self.idToken]; -} -@end - -@implementation FSISignInResult -+ (instancetype)makeWithSuccess:(nullable FSISignInSuccess *)success - error:(nullable FSISignInFailure *)error { - FSISignInResult *pigeonResult = [[FSISignInResult alloc] init]; - pigeonResult.success = success; - pigeonResult.error = error; - return pigeonResult; -} -+ (FSISignInResult *)fromList:(NSArray *)list { - FSISignInResult *pigeonResult = [[FSISignInResult alloc] init]; - pigeonResult.success = GetNullableObjectAtIndex(list, 0); - pigeonResult.error = GetNullableObjectAtIndex(list, 1); - return pigeonResult; -} -+ (nullable FSISignInResult *)nullableFromList:(NSArray *)list { - return (list) ? [FSISignInResult fromList:list] : nil; -} -- (NSArray *)toList { - return @[ - self.success ?: [NSNull null], - self.error ?: [NSNull null], - ]; -} -- (BOOL)isEqual:(id)object { - if (self == object) { - return YES; - } - if (![object isKindOfClass:[self class]]) { - return NO; - } - FSISignInResult *other = (FSISignInResult *)object; - return FLTPigeonDeepEquals(self.success, other.success) && - FLTPigeonDeepEquals(self.error, other.error); -} - -- (NSUInteger)hash { - NSUInteger result = [self class].hash; - result = result * 31 + FLTPigeonDeepHash(self.success); - result = result * 31 + FLTPigeonDeepHash(self.error); - return result; -} -- (NSString *)description { - return [NSString - stringWithFormat:@"FSISignInResult(success: %@, error: %@)", self.success, self.error]; -} -@end - -@implementation FSISignInFailure -+ (instancetype)makeWithType:(FSIGoogleSignInErrorCode)type - message:(nullable NSString *)message - details:(nullable id)details { - FSISignInFailure *pigeonResult = [[FSISignInFailure alloc] init]; - pigeonResult.type = type; - pigeonResult.message = message; - pigeonResult.details = details; - return pigeonResult; -} -+ (FSISignInFailure *)fromList:(NSArray *)list { - FSISignInFailure *pigeonResult = [[FSISignInFailure alloc] init]; - FSIGoogleSignInErrorCodeBox *boxedFSIGoogleSignInErrorCode = GetNullableObjectAtIndex(list, 0); - pigeonResult.type = boxedFSIGoogleSignInErrorCode.value; - pigeonResult.message = GetNullableObjectAtIndex(list, 1); - pigeonResult.details = GetNullableObjectAtIndex(list, 2); - return pigeonResult; -} -+ (nullable FSISignInFailure *)nullableFromList:(NSArray *)list { - return (list) ? [FSISignInFailure fromList:list] : nil; -} -- (NSArray *)toList { - return @[ - [[FSIGoogleSignInErrorCodeBox alloc] initWithValue:self.type], - self.message ?: [NSNull null], - self.details ?: [NSNull null], - ]; -} -- (BOOL)isEqual:(id)object { - if (self == object) { - return YES; - } - if (![object isKindOfClass:[self class]]) { - return NO; - } - FSISignInFailure *other = (FSISignInFailure *)object; - return self.type == other.type && FLTPigeonDeepEquals(self.message, other.message) && - FLTPigeonDeepEquals(self.details, other.details); -} - -- (NSUInteger)hash { - NSUInteger result = [self class].hash; - result = result * 31 + @(self.type).hash; - result = result * 31 + FLTPigeonDeepHash(self.message); - result = result * 31 + FLTPigeonDeepHash(self.details); - return result; -} -- (NSString *)description { - return [NSString stringWithFormat:@"FSISignInFailure(type: %ld, message: %@, details: %@)", - (long)self.type, self.message, self.details]; -} -@end - -@implementation FSISignInSuccess -+ (instancetype)makeWithUser:(FSIUserData *)user - accessToken:(NSString *)accessToken - grantedScopes:(NSArray *)grantedScopes - serverAuthCode:(nullable NSString *)serverAuthCode { - FSISignInSuccess *pigeonResult = [[FSISignInSuccess alloc] init]; - pigeonResult.user = user; - pigeonResult.accessToken = accessToken; - pigeonResult.grantedScopes = grantedScopes; - pigeonResult.serverAuthCode = serverAuthCode; - return pigeonResult; -} -+ (FSISignInSuccess *)fromList:(NSArray *)list { - FSISignInSuccess *pigeonResult = [[FSISignInSuccess alloc] init]; - pigeonResult.user = GetNullableObjectAtIndex(list, 0); - pigeonResult.accessToken = GetNullableObjectAtIndex(list, 1); - pigeonResult.grantedScopes = GetNullableObjectAtIndex(list, 2); - pigeonResult.serverAuthCode = GetNullableObjectAtIndex(list, 3); - return pigeonResult; -} -+ (nullable FSISignInSuccess *)nullableFromList:(NSArray *)list { - return (list) ? [FSISignInSuccess fromList:list] : nil; -} -- (NSArray *)toList { - return @[ - self.user ?: [NSNull null], - self.accessToken ?: [NSNull null], - self.grantedScopes ?: [NSNull null], - self.serverAuthCode ?: [NSNull null], - ]; -} -- (BOOL)isEqual:(id)object { - if (self == object) { - return YES; - } - if (![object isKindOfClass:[self class]]) { - return NO; - } - FSISignInSuccess *other = (FSISignInSuccess *)object; - return FLTPigeonDeepEquals(self.user, other.user) && - FLTPigeonDeepEquals(self.accessToken, other.accessToken) && - FLTPigeonDeepEquals(self.grantedScopes, other.grantedScopes) && - FLTPigeonDeepEquals(self.serverAuthCode, other.serverAuthCode); -} - -- (NSUInteger)hash { - NSUInteger result = [self class].hash; - result = result * 31 + FLTPigeonDeepHash(self.user); - result = result * 31 + FLTPigeonDeepHash(self.accessToken); - result = result * 31 + FLTPigeonDeepHash(self.grantedScopes); - result = result * 31 + FLTPigeonDeepHash(self.serverAuthCode); - return result; -} -- (NSString *)description { - return [NSString - stringWithFormat: - @"FSISignInSuccess(user: %@, accessToken: %@, grantedScopes: %@, serverAuthCode: %@)", - self.user, self.accessToken, self.grantedScopes, self.serverAuthCode]; -} -@end - -@interface FSIMessagesPigeonCodecReader : FlutterStandardReader -@end -@implementation FSIMessagesPigeonCodecReader -- (nullable id)readValueOfType:(UInt8)type { - switch (type) { - case 129: { - NSNumber *enumAsNumber = [self readValue]; - return enumAsNumber == nil - ? nil - : [[FSIGoogleSignInErrorCodeBox alloc] initWithValue:[enumAsNumber integerValue]]; - } - case 130: - return [FSIPlatformConfigurationParams fromList:[self readValue]]; - case 131: - return [FSIUserData fromList:[self readValue]]; - case 132: - return [FSISignInResult fromList:[self readValue]]; - case 133: - return [FSISignInFailure fromList:[self readValue]]; - case 134: - return [FSISignInSuccess fromList:[self readValue]]; - default: - return [super readValueOfType:type]; - } -} -@end - -@interface FSIMessagesPigeonCodecWriter : FlutterStandardWriter -@end -@implementation FSIMessagesPigeonCodecWriter -- (void)writeValue:(id)value { - if ([value isKindOfClass:[FSIGoogleSignInErrorCodeBox class]]) { - FSIGoogleSignInErrorCodeBox *box = (FSIGoogleSignInErrorCodeBox *)value; - [self writeByte:129]; - [self writeValue:(value == nil ? [NSNull null] : [NSNumber numberWithInteger:box.value])]; - } else if ([value isKindOfClass:[FSIPlatformConfigurationParams class]]) { - [self writeByte:130]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[FSIUserData class]]) { - [self writeByte:131]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[FSISignInResult class]]) { - [self writeByte:132]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[FSISignInFailure class]]) { - [self writeByte:133]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[FSISignInSuccess class]]) { - [self writeByte:134]; - [self writeValue:[value toList]]; - } else { - [super writeValue:value]; - } -} -@end - -@interface FSIMessagesPigeonCodecReaderWriter : FlutterStandardReaderWriter -@end -@implementation FSIMessagesPigeonCodecReaderWriter -- (FlutterStandardWriter *)writerWithData:(NSMutableData *)data { - return [[FSIMessagesPigeonCodecWriter alloc] initWithData:data]; -} -- (FlutterStandardReader *)readerWithData:(NSData *)data { - return [[FSIMessagesPigeonCodecReader alloc] initWithData:data]; -} -@end - -NSObject *FSIGetMessagesCodec(void) { - static FlutterStandardMessageCodec *sSharedObject = nil; - static dispatch_once_t sPred = 0; - dispatch_once(&sPred, ^{ - FSIMessagesPigeonCodecReaderWriter *readerWriter = - [[FSIMessagesPigeonCodecReaderWriter alloc] init]; - sSharedObject = [FlutterStandardMessageCodec codecWithReaderWriter:readerWriter]; - }); - return sSharedObject; -} -void SetUpFSIGoogleSignInApi(id binaryMessenger, - NSObject *api) { - SetUpFSIGoogleSignInApiWithSuffix(binaryMessenger, api, @""); -} - -void SetUpFSIGoogleSignInApiWithSuffix(id binaryMessenger, - NSObject *api, - NSString *messageChannelSuffix) { - messageChannelSuffix = messageChannelSuffix.length > 0 - ? [NSString stringWithFormat:@".%@", messageChannelSuffix] - : @""; - /// Configures the sign in object with application-level parameters. - { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:[NSString - stringWithFormat: - @"%@%@", - @"dev.flutter.pigeon.google_sign_in_ios.GoogleSignInApi.configure", - messageChannelSuffix] - binaryMessenger:binaryMessenger - codec:FSIGetMessagesCodec()]; - if (api) { - NSCAssert([api respondsToSelector:@selector(configureWithParameters:error:)], - @"FSIGoogleSignInApi api (%@) doesn't respond to " - @"@selector(configureWithParameters:error:)", - api); - [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; - FSIPlatformConfigurationParams *arg_params = GetNullableObjectAtIndex(args, 0); - FlutterError *error; - [api configureWithParameters:arg_params error:&error]; - callback(wrapResult(nil, error)); - }]; - } else { - [channel setMessageHandler:nil]; - } - } - /// Attempts to restore an existing sign-in, if any, with minimal user - /// interaction. - { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:[NSString stringWithFormat:@"%@%@", - @"dev.flutter.pigeon.google_sign_in_ios." - @"GoogleSignInApi.restorePreviousSignIn", - messageChannelSuffix] - binaryMessenger:binaryMessenger - codec:FSIGetMessagesCodec()]; - if (api) { - NSCAssert([api respondsToSelector:@selector(restorePreviousSignInWithCompletion:)], - @"FSIGoogleSignInApi api (%@) doesn't respond to " - @"@selector(restorePreviousSignInWithCompletion:)", - api); - [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - [api restorePreviousSignInWithCompletion:^(FSISignInResult *_Nullable output, - FlutterError *_Nullable error) { - callback(wrapResult(output, error)); - }]; - }]; - } else { - [channel setMessageHandler:nil]; - } - } - /// Starts a sign in with user interaction. - { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName: - [NSString - stringWithFormat:@"%@%@", - @"dev.flutter.pigeon.google_sign_in_ios.GoogleSignInApi.signIn", - messageChannelSuffix] - binaryMessenger:binaryMessenger - codec:FSIGetMessagesCodec()]; - if (api) { - NSCAssert([api respondsToSelector:@selector(signInWithScopeHint:nonce:completion:)], - @"FSIGoogleSignInApi api (%@) doesn't respond to " - @"@selector(signInWithScopeHint:nonce:completion:)", - api); - [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; - NSArray *arg_scopeHint = GetNullableObjectAtIndex(args, 0); - NSString *arg_nonce = GetNullableObjectAtIndex(args, 1); - [api signInWithScopeHint:arg_scopeHint - nonce:arg_nonce - completion:^(FSISignInResult *_Nullable output, - FlutterError *_Nullable error) { - callback(wrapResult(output, error)); - }]; - }]; - } else { - [channel setMessageHandler:nil]; - } - } - /// Requests the access token for the current sign in. - { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:[NSString - stringWithFormat:@"%@%@", - @"dev.flutter.pigeon.google_sign_in_ios." - @"GoogleSignInApi.getRefreshedAuthorizationTokens", - messageChannelSuffix] - binaryMessenger:binaryMessenger - codec:FSIGetMessagesCodec()]; - if (api) { - NSCAssert([api respondsToSelector:@selector(refreshedAuthorizationTokensForUser:completion:)], - @"FSIGoogleSignInApi api (%@) doesn't respond to " - @"@selector(refreshedAuthorizationTokensForUser:completion:)", - api); - [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; - NSString *arg_userId = GetNullableObjectAtIndex(args, 0); - [api refreshedAuthorizationTokensForUser:arg_userId - completion:^(FSISignInResult *_Nullable output, - FlutterError *_Nullable error) { - callback(wrapResult(output, error)); - }]; - }]; - } else { - [channel setMessageHandler:nil]; - } - } - /// Requests authorization of the given additional scopes. - { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:[NSString - stringWithFormat: - @"%@%@", - @"dev.flutter.pigeon.google_sign_in_ios.GoogleSignInApi.addScopes", - messageChannelSuffix] - binaryMessenger:binaryMessenger - codec:FSIGetMessagesCodec()]; - if (api) { - NSCAssert([api respondsToSelector:@selector(addScopes:forUser:completion:)], - @"FSIGoogleSignInApi api (%@) doesn't respond to " - @"@selector(addScopes:forUser:completion:)", - api); - [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; - NSArray *arg_scopes = GetNullableObjectAtIndex(args, 0); - NSString *arg_userId = GetNullableObjectAtIndex(args, 1); - [api addScopes:arg_scopes - forUser:arg_userId - completion:^(FSISignInResult *_Nullable output, FlutterError *_Nullable error) { - callback(wrapResult(output, error)); - }]; - }]; - } else { - [channel setMessageHandler:nil]; - } - } - /// Signs out the current user. - { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:[NSString - stringWithFormat: - @"%@%@", - @"dev.flutter.pigeon.google_sign_in_ios.GoogleSignInApi.signOut", - messageChannelSuffix] - binaryMessenger:binaryMessenger - codec:FSIGetMessagesCodec()]; - if (api) { - NSCAssert([api respondsToSelector:@selector(signOutWithError:)], - @"FSIGoogleSignInApi api (%@) doesn't respond to @selector(signOutWithError:)", - api); - [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - FlutterError *error; - [api signOutWithError:&error]; - callback(wrapResult(nil, error)); - }]; - } else { - [channel setMessageHandler:nil]; - } - } - /// Revokes scope grants to the application. - { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:[NSString - stringWithFormat: - @"%@%@", - @"dev.flutter.pigeon.google_sign_in_ios.GoogleSignInApi.disconnect", - messageChannelSuffix] - binaryMessenger:binaryMessenger - codec:FSIGetMessagesCodec()]; - if (api) { - NSCAssert( - [api respondsToSelector:@selector(disconnectWithCompletion:)], - @"FSIGoogleSignInApi api (%@) doesn't respond to @selector(disconnectWithCompletion:)", - api); - [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - [api disconnectWithCompletion:^(FlutterError *_Nullable error) { - callback(wrapResult(nil, error)); - }]; - }]; - } else { - [channel setMessageHandler:nil]; - } - } -} diff --git a/packages/google_sign_in/google_sign_in_ios/lib/google_sign_in_ios.dart b/packages/google_sign_in/google_sign_in_ios/lib/google_sign_in_ios.dart index c1fe921a1c5b..b1368a1adb41 100644 --- a/packages/google_sign_in/google_sign_in_ios/lib/google_sign_in_ios.dart +++ b/packages/google_sign_in/google_sign_in_ios/lib/google_sign_in_ios.dart @@ -58,26 +58,18 @@ class GoogleSignInIOS extends GoogleSignInPlatform { AttemptLightweightAuthenticationParameters params, ) async { final SignInResult result = await _api.restorePreviousSignIn(); - - if (result.error?.type == GoogleSignInErrorCode.noAuthInKeychain) { - return null; - } - - final SignInFailure? failure = result.error; - if (failure != null) { - throw GoogleSignInException( - code: _exceptionCodeForErrorPlatformErrorCode(failure.type), - description: failure.message, - details: failure.details, - ); + switch (result) { + case SignInFailure(type: GoogleSignInErrorCode.noAuthInKeychain): + return null; + case SignInFailure(:final type, :final message, :final details): + throw GoogleSignInException( + code: _exceptionCodeForErrorPlatformErrorCode(type), + description: message, + details: details, + ); + case SignInSuccess(): + return _authenticationResultsFromSignInSuccess(result); } - - // The native code must never return a null success and a null error. - // Switching the native implementation to Swift and using sealed classes - // in the Pigeon definition (see Android's messages.dart) will allow - // enforcing this via the type system instead of force unwrapping. - final SignInSuccess success = result.success!; - return _authenticationResultsFromSignInSuccess(success); } @override @@ -86,31 +78,23 @@ class GoogleSignInIOS extends GoogleSignInPlatform { @override Future authenticate(AuthenticateParameters params) async { final SignInResult result = await _signIn(params.scopeHint, _nonce); - - // This should never happen; the corresponding native error code is - // documented as being specific to restorePreviousSignIn. - if (result.error?.type == GoogleSignInErrorCode.noAuthInKeychain) { - throw const GoogleSignInException( - code: GoogleSignInExceptionCode.unknownError, - description: 'No auth reported during interactive sign in.', - ); + switch (result) { + // This should never happen; the corresponding native error code is + // documented as being specific to restorePreviousSignIn. + case SignInFailure(type: GoogleSignInErrorCode.noAuthInKeychain): + throw const GoogleSignInException( + code: GoogleSignInExceptionCode.unknownError, + description: 'No auth reported during interactive sign in.', + ); + case SignInFailure(:final type, :final message, :final details): + throw GoogleSignInException( + code: _exceptionCodeForErrorPlatformErrorCode(type), + description: message, + details: details, + ); + case SignInSuccess(): + return _authenticationResultsFromSignInSuccess(result); } - - final SignInFailure? failure = result.error; - if (failure != null) { - throw GoogleSignInException( - code: _exceptionCodeForErrorPlatformErrorCode(failure.type), - description: failure.message, - details: failure.details, - ); - } - - // The native code must never return a null success and a null error. - // Switching the native implementation to Swift and using sealed classes - // in the Pigeon definition (see Android's messages.dart) will allow - // enforcing this via the type system instead of force unwrapping. - final SignInSuccess success = result.success!; - return _authenticationResultsFromSignInSuccess(success); } @override @@ -154,30 +138,28 @@ class GoogleSignInIOS extends GoogleSignInPlatform { Future<({String? accessToken, String? serverAuthCode})> _getAuthorizationTokens( AuthorizationRequestDetails request, ) async { - String? userId = request.userId; - + final String userId; // The Google Sign In SDK requires authentication before authorization, so // if the authentication isn't associated with an existing sign-in user // run the authentication flow first. - if (userId == null) { - SignInResult result = await _api.restorePreviousSignIn(); - final SignInSuccess? success = result.success; - if (success == null) { - // There's no existing sign-in to use, so return the results of the - // combined authn+authz flow, if prompting is allowed. - if (request.promptIfUnauthorized) { - result = await _signIn(request.scopes, _nonce); - return _processAuthorizationResult(result); - } else { + if (request.userId case final requestedUserId?) { + userId = requestedUserId; + } else { + switch (await _api.restorePreviousSignIn()) { + case SignInSuccess(:final UserData user): + // Discard the authentication information, and extract the user ID to + // pass back to the authorization step so that it can re-associate + // with the currently signed in user on the native side. + userId = user.userId; + case SignInFailure(): + // There's no existing sign-in to use, so return the results of the + // combined authn+authz flow, if prompting is allowed. + if (request.promptIfUnauthorized) { + return _processAuthorizationResult(await _signIn(request.scopes, _nonce)); + } // No existing authentication, and no prompting allowed, so return // no tokens. return (accessToken: null, serverAuthCode: null); - } - } else { - // Discard the authentication information, and extract the user ID to - // pass back to the authorization step so that it can re-associate - // with the currently signed in user on the native side. - userId = success.user.userId; } } @@ -186,13 +168,14 @@ class GoogleSignInIOS extends GoogleSignInPlatform { ? await _api.getRefreshedAuthorizationTokens(userId) : await _addScopes(request.scopes, userId); if (!useExistingAuthorization && - result.error?.type == GoogleSignInErrorCode.scopesAlreadyGranted) { + result is SignInFailure && + result.type == GoogleSignInErrorCode.scopesAlreadyGranted) { // The Google Sign In SDK returns an error when requesting scopes that are // already authorized, so in that case request updated tokens instead to // construct a valid token response. result = await _api.getRefreshedAuthorizationTokens(userId); } - if (result.error?.type == GoogleSignInErrorCode.noAuthInKeychain) { + if (result is SignInFailure && result.type == GoogleSignInErrorCode.noAuthInKeychain) { return (accessToken: null, serverAuthCode: null); } @@ -200,7 +183,6 @@ class GoogleSignInIOS extends GoogleSignInPlatform { // requested scopes before returning it, as the list of requested scopes // may have changed since the last authorization. if (useExistingAuthorization) { - final SignInSuccess? success = result.success; // Don't validate the OpenID Connect scopes (see // https://developers.google.com/identity/protocols/oauth2/scopes#openid-connect // for details), as they should always be available, and the granted @@ -208,7 +190,7 @@ class GoogleSignInIOS extends GoogleSignInPlatform { // For example, requesting 'email' can instead result in the grant // 'https://www.googleapis.com/auth/userinfo.email'. const openIdConnectScopes = {'email', 'openid', 'profile'}; - if (success != null) { + if (result case final SignInSuccess success) { if (request.scopes.any( (String scope) => !openIdConnectScopes.contains(scope) && !success.grantedScopes.contains(scope), @@ -224,21 +206,21 @@ class GoogleSignInIOS extends GoogleSignInPlatform { Future<({String? accessToken, String? serverAuthCode})> _processAuthorizationResult( SignInResult result, ) async { - final SignInFailure? failure = result.error; - if (failure != null) { - throw GoogleSignInException( - code: _exceptionCodeForErrorPlatformErrorCode(failure.type), - description: failure.message, - details: failure.details, - ); + switch (result) { + case SignInFailure(:final type, :final message, :final details): + throw GoogleSignInException( + code: _exceptionCodeForErrorPlatformErrorCode(type), + description: message, + details: details, + ); + case SignInSuccess(): + return _authorizationTokenDataFromSignInSuccess(result); } - - return _authorizationTokenDataFromSignInSuccess(result.success); } Future _signIn(List scopeHint, String? nonce) async { final SignInResult result = await _api.signIn(scopeHint, nonce); - _updateAuthCodeCache(result.success); + _updateAuthCodeCache(result is SignInSuccess ? result : null); return result; } @@ -247,8 +229,8 @@ class GoogleSignInIOS extends GoogleSignInPlatform { // Don't clear the cache for GoogleSignInErrorCode.scopesAlreadyGranted // since that indicates that nothing has changed. Otherwise, update the // cache (with a new token on success, or clearing on failure). - if (result.error?.type != GoogleSignInErrorCode.scopesAlreadyGranted) { - _updateAuthCodeCache(result.success); + if (result is! SignInFailure || result.type != GoogleSignInErrorCode.scopesAlreadyGranted) { + _updateAuthCodeCache(result is SignInSuccess ? result : null); } return result; } @@ -273,17 +255,16 @@ class GoogleSignInIOS extends GoogleSignInPlatform { } ({String? accessToken, String? serverAuthCode}) _authorizationTokenDataFromSignInSuccess( - SignInSuccess? result, + SignInSuccess result, ) { // Check for a relevant cached auth code to add if needed. - final String? cachedAuthCode = - result != null && result.user.userId == _cachedServerAuthCodeUserId + final String? cachedAuthCode = result.user.userId == _cachedServerAuthCodeUserId ? _cachedServerAuthCode : null; return ( - accessToken: result?.accessToken, - serverAuthCode: result?.serverAuthCode ?? cachedAuthCode, + accessToken: result.accessToken, + serverAuthCode: result.serverAuthCode ?? cachedAuthCode, ); } diff --git a/packages/google_sign_in/google_sign_in_ios/lib/src/messages.g.dart b/packages/google_sign_in/google_sign_in_ios/lib/src/messages.g.dart index c71cfdd6d04c..e8f450c747bb 100644 --- a/packages/google_sign_in/google_sign_in_ios/lib/src/messages.g.dart +++ b/packages/google_sign_in/google_sign_in_ios/lib/src/messages.g.dart @@ -247,56 +247,10 @@ class UserData { } /// The response from an auth call. -class SignInResult { - SignInResult({this.success, this.error}); +sealed class SignInResult {} - /// The success result, if any. - /// - /// Exactly one of success and error will be non-nil. - SignInSuccess? success; - - /// The error result, if any. - /// - /// Exactly one of success and error will be non-nil. - SignInFailure? error; - - List _toList() { - return [success, error]; - } - - Object encode() { - return _toList(); - } - - static SignInResult decode(Object result) { - result as List; - return SignInResult(success: result[0] as SignInSuccess?, error: result[1] as SignInFailure?); - } - - @override - // ignore: avoid_equals_and_hash_code_on_mutable_classes - bool operator ==(Object other) { - if (other is! SignInResult || other.runtimeType != runtimeType) { - return false; - } - if (identical(this, other)) { - return true; - } - return _deepEquals(success, other.success) && _deepEquals(error, other.error); - } - - @override - // ignore: avoid_equals_and_hash_code_on_mutable_classes - int get hashCode => _deepHash([runtimeType, ..._toList()]); - - @override - String toString() { - return 'SignInResult(success: $success, error: $error)'; - } -} - -/// An sign in failure. -class SignInFailure { +/// A sign in failure. +class SignInFailure extends SignInResult { SignInFailure({required this.type, this.message, this.details}); /// The type of failure. @@ -355,7 +309,7 @@ class SignInFailure { /// structure of the Google Sign In SDK, this has information corresponding to /// both authn and authz steps, even though incremental authorization is /// supported. -class SignInSuccess { +class SignInSuccess extends SignInResult { SignInSuccess({ required this.user, required this.accessToken, @@ -430,14 +384,11 @@ class _PigeonCodec extends StandardMessageCodec { } else if (value is UserData) { buffer.putUint8(131); writeValue(buffer, value.encode()); - } else if (value is SignInResult) { - buffer.putUint8(132); - writeValue(buffer, value.encode()); } else if (value is SignInFailure) { - buffer.putUint8(133); + buffer.putUint8(132); writeValue(buffer, value.encode()); } else if (value is SignInSuccess) { - buffer.putUint8(134); + buffer.putUint8(133); writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); @@ -455,10 +406,8 @@ class _PigeonCodec extends StandardMessageCodec { case 131: return UserData.decode(readValue(buffer)!); case 132: - return SignInResult.decode(readValue(buffer)!); - case 133: return SignInFailure.decode(readValue(buffer)!); - case 134: + case 133: return SignInSuccess.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); diff --git a/packages/google_sign_in/google_sign_in_ios/pigeons/messages.dart b/packages/google_sign_in/google_sign_in_ios/pigeons/messages.dart index 39770692c23b..f35708bf505c 100644 --- a/packages/google_sign_in/google_sign_in_ios/pigeons/messages.dart +++ b/packages/google_sign_in/google_sign_in_ios/pigeons/messages.dart @@ -7,13 +7,8 @@ import 'package:pigeon/pigeon.dart'; @ConfigurePigeon( PigeonOptions( dartOut: 'lib/src/messages.g.dart', - objcHeaderOut: - 'darwin/google_sign_in_ios/Sources/google_sign_in_ios_objc/include/google_sign_in_ios/messages.g.h', - objcSourceOut: 'darwin/google_sign_in_ios/Sources/google_sign_in_ios_objc/messages.g.m', - objcOptions: ObjcOptions( - prefix: 'FSI', - headerIncludePath: './include/google_sign_in_ios/messages.g.h', - ), + swiftOut: 'darwin/google_sign_in_ios/Sources/google_sign_in_ios/messages.g.swift', + swiftOptions: SwiftOptions(fileSpecificClassNameComponent: 'Messages'), copyrightHeader: 'pigeons/copyright.txt', ), ) @@ -76,22 +71,10 @@ enum GoogleSignInErrorCode { } /// The response from an auth call. -// TODO(stuartmorgan): Switch to a sealed base class with two subclasses instead -// of using composition when the plugin is migrated to Swift. -class SignInResult { - /// The success result, if any. - /// - /// Exactly one of success and error will be non-nil. - SignInSuccess? success; - - /// The error result, if any. - /// - /// Exactly one of success and error will be non-nil. - SignInFailure? error; -} +sealed class SignInResult {} -/// An sign in failure. -class SignInFailure { +/// A sign in failure. +class SignInFailure extends SignInResult { /// The type of failure. late GoogleSignInErrorCode type; @@ -108,7 +91,7 @@ class SignInFailure { /// structure of the Google Sign In SDK, this has information corresponding to /// both authn and authz steps, even though incremental authorization is /// supported. -class SignInSuccess { +class SignInSuccess extends SignInResult { late UserData user; late String accessToken; @@ -124,7 +107,6 @@ class SignInSuccess { @HostApi() abstract class GoogleSignInApi { /// Configures the sign in object with application-level parameters. - @ObjCSelector('configureWithParameters:') void configure(PlatformConfigurationParams params); /// Attempts to restore an existing sign-in, if any, with minimal user @@ -134,17 +116,15 @@ abstract class GoogleSignInApi { /// Starts a sign in with user interaction. @async - @ObjCSelector('signInWithScopeHint:nonce:') SignInResult signIn(List scopeHint, String? nonce); /// Requests the access token for the current sign in. @async - @ObjCSelector('refreshedAuthorizationTokensForUser:') SignInResult getRefreshedAuthorizationTokens(String userId); /// Requests authorization of the given additional scopes. @async - @ObjCSelector('addScopes:forUser:') + @SwiftFunction('addScopes(_:forUser:)') SignInResult addScopes(List scopes, String userId); /// Signs out the current user. diff --git a/packages/google_sign_in/google_sign_in_ios/pubspec.yaml b/packages/google_sign_in/google_sign_in_ios/pubspec.yaml index 97e84fb3f124..eb9e3841055e 100644 --- a/packages/google_sign_in/google_sign_in_ios/pubspec.yaml +++ b/packages/google_sign_in/google_sign_in_ios/pubspec.yaml @@ -2,7 +2,7 @@ name: google_sign_in_ios description: iOS implementation of the google_sign_in plugin. repository: https://github.com/flutter/packages/tree/main/packages/google_sign_in/google_sign_in_ios issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+google_sign_in%22 -version: 6.3.5 +version: 6.3.6 environment: sdk: ^3.11.0 diff --git a/packages/google_sign_in/google_sign_in_ios/test/google_sign_in_ios_test.dart b/packages/google_sign_in/google_sign_in_ios/test/google_sign_in_ios_test.dart index 459d117d045e..0b81f97a0200 100644 --- a/packages/google_sign_in/google_sign_in_ios/test/google_sign_in_ios_test.dart +++ b/packages/google_sign_in/google_sign_in_ios/test/google_sign_in_ios_test.dart @@ -18,7 +18,7 @@ const GoogleSignInUserData _testUser = GoogleSignInUserData( displayName: 'John Doe', ); -@GenerateMocks([GoogleSignInApi]) +@GenerateNiceMocks(>[MockSpec()]) void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -28,6 +28,7 @@ void main() { setUp(() { mockApi = MockGoogleSignInApi(); googleSignIn = GoogleSignInIOS(api: mockApi); + provideDummy(SignInFailure(type: GoogleSignInErrorCode.unknown)); }); test('registered instance', () { @@ -71,18 +72,16 @@ void main() { test('passes success data to caller', () async { const idToken = 'idToken'; when(mockApi.restorePreviousSignIn()).thenAnswer( - (_) async => SignInResult( - success: SignInSuccess( - user: UserData( - displayName: _testUser.displayName, - email: _testUser.email, - userId: _testUser.id, - photoUrl: _testUser.photoUrl, - idToken: idToken, - ), - accessToken: '', - grantedScopes: [], + (_) async => SignInSuccess( + user: UserData( + displayName: _testUser.displayName, + email: _testUser.email, + userId: _testUser.id, + photoUrl: _testUser.photoUrl, + idToken: idToken, ), + accessToken: '', + grantedScopes: [], ), ); @@ -95,10 +94,9 @@ void main() { }); test('returns null for missing auth', () async { - when(mockApi.restorePreviousSignIn()).thenAnswer( - (_) async => - SignInResult(error: SignInFailure(type: GoogleSignInErrorCode.noAuthInKeychain)), - ); + when( + mockApi.restorePreviousSignIn(), + ).thenAnswer((_) async => SignInFailure(type: GoogleSignInErrorCode.noAuthInKeychain)); final AuthenticationResults? result = await googleSignIn.attemptLightweightAuthentication( const AttemptLightweightAuthenticationParameters(), @@ -108,9 +106,9 @@ void main() { }); test('throws for other errors', () async { - when(mockApi.restorePreviousSignIn()).thenAnswer( - (_) async => SignInResult(error: SignInFailure(type: GoogleSignInErrorCode.keychainError)), - ); + when( + mockApi.restorePreviousSignIn(), + ).thenAnswer((_) async => SignInFailure(type: GoogleSignInErrorCode.keychainError)); expect( googleSignIn.attemptLightweightAuthentication( @@ -131,18 +129,16 @@ void main() { test('passes nonce if provided', () async { const nonce = 'nonce'; when(mockApi.signIn(any, nonce)).thenAnswer( - (_) async => SignInResult( - success: SignInSuccess( - user: UserData( - displayName: _testUser.displayName, - email: _testUser.email, - userId: _testUser.id, - photoUrl: _testUser.photoUrl, - idToken: '', - ), - accessToken: '', - grantedScopes: [], + (_) async => SignInSuccess( + user: UserData( + displayName: _testUser.displayName, + email: _testUser.email, + userId: _testUser.id, + photoUrl: _testUser.photoUrl, + idToken: '', ), + accessToken: '', + grantedScopes: [], ), ); @@ -155,18 +151,16 @@ void main() { test('passes success data to caller', () async { const idToken = 'idToken'; when(mockApi.signIn(any, null)).thenAnswer( - (_) async => SignInResult( - success: SignInSuccess( - user: UserData( - displayName: _testUser.displayName, - email: _testUser.email, - userId: _testUser.id, - photoUrl: _testUser.photoUrl, - idToken: idToken, - ), - accessToken: '', - grantedScopes: [], + (_) async => SignInSuccess( + user: UserData( + displayName: _testUser.displayName, + email: _testUser.email, + userId: _testUser.id, + photoUrl: _testUser.photoUrl, + idToken: idToken, ), + accessToken: '', + grantedScopes: [], ), ); @@ -179,10 +173,9 @@ void main() { }); test('throws unknown for missing auth', () async { - when(mockApi.signIn(any, null)).thenAnswer( - (_) async => - SignInResult(error: SignInFailure(type: GoogleSignInErrorCode.noAuthInKeychain)), - ); + when( + mockApi.signIn(any, null), + ).thenAnswer((_) async => SignInFailure(type: GoogleSignInErrorCode.noAuthInKeychain)); expect( googleSignIn.authenticate(const AuthenticateParameters()), @@ -203,9 +196,9 @@ void main() { }); test('throws provider configuration error for keychain error', () async { - when(mockApi.signIn(any, null)).thenAnswer( - (_) async => SignInResult(error: SignInFailure(type: GoogleSignInErrorCode.keychainError)), - ); + when( + mockApi.signIn(any, null), + ).thenAnswer((_) async => SignInFailure(type: GoogleSignInErrorCode.keychainError)); expect( googleSignIn.authenticate(const AuthenticateParameters()), @@ -220,9 +213,9 @@ void main() { }); test('throws provider configuration error for EEM error', () async { - when(mockApi.signIn(any, null)).thenAnswer( - (_) async => SignInResult(error: SignInFailure(type: GoogleSignInErrorCode.eemError)), - ); + when( + mockApi.signIn(any, null), + ).thenAnswer((_) async => SignInFailure(type: GoogleSignInErrorCode.eemError)); expect( googleSignIn.authenticate(const AuthenticateParameters()), @@ -237,9 +230,9 @@ void main() { }); test('throws canceled from SDK', () async { - when(mockApi.signIn(any, null)).thenAnswer( - (_) async => SignInResult(error: SignInFailure(type: GoogleSignInErrorCode.canceled)), - ); + when( + mockApi.signIn(any, null), + ).thenAnswer((_) async => SignInFailure(type: GoogleSignInErrorCode.canceled)); expect( googleSignIn.authenticate(const AuthenticateParameters()), @@ -254,9 +247,9 @@ void main() { }); test('throws user mismatch from SDK', () async { - when(mockApi.signIn(any, null)).thenAnswer( - (_) async => SignInResult(error: SignInFailure(type: GoogleSignInErrorCode.userMismatch)), - ); + when( + mockApi.signIn(any, null), + ).thenAnswer((_) async => SignInFailure(type: GoogleSignInErrorCode.userMismatch)); expect( googleSignIn.authenticate(const AuthenticateParameters()), @@ -271,9 +264,9 @@ void main() { }); test('throws unknown from SDK', () async { - when(mockApi.signIn(any, null)).thenAnswer( - (_) async => SignInResult(error: SignInFailure(type: GoogleSignInErrorCode.unknown)), - ); + when( + mockApi.signIn(any, null), + ).thenAnswer((_) async => SignInFailure(type: GoogleSignInErrorCode.unknown)); expect( googleSignIn.authenticate(const AuthenticateParameters()), @@ -301,18 +294,16 @@ void main() { test('passes expected values to addScopes if interaction is allowed', () async { const scopes = ['a', 'b']; when(mockApi.addScopes(any, _testUser.id)).thenAnswer( - (_) async => SignInResult( - success: SignInSuccess( - user: UserData( - displayName: _testUser.displayName, - email: _testUser.email, - userId: _testUser.id, - photoUrl: _testUser.photoUrl, - idToken: '', - ), - accessToken: '', - grantedScopes: scopes, + (_) async => SignInSuccess( + user: UserData( + displayName: _testUser.displayName, + email: _testUser.email, + userId: _testUser.id, + photoUrl: _testUser.photoUrl, + idToken: '', ), + accessToken: '', + grantedScopes: scopes, ), ); @@ -336,18 +327,16 @@ void main() { 'interaction is not allowed', () async { const scopes = ['a', 'b']; when(mockApi.getRefreshedAuthorizationTokens(_testUser.id)).thenAnswer( - (_) async => SignInResult( - success: SignInSuccess( - user: UserData( - displayName: _testUser.displayName, - email: _testUser.email, - userId: _testUser.id, - photoUrl: _testUser.photoUrl, - idToken: '', - ), - accessToken: '', - grantedScopes: scopes, + (_) async => SignInSuccess( + user: UserData( + displayName: _testUser.displayName, + email: _testUser.email, + userId: _testUser.id, + photoUrl: _testUser.photoUrl, + idToken: '', ), + accessToken: '', + grantedScopes: scopes, ), ); @@ -367,18 +356,16 @@ void main() { test('attempts to restore previous sign in if no user is provided', () async { const scopes = ['a', 'b']; - final signInResult = SignInResult( - success: SignInSuccess( - user: UserData( - displayName: _testUser.displayName, - email: _testUser.email, - userId: _testUser.id, - photoUrl: _testUser.photoUrl, - idToken: '', - ), - accessToken: '', - grantedScopes: [], + final signInResult = SignInSuccess( + user: UserData( + displayName: _testUser.displayName, + email: _testUser.email, + userId: _testUser.id, + photoUrl: _testUser.photoUrl, + idToken: '', ), + accessToken: '', + grantedScopes: [], ); when(mockApi.restorePreviousSignIn()).thenAnswer((_) async => signInResult); when( @@ -404,10 +391,9 @@ void main() { }); test('returns null if unauthenticated and interaction is not allowed', () async { - when(mockApi.restorePreviousSignIn()).thenAnswer( - (_) async => - SignInResult(error: SignInFailure(type: GoogleSignInErrorCode.noAuthInKeychain)), - ); + when( + mockApi.restorePreviousSignIn(), + ).thenAnswer((_) async => SignInFailure(type: GoogleSignInErrorCode.noAuthInKeychain)); final ClientAuthorizationTokenData? result = await googleSignIn .clientAuthorizationTokensForScopes( @@ -432,23 +418,20 @@ void main() { test('attempts to authenticate if no user is provided or already signed in ' 'and interaction is allowed', () async { const scopes = ['a', 'b']; - when(mockApi.restorePreviousSignIn()).thenAnswer( - (_) async => - SignInResult(error: SignInFailure(type: GoogleSignInErrorCode.noAuthInKeychain)), - ); + when( + mockApi.restorePreviousSignIn(), + ).thenAnswer((_) async => SignInFailure(type: GoogleSignInErrorCode.noAuthInKeychain)); when(mockApi.signIn(scopes, null)).thenAnswer( - (_) async => SignInResult( - success: SignInSuccess( - user: UserData( - displayName: _testUser.displayName, - email: _testUser.email, - userId: _testUser.id, - photoUrl: _testUser.photoUrl, - idToken: '', - ), - accessToken: '', - grantedScopes: [], + (_) async => SignInSuccess( + user: UserData( + displayName: _testUser.displayName, + email: _testUser.email, + userId: _testUser.id, + photoUrl: _testUser.photoUrl, + idToken: '', ), + accessToken: '', + grantedScopes: [], ), ); @@ -474,18 +457,16 @@ void main() { const scopes = ['a', 'b']; const accessToken = 'token'; when(mockApi.getRefreshedAuthorizationTokens(_testUser.id)).thenAnswer( - (_) async => SignInResult( - success: SignInSuccess( - user: UserData( - displayName: _testUser.displayName, - email: _testUser.email, - userId: _testUser.id, - photoUrl: _testUser.photoUrl, - idToken: 'idToken', - ), - accessToken: accessToken, - grantedScopes: scopes, + (_) async => SignInSuccess( + user: UserData( + displayName: _testUser.displayName, + email: _testUser.email, + userId: _testUser.id, + photoUrl: _testUser.photoUrl, + idToken: 'idToken', ), + accessToken: accessToken, + grantedScopes: scopes, ), ); @@ -508,18 +489,16 @@ void main() { const scopes = ['a', 'b']; const accessToken = 'token'; when(mockApi.addScopes(scopes, _testUser.id)).thenAnswer( - (_) async => SignInResult( - success: SignInSuccess( - user: UserData( - displayName: _testUser.displayName, - email: _testUser.email, - userId: _testUser.id, - photoUrl: _testUser.photoUrl, - idToken: 'idToken', - ), - accessToken: accessToken, - grantedScopes: scopes, + (_) async => SignInSuccess( + user: UserData( + displayName: _testUser.displayName, + email: _testUser.email, + userId: _testUser.id, + photoUrl: _testUser.photoUrl, + idToken: 'idToken', ), + accessToken: accessToken, + grantedScopes: scopes, ), ); @@ -542,23 +521,20 @@ void main() { 'requested scopes are already granted', () async { const scopes = ['a', 'b']; const accessToken = 'token'; - when(mockApi.addScopes(scopes, _testUser.id)).thenAnswer( - (_) async => - SignInResult(error: SignInFailure(type: GoogleSignInErrorCode.scopesAlreadyGranted)), - ); + when( + mockApi.addScopes(scopes, _testUser.id), + ).thenAnswer((_) async => SignInFailure(type: GoogleSignInErrorCode.scopesAlreadyGranted)); when(mockApi.getRefreshedAuthorizationTokens(_testUser.id)).thenAnswer( - (_) async => SignInResult( - success: SignInSuccess( - user: UserData( - displayName: _testUser.displayName, - email: _testUser.email, - userId: _testUser.id, - photoUrl: _testUser.photoUrl, - idToken: 'idToken', - ), - accessToken: accessToken, - grantedScopes: scopes, + (_) async => SignInSuccess( + user: UserData( + displayName: _testUser.displayName, + email: _testUser.email, + userId: _testUser.id, + photoUrl: _testUser.photoUrl, + idToken: 'idToken', ), + accessToken: accessToken, + grantedScopes: scopes, ), ); @@ -585,18 +561,16 @@ void main() { const grantedScopes = ['a']; const accessToken = 'token'; when(mockApi.getRefreshedAuthorizationTokens(_testUser.id)).thenAnswer( - (_) async => SignInResult( - success: SignInSuccess( - user: UserData( - displayName: _testUser.displayName, - email: _testUser.email, - userId: _testUser.id, - photoUrl: _testUser.photoUrl, - idToken: 'idToken', - ), - accessToken: accessToken, - grantedScopes: grantedScopes, + (_) async => SignInSuccess( + user: UserData( + displayName: _testUser.displayName, + email: _testUser.email, + userId: _testUser.id, + photoUrl: _testUser.photoUrl, + idToken: 'idToken', ), + accessToken: accessToken, + grantedScopes: grantedScopes, ), ); @@ -616,10 +590,9 @@ void main() { }); test('returns null when unauthorized', () async { - when(mockApi.restorePreviousSignIn()).thenAnswer( - (_) async => - SignInResult(error: SignInFailure(type: GoogleSignInErrorCode.noAuthInKeychain)), - ); + when( + mockApi.restorePreviousSignIn(), + ).thenAnswer((_) async => SignInFailure(type: GoogleSignInErrorCode.noAuthInKeychain)); expect( await googleSignIn.clientAuthorizationTokensForScopes( @@ -630,9 +603,9 @@ void main() { }); test('thows canceled from SDK', () async { - when(mockApi.addScopes(any, any)).thenAnswer( - (_) async => SignInResult(error: SignInFailure(type: GoogleSignInErrorCode.canceled)), - ); + when( + mockApi.addScopes(any, any), + ).thenAnswer((_) async => SignInFailure(type: GoogleSignInErrorCode.canceled)); expect( googleSignIn.clientAuthorizationTokensForScopes( @@ -656,9 +629,9 @@ void main() { }); test('throws unknown from SDK', () async { - when(mockApi.addScopes(any, any)).thenAnswer( - (_) async => SignInResult(error: SignInFailure(type: GoogleSignInErrorCode.unknown)), - ); + when( + mockApi.addScopes(any, any), + ).thenAnswer((_) async => SignInFailure(type: GoogleSignInErrorCode.unknown)); expect( googleSignIn.clientAuthorizationTokensForScopes( @@ -682,9 +655,9 @@ void main() { }); test('throws user mismatch from SDK', () async { - when(mockApi.addScopes(any, any)).thenAnswer( - (_) async => SignInResult(error: SignInFailure(type: GoogleSignInErrorCode.userMismatch)), - ); + when( + mockApi.addScopes(any, any), + ).thenAnswer((_) async => SignInFailure(type: GoogleSignInErrorCode.userMismatch)); expect( googleSignIn.clientAuthorizationTokensForScopes( @@ -721,18 +694,16 @@ void main() { test('passes expected values to addScopes if interaction is allowed', () async { const scopes = ['a', 'b']; when(mockApi.addScopes(any, _testUser.id)).thenAnswer( - (_) async => SignInResult( - success: SignInSuccess( - user: UserData( - displayName: _testUser.displayName, - email: _testUser.email, - userId: _testUser.id, - photoUrl: _testUser.photoUrl, - idToken: '', - ), - accessToken: '', - grantedScopes: scopes, + (_) async => SignInSuccess( + user: UserData( + displayName: _testUser.displayName, + email: _testUser.email, + userId: _testUser.id, + photoUrl: _testUser.photoUrl, + idToken: '', ), + accessToken: '', + grantedScopes: scopes, ), ); @@ -756,18 +727,16 @@ void main() { 'interaction is not allowed', () async { const scopes = ['a', 'b']; when(mockApi.getRefreshedAuthorizationTokens(_testUser.id)).thenAnswer( - (_) async => SignInResult( - success: SignInSuccess( - user: UserData( - displayName: _testUser.displayName, - email: _testUser.email, - userId: _testUser.id, - photoUrl: _testUser.photoUrl, - idToken: '', - ), - accessToken: '', - grantedScopes: scopes, + (_) async => SignInSuccess( + user: UserData( + displayName: _testUser.displayName, + email: _testUser.email, + userId: _testUser.id, + photoUrl: _testUser.photoUrl, + idToken: '', ), + accessToken: '', + grantedScopes: scopes, ), ); @@ -787,18 +756,16 @@ void main() { test('attempts to restore previous sign in if no user is provided', () async { const scopes = ['a', 'b']; - final signInResult = SignInResult( - success: SignInSuccess( - user: UserData( - displayName: _testUser.displayName, - email: _testUser.email, - userId: _testUser.id, - photoUrl: _testUser.photoUrl, - idToken: '', - ), - accessToken: '', - grantedScopes: [], + final signInResult = SignInSuccess( + user: UserData( + displayName: _testUser.displayName, + email: _testUser.email, + userId: _testUser.id, + photoUrl: _testUser.photoUrl, + idToken: '', ), + accessToken: '', + grantedScopes: [], ); when(mockApi.restorePreviousSignIn()).thenAnswer((_) async => signInResult); when( @@ -824,10 +791,9 @@ void main() { }); test('returns null if unauthenticated and interaction is not allowed', () async { - when(mockApi.restorePreviousSignIn()).thenAnswer( - (_) async => - SignInResult(error: SignInFailure(type: GoogleSignInErrorCode.noAuthInKeychain)), - ); + when( + mockApi.restorePreviousSignIn(), + ).thenAnswer((_) async => SignInFailure(type: GoogleSignInErrorCode.noAuthInKeychain)); final ServerAuthorizationTokenData? result = await googleSignIn .serverAuthorizationTokensForScopes( @@ -852,23 +818,20 @@ void main() { test('attempts to authenticate if no user is provided or already signed in ' 'and interaction is allowed', () async { const scopes = ['a', 'b']; - when(mockApi.restorePreviousSignIn()).thenAnswer( - (_) async => - SignInResult(error: SignInFailure(type: GoogleSignInErrorCode.noAuthInKeychain)), - ); + when( + mockApi.restorePreviousSignIn(), + ).thenAnswer((_) async => SignInFailure(type: GoogleSignInErrorCode.noAuthInKeychain)); when(mockApi.signIn(scopes, null)).thenAnswer( - (_) async => SignInResult( - success: SignInSuccess( - user: UserData( - displayName: _testUser.displayName, - email: _testUser.email, - userId: _testUser.id, - photoUrl: _testUser.photoUrl, - idToken: '', - ), - accessToken: '', - grantedScopes: [], + (_) async => SignInSuccess( + user: UserData( + displayName: _testUser.displayName, + email: _testUser.email, + userId: _testUser.id, + photoUrl: _testUser.photoUrl, + idToken: '', ), + accessToken: '', + grantedScopes: [], ), ); @@ -902,23 +865,19 @@ void main() { const accessToken = 'accessToken'; const serverAuthCode = 'authCode'; when(mockApi.signIn(scopes, null)).thenAnswer( - (_) async => SignInResult( - success: SignInSuccess( - user: userData, - accessToken: accessToken, - serverAuthCode: serverAuthCode, - grantedScopes: [], - ), + (_) async => SignInSuccess( + user: userData, + accessToken: accessToken, + serverAuthCode: serverAuthCode, + grantedScopes: [], ), ); when(mockApi.getRefreshedAuthorizationTokens(_testUser.id)).thenAnswer( - (_) async => SignInResult( - success: SignInSuccess( - user: userData, - accessToken: accessToken, - // serverAuthCode will always be null for getRefreshedAuthorizationTokens. - grantedScopes: scopes, - ), + (_) async => SignInSuccess( + user: userData, + accessToken: accessToken, + // serverAuthCode will always be null for getRefreshedAuthorizationTokens. + grantedScopes: scopes, ), ); @@ -957,23 +916,19 @@ void main() { idToken: '', ); when(mockApi.signIn(scopes, null)).thenAnswer( - (_) async => SignInResult( - success: SignInSuccess( - user: previousUser, - accessToken: accessToken, - serverAuthCode: serverAuthCode, - grantedScopes: [], - ), + (_) async => SignInSuccess( + user: previousUser, + accessToken: accessToken, + serverAuthCode: serverAuthCode, + grantedScopes: [], ), ); when(mockApi.getRefreshedAuthorizationTokens(newUser.userId)).thenAnswer( - (_) async => SignInResult( - success: SignInSuccess( - user: newUser, - accessToken: accessToken, - // serverAuthCode will always be null for getRefreshedAuthorizationTokens. - grantedScopes: scopes, - ), + (_) async => SignInSuccess( + user: newUser, + accessToken: accessToken, + // serverAuthCode will always be null for getRefreshedAuthorizationTokens. + grantedScopes: scopes, ), ); @@ -1005,23 +960,19 @@ void main() { idToken: '', ); when(mockApi.signIn(scopes, null)).thenAnswer( - (_) async => SignInResult( - success: SignInSuccess( - user: userData, - accessToken: accessToken, - serverAuthCode: serverAuthCode, - grantedScopes: [], - ), + (_) async => SignInSuccess( + user: userData, + accessToken: accessToken, + serverAuthCode: serverAuthCode, + grantedScopes: [], ), ); when(mockApi.getRefreshedAuthorizationTokens(userData.userId)).thenAnswer( - (_) async => SignInResult( - success: SignInSuccess( - user: userData, - accessToken: accessToken, - // serverAuthCode will always be null for getRefreshedAuthorizationTokens. - grantedScopes: scopes, - ), + (_) async => SignInSuccess( + user: userData, + accessToken: accessToken, + // serverAuthCode will always be null for getRefreshedAuthorizationTokens. + grantedScopes: scopes, ), ); @@ -1054,23 +1005,19 @@ void main() { idToken: '', ); when(mockApi.signIn(scopes, null)).thenAnswer( - (_) async => SignInResult( - success: SignInSuccess( - user: userData, - accessToken: accessToken, - serverAuthCode: serverAuthCode, - grantedScopes: [], - ), + (_) async => SignInSuccess( + user: userData, + accessToken: accessToken, + serverAuthCode: serverAuthCode, + grantedScopes: [], ), ); when(mockApi.getRefreshedAuthorizationTokens(userData.userId)).thenAnswer( - (_) async => SignInResult( - success: SignInSuccess( - user: userData, - accessToken: accessToken, - // serverAuthCode will always be null for getRefreshedAuthorizationTokens. - grantedScopes: scopes, - ), + (_) async => SignInSuccess( + user: userData, + accessToken: accessToken, + // serverAuthCode will always be null for getRefreshedAuthorizationTokens. + grantedScopes: scopes, ), ); @@ -1095,19 +1042,17 @@ void main() { const scopes = ['a', 'b']; const serverAuthCode = 'authCode'; when(mockApi.addScopes(scopes, _testUser.id)).thenAnswer( - (_) async => SignInResult( - success: SignInSuccess( - user: UserData( - displayName: _testUser.displayName, - email: _testUser.email, - userId: _testUser.id, - photoUrl: _testUser.photoUrl, - idToken: 'idToken', - ), - accessToken: 'token', - serverAuthCode: serverAuthCode, - grantedScopes: scopes, + (_) async => SignInSuccess( + user: UserData( + displayName: _testUser.displayName, + email: _testUser.email, + userId: _testUser.id, + photoUrl: _testUser.photoUrl, + idToken: 'idToken', ), + accessToken: 'token', + serverAuthCode: serverAuthCode, + grantedScopes: scopes, ), ); @@ -1137,23 +1082,19 @@ void main() { ); const serverAuthCode = 'authCode'; when(mockApi.signIn([], null)).thenAnswer( - (_) async => SignInResult( - success: SignInSuccess( - user: userData, - accessToken: 'token', - serverAuthCode: 'no-scope-auth-code', - grantedScopes: [], - ), + (_) async => SignInSuccess( + user: userData, + accessToken: 'token', + serverAuthCode: 'no-scope-auth-code', + grantedScopes: [], ), ); when(mockApi.addScopes(scopes, _testUser.id)).thenAnswer( - (_) async => SignInResult( - success: SignInSuccess( - user: userData, - accessToken: 'token', - serverAuthCode: serverAuthCode, - grantedScopes: scopes, - ), + (_) async => SignInSuccess( + user: userData, + accessToken: 'token', + serverAuthCode: serverAuthCode, + grantedScopes: scopes, ), ); @@ -1185,27 +1126,22 @@ void main() { idToken: 'idToken', ); when(mockApi.signIn(scopes, null)).thenAnswer( - (_) async => SignInResult( - success: SignInSuccess( - user: userData, - accessToken: 'token', - serverAuthCode: serverAuthCode, - grantedScopes: scopes, - ), + (_) async => SignInSuccess( + user: userData, + accessToken: 'token', + serverAuthCode: serverAuthCode, + grantedScopes: scopes, ), ); - when(mockApi.addScopes(scopes, _testUser.id)).thenAnswer( - (_) async => - SignInResult(error: SignInFailure(type: GoogleSignInErrorCode.scopesAlreadyGranted)), - ); + when( + mockApi.addScopes(scopes, _testUser.id), + ).thenAnswer((_) async => SignInFailure(type: GoogleSignInErrorCode.scopesAlreadyGranted)); when(mockApi.getRefreshedAuthorizationTokens(_testUser.id)).thenAnswer( - (_) async => SignInResult( - success: SignInSuccess( - user: userData, - accessToken: 'token', - // serverAuthCode will always be null for getRefreshedAuthorizationTokens. - grantedScopes: scopes, - ), + (_) async => SignInSuccess( + user: userData, + accessToken: 'token', + // serverAuthCode will always be null for getRefreshedAuthorizationTokens. + grantedScopes: scopes, ), ); @@ -1240,23 +1176,19 @@ void main() { idToken: 'idToken', ); when(mockApi.signIn([], null)).thenAnswer( - (_) async => SignInResult( - success: SignInSuccess( - user: userData, - accessToken: 'token', - serverAuthCode: 'no-scope-auth-code', - grantedScopes: [], - ), + (_) async => SignInSuccess( + user: userData, + accessToken: 'token', + serverAuthCode: 'no-scope-auth-code', + grantedScopes: [], ), ); when(mockApi.getRefreshedAuthorizationTokens(_testUser.id)).thenAnswer( - (_) async => SignInResult( - success: SignInSuccess( - user: userData, - accessToken: accessToken, - serverAuthCode: 'wrong-scope-auth-code', - grantedScopes: grantedScopes, - ), + (_) async => SignInSuccess( + user: userData, + accessToken: accessToken, + serverAuthCode: 'wrong-scope-auth-code', + grantedScopes: grantedScopes, ), ); @@ -1277,10 +1209,9 @@ void main() { }); test('returns null when unauthorized', () async { - when(mockApi.restorePreviousSignIn()).thenAnswer( - (_) async => - SignInResult(error: SignInFailure(type: GoogleSignInErrorCode.noAuthInKeychain)), - ); + when( + mockApi.restorePreviousSignIn(), + ).thenAnswer((_) async => SignInFailure(type: GoogleSignInErrorCode.noAuthInKeychain)); expect( await googleSignIn.serverAuthorizationTokensForScopes( @@ -1291,9 +1222,9 @@ void main() { }); test('thows canceled from SDK', () async { - when(mockApi.addScopes(any, any)).thenAnswer( - (_) async => SignInResult(error: SignInFailure(type: GoogleSignInErrorCode.canceled)), - ); + when( + mockApi.addScopes(any, any), + ).thenAnswer((_) async => SignInFailure(type: GoogleSignInErrorCode.canceled)); expect( googleSignIn.serverAuthorizationTokensForScopes( @@ -1317,9 +1248,9 @@ void main() { }); test('throws unknown from SDK', () async { - when(mockApi.addScopes(any, any)).thenAnswer( - (_) async => SignInResult(error: SignInFailure(type: GoogleSignInErrorCode.unknown)), - ); + when( + mockApi.addScopes(any, any), + ).thenAnswer((_) async => SignInFailure(type: GoogleSignInErrorCode.unknown)); expect( googleSignIn.serverAuthorizationTokensForScopes( @@ -1343,9 +1274,9 @@ void main() { }); test('throws user mismatch from SDK', () async { - when(mockApi.addScopes(any, any)).thenAnswer( - (_) async => SignInResult(error: SignInFailure(type: GoogleSignInErrorCode.userMismatch)), - ); + when( + mockApi.addScopes(any, any), + ).thenAnswer((_) async => SignInFailure(type: GoogleSignInErrorCode.userMismatch)); expect( googleSignIn.serverAuthorizationTokensForScopes( diff --git a/packages/google_sign_in/google_sign_in_ios/test/google_sign_in_ios_test.mocks.dart b/packages/google_sign_in/google_sign_in_ios/test/google_sign_in_ios_test.mocks.dart index 31a501c14361..ee104e7e3531 100644 --- a/packages/google_sign_in/google_sign_in_ios/test/google_sign_in_ios_test.mocks.dart +++ b/packages/google_sign_in/google_sign_in_ios/test/google_sign_in_ios_test.mocks.dart @@ -22,19 +22,12 @@ import 'package:mockito/src/dummies.dart' as _i3; // ignore_for_file: unnecessary_parenthesis // ignore_for_file: camel_case_types // ignore_for_file: subtype_of_sealed_class - -class _FakeSignInResult_0 extends _i1.SmartFake implements _i2.SignInResult { - _FakeSignInResult_0(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); -} +// ignore_for_file: invalid_use_of_internal_member /// A class which mocks [GoogleSignInApi]. /// /// See the documentation for Mockito's code generation for more information. class MockGoogleSignInApi extends _i1.Mock implements _i2.GoogleSignInApi { - MockGoogleSignInApi() { - _i1.throwOnMissingStub(this); - } - @override String get pigeonVar_messageChannelSuffix => (super.noSuchMethod( @@ -43,6 +36,10 @@ class MockGoogleSignInApi extends _i1.Mock implements _i2.GoogleSignInApi { this, Invocation.getter(#pigeonVar_messageChannelSuffix), ), + returnValueForMissingStub: _i3.dummyValue( + this, + Invocation.getter(#pigeonVar_messageChannelSuffix), + ), ) as String); @@ -60,7 +57,10 @@ class MockGoogleSignInApi extends _i1.Mock implements _i2.GoogleSignInApi { (super.noSuchMethod( Invocation.method(#restorePreviousSignIn, []), returnValue: _i4.Future<_i2.SignInResult>.value( - _FakeSignInResult_0(this, Invocation.method(#restorePreviousSignIn, [])), + _i3.dummyValue<_i2.SignInResult>(this, Invocation.method(#restorePreviousSignIn, [])), + ), + returnValueForMissingStub: _i4.Future<_i2.SignInResult>.value( + _i3.dummyValue<_i2.SignInResult>(this, Invocation.method(#restorePreviousSignIn, [])), ), ) as _i4.Future<_i2.SignInResult>); @@ -70,7 +70,16 @@ class MockGoogleSignInApi extends _i1.Mock implements _i2.GoogleSignInApi { (super.noSuchMethod( Invocation.method(#signIn, [scopeHint, nonce]), returnValue: _i4.Future<_i2.SignInResult>.value( - _FakeSignInResult_0(this, Invocation.method(#signIn, [scopeHint, nonce])), + _i3.dummyValue<_i2.SignInResult>( + this, + Invocation.method(#signIn, [scopeHint, nonce]), + ), + ), + returnValueForMissingStub: _i4.Future<_i2.SignInResult>.value( + _i3.dummyValue<_i2.SignInResult>( + this, + Invocation.method(#signIn, [scopeHint, nonce]), + ), ), ) as _i4.Future<_i2.SignInResult>); @@ -80,7 +89,13 @@ class MockGoogleSignInApi extends _i1.Mock implements _i2.GoogleSignInApi { (super.noSuchMethod( Invocation.method(#getRefreshedAuthorizationTokens, [userId]), returnValue: _i4.Future<_i2.SignInResult>.value( - _FakeSignInResult_0( + _i3.dummyValue<_i2.SignInResult>( + this, + Invocation.method(#getRefreshedAuthorizationTokens, [userId]), + ), + ), + returnValueForMissingStub: _i4.Future<_i2.SignInResult>.value( + _i3.dummyValue<_i2.SignInResult>( this, Invocation.method(#getRefreshedAuthorizationTokens, [userId]), ), @@ -93,7 +108,16 @@ class MockGoogleSignInApi extends _i1.Mock implements _i2.GoogleSignInApi { (super.noSuchMethod( Invocation.method(#addScopes, [scopes, userId]), returnValue: _i4.Future<_i2.SignInResult>.value( - _FakeSignInResult_0(this, Invocation.method(#addScopes, [scopes, userId])), + _i3.dummyValue<_i2.SignInResult>( + this, + Invocation.method(#addScopes, [scopes, userId]), + ), + ), + returnValueForMissingStub: _i4.Future<_i2.SignInResult>.value( + _i3.dummyValue<_i2.SignInResult>( + this, + Invocation.method(#addScopes, [scopes, userId]), + ), ), ) as _i4.Future<_i2.SignInResult>);