[google_sign_in] Upgrade to GoogleSignIn 6.2, support arm64 simulators (#5708)
diff --git a/packages/google_sign_in/google_sign_in/CHANGELOG.md b/packages/google_sign_in/google_sign_in/CHANGELOG.md
index 9edadf7..86a3b56 100644
--- a/packages/google_sign_in/google_sign_in/CHANGELOG.md
+++ b/packages/google_sign_in/google_sign_in/CHANGELOG.md
@@ -2,6 +2,7 @@
* Updates tests to use a mock platform instead of relying on default
method channel implementation internals.
+* Removes example workaround to build for arm64 iOS simulators.
## 5.3.1
diff --git a/packages/google_sign_in/google_sign_in/example/ios/Podfile b/packages/google_sign_in/google_sign_in/example/ios/Podfile
index 56085c3..f7d6a5e 100644
--- a/packages/google_sign_in/google_sign_in/example/ios/Podfile
+++ b/packages/google_sign_in/google_sign_in/example/ios/Podfile
@@ -34,9 +34,5 @@
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
- target.build_configurations.each do |build_configuration|
- # GoogleSignIn does not support arm64 simulators.
- build_configuration.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64 i386'
- end
end
end
diff --git a/packages/google_sign_in/google_sign_in/example/ios/Runner.xcodeproj/project.pbxproj b/packages/google_sign_in/google_sign_in/example/ios/Runner.xcodeproj/project.pbxproj
index 8909bb9..6c698e1 100644
--- a/packages/google_sign_in/google_sign_in/example/ios/Runner.xcodeproj/project.pbxproj
+++ b/packages/google_sign_in/google_sign_in/example/ios/Runner.xcodeproj/project.pbxproj
@@ -426,7 +426,6 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ENABLE_BITCODE = NO;
- "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "i386 arm64";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
@@ -448,7 +447,6 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ENABLE_BITCODE = NO;
- "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "i386 arm64";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
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 90069d0..e5de49d 100644
--- a/packages/google_sign_in/google_sign_in_ios/CHANGELOG.md
+++ b/packages/google_sign_in/google_sign_in_ios/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 5.3.0
+
+* Supports arm64 iOS simulators by increasing GoogleSignIn dependency to version 6.2.
+
## 5.2.7
* Fixes library_private_types_in_public_api, sort_child_properties_last and use_key_in_widget_constructors
diff --git a/packages/google_sign_in/google_sign_in_ios/example/ios/Podfile b/packages/google_sign_in/google_sign_in_ios/example/ios/Podfile
index b20e1ad..6c315d2 100644
--- a/packages/google_sign_in/google_sign_in_ios/example/ios/Podfile
+++ b/packages/google_sign_in/google_sign_in_ios/example/ios/Podfile
@@ -42,9 +42,5 @@
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
- target.build_configurations.each do |build_configuration|
- # GoogleSignIn does not support arm64 simulators.
- build_configuration.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64 i386'
- end
end
end
diff --git a/packages/google_sign_in/google_sign_in_ios/example/ios/Runner.xcodeproj/project.pbxproj b/packages/google_sign_in/google_sign_in_ios/example/ios/Runner.xcodeproj/project.pbxproj
index f2bf4eb..a7f2019 100644
--- a/packages/google_sign_in/google_sign_in_ios/example/ios/Runner.xcodeproj/project.pbxproj
+++ b/packages/google_sign_in/google_sign_in_ios/example/ios/Runner.xcodeproj/project.pbxproj
@@ -384,7 +384,7 @@
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh",
- "${PODS_ROOT}/GoogleSignIn/Resources/GoogleSignIn.bundle",
+ "${PODS_CONFIGURATION_BUILD_DIR}/GoogleSignIn/GoogleSignIn.bundle",
);
name = "[CP] Copy Pods Resources";
outputPaths = (
@@ -603,7 +603,6 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ENABLE_BITCODE = NO;
- "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "i386 arm64";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
@@ -625,7 +624,6 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ENABLE_BITCODE = NO;
- "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "i386 arm64";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
@@ -647,7 +645,6 @@
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
- "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "i386 arm64";
INFOPLIST_FILE = RunnerTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.plugins.RunnerTests;
@@ -662,7 +659,6 @@
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
- "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "i386 arm64";
INFOPLIST_FILE = RunnerTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.plugins.RunnerTests;
diff --git a/packages/google_sign_in/google_sign_in_ios/example/ios/RunnerTests/GoogleSignInTests.m b/packages/google_sign_in/google_sign_in_ios/example/ios/RunnerTests/GoogleSignInTests.m
index 3bc08d1..7efd490 100644
--- a/packages/google_sign_in/google_sign_in_ios/example/ios/RunnerTests/GoogleSignInTests.m
+++ b/packages/google_sign_in/google_sign_in_ios/example/ios/RunnerTests/GoogleSignInTests.m
@@ -64,66 +64,103 @@
}
- (void)testDisconnect {
+ [[self.mockSignIn stub] disconnectWithCallback:[OCMArg invokeBlockWithArgs:[NSNull null], nil]];
FlutterMethodCall *methodCall = [FlutterMethodCall methodCallWithMethodName:@"disconnect"
arguments:nil];
+ XCTestExpectation *expectation = [self expectationWithDescription:@"expect result returns true"];
[self.plugin handleMethodCall:methodCall
- result:^(id result){
+ result:^(NSDictionary *result) {
+ XCTAssertEqualObjects(result, @{});
+ [expectation fulfill];
}];
- OCMVerify([self.mockSignIn disconnect]);
+ [self waitForExpectationsWithTimeout:5.0 handler:nil];
+}
+
+- (void)testDisconnectIgnoresError {
+ NSError *error = [NSError errorWithDomain:kGIDSignInErrorDomain
+ code:kGIDSignInErrorCodeHasNoAuthInKeychain
+ userInfo:nil];
+ [[self.mockSignIn stub] disconnectWithCallback:[OCMArg invokeBlockWithArgs:error, nil]];
+ FlutterMethodCall *methodCall = [FlutterMethodCall methodCallWithMethodName:@"disconnect"
+ arguments:nil];
+
+ XCTestExpectation *expectation = [self expectationWithDescription:@"expect result returns true"];
+ [self.plugin handleMethodCall:methodCall
+ result:^(NSDictionary *result) {
+ XCTAssertEqualObjects(result, @{});
+ [expectation fulfill];
+ }];
+ [self waitForExpectationsWithTimeout:5.0 handler:nil];
}
#pragma mark - Init
- (void)testInitGoogleServiceInfoPlist {
- FlutterMethodCall *methodCall = [FlutterMethodCall
- methodCallWithMethodName:@"init"
- arguments:@{@"scopes" : @[ @"mockScope1" ], @"hostedDomain" : @"example.com"}];
+ FlutterMethodCall *initMethodCall =
+ [FlutterMethodCall methodCallWithMethodName:@"init"
+ arguments:@{@"hostedDomain" : @"example.com"}];
- XCTestExpectation *expectation = [self expectationWithDescription:@"expect result returns true"];
- [self.plugin handleMethodCall:methodCall
+ XCTestExpectation *initExpectation =
+ [self expectationWithDescription:@"expect result returns true"];
+ [self.plugin handleMethodCall:initMethodCall
result:^(id result) {
XCTAssertNil(result);
- [expectation fulfill];
+ [initExpectation fulfill];
}];
[self waitForExpectationsWithTimeout:5.0 handler:nil];
- id mockSignIn = self.mockSignIn;
- OCMVerify([mockSignIn setScopes:@[ @"mockScope1" ]]);
- OCMVerify([mockSignIn setHostedDomain:@"example.com"]);
-
- // Set in example app GoogleService-Info.plist.
- OCMVerify([mockSignIn
- setClientID:@"479882132969-9i9aqik3jfjd7qhci1nqf0bm2g71rm1u.apps.googleusercontent.com"]);
- OCMVerify([mockSignIn setServerClientID:@"YOUR_SERVER_CLIENT_ID"]);
+ // Initialization values used in the next sign in request.
+ FlutterMethodCall *signInMethodCall = [FlutterMethodCall methodCallWithMethodName:@"signIn"
+ arguments:nil];
+ [self.plugin handleMethodCall:signInMethodCall
+ result:^(id r){
+ }];
+ OCMVerify([self.mockSignIn
+ signInWithConfiguration:[OCMArg checkWithBlock:^BOOL(GIDConfiguration *configuration) {
+ // Set in example app GoogleService-Info.plist.
+ return
+ [configuration.hostedDomain isEqualToString:@"example.com"] &&
+ [configuration.clientID
+ isEqualToString:
+ @"479882132969-9i9aqik3jfjd7qhci1nqf0bm2g71rm1u.apps.googleusercontent.com"] &&
+ [configuration.serverClientID isEqualToString:@"YOUR_SERVER_CLIENT_ID"];
+ }]
+ presentingViewController:[OCMArg isKindOfClass:[FlutterViewController class]]
+ hint:nil
+ additionalScopes:OCMOCK_ANY
+ callback:OCMOCK_ANY]);
}
-- (void)testInitNullDomain {
- FlutterMethodCall *methodCall =
- [FlutterMethodCall methodCallWithMethodName:@"init"
- arguments:@{@"hostedDomain" : [NSNull null]}];
+- (void)testInitDynamicClientIdNullDomain {
+ FlutterMethodCall *initMethodCall = [FlutterMethodCall
+ methodCallWithMethodName:@"init"
+ arguments:@{@"hostedDomain" : [NSNull null], @"clientId" : @"mockClientId"}];
- XCTestExpectation *expectation = [self expectationWithDescription:@"expect result returns true"];
- [self.plugin handleMethodCall:methodCall
- result:^(id r) {
- [expectation fulfill];
+ XCTestExpectation *initExpectation =
+ [self expectationWithDescription:@"expect result returns true"];
+ [self.plugin handleMethodCall:initMethodCall
+ result:^(id result) {
+ XCTAssertNil(result);
+ [initExpectation fulfill];
}];
[self waitForExpectationsWithTimeout:5.0 handler:nil];
- OCMVerify([self.mockSignIn setHostedDomain:nil]);
-}
-- (void)testInitDynamicClientId {
- FlutterMethodCall *methodCall =
- [FlutterMethodCall methodCallWithMethodName:@"init"
- arguments:@{@"clientId" : @"mockClientId"}];
-
- XCTestExpectation *expectation = [self expectationWithDescription:@"expect result returns true"];
- [self.plugin handleMethodCall:methodCall
- result:^(id r) {
- [expectation fulfill];
+ // Initialization values used in the next sign in request.
+ FlutterMethodCall *signInMethodCall = [FlutterMethodCall methodCallWithMethodName:@"signIn"
+ arguments:nil];
+ [self.plugin handleMethodCall:signInMethodCall
+ result:^(id r){
}];
- [self waitForExpectationsWithTimeout:5.0 handler:nil];
- OCMVerify([self.mockSignIn setClientID:@"mockClientId"]);
+ OCMVerify([self.mockSignIn
+ signInWithConfiguration:[OCMArg checkWithBlock:^BOOL(GIDConfiguration *configuration) {
+ return configuration.hostedDomain == nil &&
+ [configuration.clientID isEqualToString:@"mockClientId"];
+ }]
+ presentingViewController:[OCMArg isKindOfClass:[FlutterViewController class]]
+ hint:nil
+ additionalScopes:OCMOCK_ANY
+ callback:OCMOCK_ANY]);
}
#pragma mark - Is signed in
@@ -161,59 +198,195 @@
#pragma mark - Sign in silently
- (void)testSignInSilently {
- OCMExpect([self.mockSignIn restorePreviousSignIn]);
+ id mockUser = OCMClassMock([GIDGoogleUser class]);
+ OCMStub([mockUser userID]).andReturn(@"mockID");
- FlutterMethodCall *methodCall = [FlutterMethodCall methodCallWithMethodName:@"signInSilently"
- arguments:nil];
+ [[self.mockSignIn stub]
+ restorePreviousSignInWithCallback:[OCMArg invokeBlockWithArgs:mockUser, [NSNull null], nil]];
- [self.plugin handleMethodCall:methodCall
- result:^(id result){
- }];
- OCMVerifyAll(self.mockSignIn);
-}
-
-- (void)testSignInSilentlyFailsConcurrently {
FlutterMethodCall *methodCall = [FlutterMethodCall methodCallWithMethodName:@"signInSilently"
arguments:nil];
XCTestExpectation *expectation = [self expectationWithDescription:@"expect result returns true"];
-
- OCMExpect([self.mockSignIn restorePreviousSignIn]).andDo(^(NSInvocation *invocation) {
- // Simulate calling the same method while the previous one is in flight.
- [self.plugin handleMethodCall:methodCall
- result:^(FlutterError *result) {
- XCTAssertEqualObjects(result.code, @"concurrent-requests");
- [expectation fulfill];
- }];
- });
-
[self.plugin handleMethodCall:methodCall
- result:^(id result){
+ result:^(NSDictionary<NSString *, NSString *> *result) {
+ XCTAssertEqualObjects(result[@"displayName"], [NSNull null]);
+ XCTAssertEqualObjects(result[@"email"], [NSNull null]);
+ XCTAssertEqualObjects(result[@"id"], @"mockID");
+ XCTAssertEqualObjects(result[@"photoUrl"], [NSNull null]);
+ XCTAssertEqualObjects(result[@"serverAuthCode"], [NSNull null]);
+ [expectation fulfill];
}];
+ [self waitForExpectationsWithTimeout:5.0 handler:nil];
+}
+- (void)testSignInSilentlyWithError {
+ NSError *error = [NSError errorWithDomain:kGIDSignInErrorDomain
+ code:kGIDSignInErrorCodeHasNoAuthInKeychain
+ userInfo:nil];
+
+ [[self.mockSignIn stub]
+ restorePreviousSignInWithCallback:[OCMArg invokeBlockWithArgs:[NSNull null], error, nil]];
+
+ FlutterMethodCall *methodCall = [FlutterMethodCall methodCallWithMethodName:@"signInSilently"
+ arguments:nil];
+
+ XCTestExpectation *expectation = [self expectationWithDescription:@"expect result returns true"];
+ [self.plugin handleMethodCall:methodCall
+ result:^(FlutterError *result) {
+ XCTAssertEqualObjects(result.code, @"sign_in_required");
+ [expectation fulfill];
+ }];
[self waitForExpectationsWithTimeout:5.0 handler:nil];
}
#pragma mark - Sign in
- (void)testSignIn {
+ id mockUser = OCMClassMock([GIDGoogleUser class]);
+ id mockUserProfile = OCMClassMock([GIDProfileData class]);
+ OCMStub([mockUserProfile name]).andReturn(@"mockDisplay");
+ OCMStub([mockUserProfile email]).andReturn(@"mock@example.com");
+ OCMStub([mockUserProfile hasImage]).andReturn(YES);
+ OCMStub([mockUserProfile imageURLWithDimension:1337])
+ .andReturn([NSURL URLWithString:@"https://example.com/profile.png"]);
+
+ OCMStub([mockUser profile]).andReturn(mockUserProfile);
+ OCMStub([mockUser userID]).andReturn(@"mockID");
+ OCMStub([mockUser serverAuthCode]).andReturn(@"mockAuthCode");
+
+ [[self.mockSignIn expect]
+ signInWithConfiguration:[OCMArg checkWithBlock:^BOOL(GIDConfiguration *configuration) {
+ return [configuration.clientID
+ isEqualToString:
+ @"479882132969-9i9aqik3jfjd7qhci1nqf0bm2g71rm1u.apps.googleusercontent.com"];
+ }]
+ presentingViewController:[OCMArg isKindOfClass:[FlutterViewController class]]
+ hint:nil
+ additionalScopes:@[]
+ callback:[OCMArg invokeBlockWithArgs:mockUser, [NSNull null], nil]];
+
FlutterMethodCall *methodCall = [FlutterMethodCall methodCallWithMethodName:@"signIn"
arguments:nil];
- [self.plugin handleMethodCall:methodCall
- result:^(NSNumber *result){
- }];
+ XCTestExpectation *expectation = [self expectationWithDescription:@"expect result returns true"];
+ [self.plugin
+ handleMethodCall:methodCall
+ result:^(NSDictionary<NSString *, NSString *> *result) {
+ XCTAssertEqualObjects(result[@"displayName"], @"mockDisplay");
+ XCTAssertEqualObjects(result[@"email"], @"mock@example.com");
+ XCTAssertEqualObjects(result[@"id"], @"mockID");
+ XCTAssertEqualObjects(result[@"photoUrl"], @"https://example.com/profile.png");
+ XCTAssertEqualObjects(result[@"serverAuthCode"], @"mockAuthCode");
+ [expectation fulfill];
+ }];
+ [self waitForExpectationsWithTimeout:5.0 handler:nil];
- id mockSignIn = self.mockSignIn;
- OCMVerify([mockSignIn
- setPresentingViewController:[OCMArg isKindOfClass:[FlutterViewController class]]]);
- OCMVerify([mockSignIn signIn]);
+ OCMVerifyAll(self.mockSignIn);
}
-- (void)testSignInExecption {
+- (void)testSignInWithInitializedScopes {
+ FlutterMethodCall *initMethodCall =
+ [FlutterMethodCall methodCallWithMethodName:@"init"
+ arguments:@{@"scopes" : @[ @"initial1", @"initial2" ]}];
+
+ XCTestExpectation *initExpectation =
+ [self expectationWithDescription:@"expect result returns true"];
+ [self.plugin handleMethodCall:initMethodCall
+ result:^(id result) {
+ XCTAssertNil(result);
+ [initExpectation fulfill];
+ }];
+ [self waitForExpectationsWithTimeout:5.0 handler:nil];
+
+ id mockUser = OCMClassMock([GIDGoogleUser class]);
+ OCMStub([mockUser userID]).andReturn(@"mockID");
+
+ [[self.mockSignIn expect]
+ signInWithConfiguration:OCMOCK_ANY
+ presentingViewController:OCMOCK_ANY
+ hint:nil
+ additionalScopes:[OCMArg checkWithBlock:^BOOL(NSArray<NSString *> *scopes) {
+ return [[NSSet setWithArray:scopes]
+ isEqualToSet:[NSSet setWithObjects:@"initial1", @"initial2", nil]];
+ }]
+ callback:[OCMArg invokeBlockWithArgs:mockUser, [NSNull null], nil]];
+
FlutterMethodCall *methodCall = [FlutterMethodCall methodCallWithMethodName:@"signIn"
arguments:nil];
- OCMExpect([self.mockSignIn signIn])
+
+ XCTestExpectation *expectation = [self expectationWithDescription:@"expect result returns true"];
+ [self.plugin handleMethodCall:methodCall
+ result:^(NSDictionary<NSString *, NSString *> *result) {
+ XCTAssertEqualObjects(result[@"id"], @"mockID");
+ [expectation fulfill];
+ }];
+ [self waitForExpectationsWithTimeout:5.0 handler:nil];
+
+ OCMVerifyAll(self.mockSignIn);
+}
+
+- (void)testSignInAlreadyGranted {
+ id mockUser = OCMClassMock([GIDGoogleUser class]);
+ OCMStub([mockUser userID]).andReturn(@"mockID");
+
+ [[self.mockSignIn stub]
+ signInWithConfiguration:OCMOCK_ANY
+ presentingViewController:OCMOCK_ANY
+ hint:nil
+ additionalScopes:OCMOCK_ANY
+ callback:[OCMArg invokeBlockWithArgs:mockUser, [NSNull null], nil]];
+
+ NSError *error = [NSError errorWithDomain:kGIDSignInErrorDomain
+ code:kGIDSignInErrorCodeScopesAlreadyGranted
+ userInfo:nil];
+ [[self.mockSignIn stub] addScopes:OCMOCK_ANY
+ presentingViewController:OCMOCK_ANY
+ callback:[OCMArg invokeBlockWithArgs:[NSNull null], error, nil]];
+
+ FlutterMethodCall *methodCall = [FlutterMethodCall methodCallWithMethodName:@"signIn"
+ arguments:nil];
+
+ XCTestExpectation *expectation = [self expectationWithDescription:@"expect result returns true"];
+ [self.plugin handleMethodCall:methodCall
+ result:^(NSDictionary<NSString *, NSString *> *result) {
+ XCTAssertEqualObjects(result[@"id"], @"mockID");
+ [expectation fulfill];
+ }];
+ [self waitForExpectationsWithTimeout:5.0 handler:nil];
+}
+
+- (void)testSignInError {
+ NSError *error = [NSError errorWithDomain:kGIDSignInErrorDomain
+ code:kGIDSignInErrorCodeCanceled
+ userInfo:nil];
+ [[self.mockSignIn stub]
+ signInWithConfiguration:OCMOCK_ANY
+ presentingViewController:OCMOCK_ANY
+ hint:nil
+ additionalScopes:OCMOCK_ANY
+ callback:[OCMArg invokeBlockWithArgs:[NSNull null], error, nil]];
+
+ FlutterMethodCall *methodCall = [FlutterMethodCall methodCallWithMethodName:@"signIn"
+ arguments:nil];
+
+ XCTestExpectation *expectation = [self expectationWithDescription:@"expect result returns true"];
+ [self.plugin handleMethodCall:methodCall
+ result:^(FlutterError *result) {
+ XCTAssertEqualObjects(result.code, @"sign_in_canceled");
+ [expectation fulfill];
+ }];
+ [self waitForExpectationsWithTimeout:5.0 handler:nil];
+}
+
+- (void)testSignInException {
+ FlutterMethodCall *methodCall = [FlutterMethodCall methodCallWithMethodName:@"signIn"
+ arguments:nil];
+ OCMExpect([self.mockSignIn signInWithConfiguration:OCMOCK_ANY
+ presentingViewController:OCMOCK_ANY
+ hint:OCMOCK_ANY
+ additionalScopes:OCMOCK_ANY
+ callback:OCMOCK_ANY])
.andThrow([NSException exceptionWithName:@"MockName" reason:@"MockReason" userInfo:nil]);
__block FlutterError *error;
@@ -237,7 +410,7 @@
OCMStub([mockAuthentication idToken]).andReturn(@"mockIdToken");
OCMStub([mockAuthentication accessToken]).andReturn(@"mockAccessToken");
[[mockAuthentication stub]
- getTokensWithHandler:[OCMArg invokeBlockWithArgs:mockAuthentication, [NSNull null], nil]];
+ doWithFreshTokens:[OCMArg invokeBlockWithArgs:mockAuthentication, [NSNull null], nil]];
OCMStub([mockUser authentication]).andReturn(mockAuthentication);
FlutterMethodCall *methodCall = [FlutterMethodCall methodCallWithMethodName:@"getTokens"
@@ -262,7 +435,7 @@
code:kGIDSignInErrorCodeHasNoAuthInKeychain
userInfo:nil];
[[mockAuthentication stub]
- getTokensWithHandler:[OCMArg invokeBlockWithArgs:[NSNull null], error, nil]];
+ doWithFreshTokens:[OCMArg invokeBlockWithArgs:[NSNull null], error, nil]];
OCMStub([mockUser authentication]).andReturn(mockAuthentication);
FlutterMethodCall *methodCall = [FlutterMethodCall methodCallWithMethodName:@"getTokens"
@@ -287,7 +460,7 @@
code:kGIDSignInErrorCodeCanceled
userInfo:nil];
[[mockAuthentication stub]
- getTokensWithHandler:[OCMArg invokeBlockWithArgs:[NSNull null], error, nil]];
+ doWithFreshTokens:[OCMArg invokeBlockWithArgs:[NSNull null], error, nil]];
OCMStub([mockUser authentication]).andReturn(mockAuthentication);
FlutterMethodCall *methodCall = [FlutterMethodCall methodCallWithMethodName:@"getTokens"
@@ -310,7 +483,7 @@
id mockAuthentication = OCMClassMock([GIDAuthentication class]);
NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorTimedOut userInfo:nil];
[[mockAuthentication stub]
- getTokensWithHandler:[OCMArg invokeBlockWithArgs:[NSNull null], error, nil]];
+ doWithFreshTokens:[OCMArg invokeBlockWithArgs:[NSNull null], error, nil]];
OCMStub([mockUser authentication]).andReturn(mockAuthentication);
FlutterMethodCall *methodCall = [FlutterMethodCall methodCallWithMethodName:@"getTokens"
@@ -333,7 +506,7 @@
id mockAuthentication = OCMClassMock([GIDAuthentication class]);
NSError *error = [NSError errorWithDomain:@"BogusDomain" code:42 userInfo:nil];
[[mockAuthentication stub]
- getTokensWithHandler:[OCMArg invokeBlockWithArgs:[NSNull null], error, nil]];
+ doWithFreshTokens:[OCMArg invokeBlockWithArgs:[NSNull null], error, nil]];
OCMStub([mockUser authentication]).andReturn(mockAuthentication);
FlutterMethodCall *methodCall = [FlutterMethodCall methodCallWithMethodName:@"getTokens"
@@ -352,7 +525,12 @@
#pragma mark - Request scopes
- (void)testRequestScopesResultErrorIfNotSignedIn {
- OCMStub([self.mockSignIn currentUser]).andReturn(nil);
+ NSError *error = [NSError errorWithDomain:kGIDSignInErrorDomain
+ code:kGIDSignInErrorCodeNoCurrentUser
+ userInfo:nil];
+ [[self.mockSignIn stub] addScopes:@[ @"mockScope1" ]
+ presentingViewController:OCMOCK_ANY
+ callback:[OCMArg invokeBlockWithArgs:[NSNull null], error, nil]];
FlutterMethodCall *methodCall =
[FlutterMethodCall methodCallWithMethodName:@"requestScopes"
@@ -368,14 +546,16 @@
}
- (void)testRequestScopesIfNoMissingScope {
- // Mock Google Signin internal calls
- GIDGoogleUser *mockUser = OCMClassMock([GIDGoogleUser class]);
- OCMStub([self.mockSignIn currentUser]).andReturn(mockUser);
- NSArray *requestedScopes = @[ @"mockScope1" ];
- OCMStub(mockUser.grantedScopes).andReturn(requestedScopes);
+ NSError *error = [NSError errorWithDomain:kGIDSignInErrorDomain
+ code:kGIDSignInErrorCodeScopesAlreadyGranted
+ userInfo:nil];
+ [[self.mockSignIn stub] addScopes:@[ @"mockScope1" ]
+ presentingViewController:OCMOCK_ANY
+ callback:[OCMArg invokeBlockWithArgs:[NSNull null], error, nil]];
+
FlutterMethodCall *methodCall =
[FlutterMethodCall methodCallWithMethodName:@"requestScopes"
- arguments:@{@"scopes" : requestedScopes}];
+ arguments:@{@"scopes" : @[ @"mockScope1" ]}];
XCTestExpectation *expectation = [self expectationWithDescription:@"expect result returns true"];
[self.plugin handleMethodCall:methodCall
@@ -386,39 +566,50 @@
[self waitForExpectationsWithTimeout:5.0 handler:nil];
}
-- (void)testRequestScopesRequestsIfNotGranted {
- // Mock Google Signin internal calls
- GIDGoogleUser *mockUser = OCMClassMock([GIDGoogleUser class]);
- OCMStub([self.mockSignIn currentUser]).andReturn(mockUser);
- NSArray *requestedScopes = @[ @"mockScope1" ];
- OCMStub(mockUser.grantedScopes).andReturn(@[]);
- id mockSignIn = self.mockSignIn;
- OCMStub([mockSignIn scopes]).andReturn(@[]);
+- (void)testRequestScopesWithUnknownError {
+ NSError *error = [NSError errorWithDomain:@"BogusDomain" code:42 userInfo:nil];
+ [[self.mockSignIn stub] addScopes:@[ @"mockScope1" ]
+ presentingViewController:OCMOCK_ANY
+ callback:[OCMArg invokeBlockWithArgs:[NSNull null], error, nil]];
FlutterMethodCall *methodCall =
[FlutterMethodCall methodCallWithMethodName:@"requestScopes"
- arguments:@{@"scopes" : requestedScopes}];
+ arguments:@{@"scopes" : @[ @"mockScope1" ]}];
+ XCTestExpectation *expectation = [self expectationWithDescription:@"expect result returns true"];
[self.plugin handleMethodCall:methodCall
- result:^(id r){
+ result:^(NSNumber *result) {
+ XCTAssertFalse(result.boolValue);
+ [expectation fulfill];
}];
-
- OCMVerify([mockSignIn setScopes:@[ @"mockScope1" ]]);
- OCMVerify([mockSignIn signIn]);
+ [self waitForExpectationsWithTimeout:5.0 handler:nil];
}
-- (void)testRequestScopesReturnsFalseIfNotGranted {
- // Mock Google Signin internal calls
+- (void)testRequestScopesException {
+ FlutterMethodCall *methodCall = [FlutterMethodCall methodCallWithMethodName:@"requestScopes"
+ arguments:nil];
+ OCMExpect([self.mockSignIn addScopes:@[] presentingViewController:OCMOCK_ANY callback:OCMOCK_ANY])
+ .andThrow([NSException exceptionWithName:@"MockName" reason:@"MockReason" userInfo:nil]);
+
+ [self.plugin handleMethodCall:methodCall
+ result:^(FlutterError *result) {
+ XCTAssertEqualObjects(result.code, @"request_scopes");
+ XCTAssertEqualObjects(result.message, @"MockReason");
+ XCTAssertEqualObjects(result.details, @"MockName");
+ }];
+}
+
+- (void)testRequestScopesReturnsFalseIfOnlySubsetGranted {
GIDGoogleUser *mockUser = OCMClassMock([GIDGoogleUser class]);
OCMStub([self.mockSignIn currentUser]).andReturn(mockUser);
- NSArray *requestedScopes = @[ @"mockScope1" ];
- OCMStub(mockUser.grantedScopes).andReturn(@[]);
+ NSArray<NSString *> *requestedScopes = @[ @"mockScope1", @"mockScope2" ];
- OCMStub([self.mockSignIn signIn]).andDo(^(NSInvocation *invocation) {
- [((NSObject<GIDSignInDelegate> *)self.plugin) signIn:self.mockSignIn
- didSignInForUser:mockUser
- withError:nil];
- });
+ // Only grant one of the two requested scopes.
+ OCMStub(mockUser.grantedScopes).andReturn(@[ @"mockScope1" ]);
+
+ [[self.mockSignIn stub] addScopes:requestedScopes
+ presentingViewController:OCMOCK_ANY
+ callback:[OCMArg invokeBlockWithArgs:mockUser, [NSNull null], nil]];
FlutterMethodCall *methodCall =
[FlutterMethodCall methodCallWithMethodName:@"requestScopes"
@@ -433,20 +624,53 @@
[self waitForExpectationsWithTimeout:5.0 handler:nil];
}
+- (void)testRequestsInitializedScopes {
+ FlutterMethodCall *initMethodCall =
+ [FlutterMethodCall methodCallWithMethodName:@"init"
+ arguments:@{@"scopes" : @[ @"initial1", @"initial2" ]}];
+
+ XCTestExpectation *initExpectation =
+ [self expectationWithDescription:@"expect result returns true"];
+ [self.plugin handleMethodCall:initMethodCall
+ result:^(id result) {
+ XCTAssertNil(result);
+ [initExpectation fulfill];
+ }];
+ [self waitForExpectationsWithTimeout:5.0 handler:nil];
+
+ // Include one of the initially requested scopes.
+ NSArray<NSString *> *addedScopes = @[ @"initial1", @"addScope1", @"addScope2" ];
+
+ FlutterMethodCall *methodCall =
+ [FlutterMethodCall methodCallWithMethodName:@"requestScopes"
+ arguments:@{@"scopes" : addedScopes}];
+
+ [self.plugin handleMethodCall:methodCall
+ result:^(id result){
+ }];
+
+ // All four scopes are requested.
+ [[self.mockSignIn verify]
+ addScopes:[OCMArg checkWithBlock:^BOOL(NSArray<NSString *> *scopes) {
+ return [[NSSet setWithArray:scopes]
+ isEqualToSet:[NSSet setWithObjects:@"initial1", @"initial2",
+ @"addScope1", @"addScope2", nil]];
+ }]
+ presentingViewController:OCMOCK_ANY
+ callback:OCMOCK_ANY];
+}
+
- (void)testRequestScopesReturnsTrueIfGranted {
- // Mock Google Signin internal calls
GIDGoogleUser *mockUser = OCMClassMock([GIDGoogleUser class]);
OCMStub([self.mockSignIn currentUser]).andReturn(mockUser);
- NSArray *requestedScopes = @[ @"mockScope1" ];
- NSMutableArray *availableScopes = [NSMutableArray new];
- OCMStub(mockUser.grantedScopes).andReturn(availableScopes);
+ NSArray<NSString *> *requestedScopes = @[ @"mockScope1", @"mockScope2" ];
- OCMStub([self.mockSignIn signIn]).andDo(^(NSInvocation *invocation) {
- [availableScopes addObject:@"mockScope1"];
- [((NSObject<GIDSignInDelegate> *)self.plugin) signIn:self.mockSignIn
- didSignInForUser:mockUser
- withError:nil];
- });
+ // Grant both of the requested scopes.
+ OCMStub(mockUser.grantedScopes).andReturn(requestedScopes);
+
+ [[self.mockSignIn stub] addScopes:requestedScopes
+ presentingViewController:OCMOCK_ANY
+ callback:[OCMArg invokeBlockWithArgs:mockUser, [NSNull null], nil]];
FlutterMethodCall *methodCall =
[FlutterMethodCall methodCallWithMethodName:@"requestScopes"
diff --git a/packages/google_sign_in/google_sign_in_ios/ios/Classes/FLTGoogleSignInPlugin.m b/packages/google_sign_in/google_sign_in_ios/ios/Classes/FLTGoogleSignInPlugin.m
index 5ad69e2..55d09bd 100644
--- a/packages/google_sign_in/google_sign_in_ios/ios/Classes/FLTGoogleSignInPlugin.m
+++ b/packages/google_sign_in/google_sign_in_ios/ios/Classes/FLTGoogleSignInPlugin.m
@@ -36,17 +36,28 @@
details:error.localizedDescription];
}
-@interface FLTGoogleSignInPlugin () <GIDSignInDelegate>
+@interface FLTGoogleSignInPlugin ()
+
+// Configuration wrapping Google Cloud Console, Google Apps, OpenID,
+// and other initialization metadata.
+@property(strong) GIDConfiguration *configuration;
+
+// Permissions requested during at sign in "init" method call
+// unioned with scopes requested later with incremental authorization
+// "requestScopes" method call.
+// The "email" and "profile" base scopes are always implicitly requested.
+@property(copy) NSSet<NSString *> *requestedScopes;
+
+// Instance used to manage Google Sign In authentication including
+// sign in, sign out, and requesting additional scopes.
@property(strong, readonly) GIDSignIn *signIn;
// Redeclared as not a designated initializer.
- (instancetype)init;
+
@end
-@implementation FLTGoogleSignInPlugin {
- FlutterResult _accountRequest;
- NSArray<NSString *> *_additionalScopesRequest;
-}
+@implementation FLTGoogleSignInPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
FlutterMethodChannel *channel =
@@ -65,11 +76,11 @@
self = [super init];
if (self) {
_signIn = signIn;
- _signIn.delegate = self;
// On the iOS simulator, we get "Broken pipe" errors after sign-in for some
// unknown reason. We can avoid crashing the app by ignoring them.
signal(SIGPIPE, SIG_IGN);
+ _requestedScopes = [[NSSet alloc] init];
}
return self;
}
@@ -78,25 +89,14 @@
- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
if ([call.method isEqualToString:@"init"]) {
- NSString *path = [[NSBundle mainBundle] pathForResource:@"GoogleService-Info" ofType:@"plist"];
- if (path) {
- NSMutableDictionary<NSString *, NSString *> *plist =
- [[NSMutableDictionary alloc] initWithContentsOfFile:path];
- BOOL hasDynamicClientId = [call.arguments[@"clientId"] isKindOfClass:[NSString class]];
-
- if (hasDynamicClientId) {
- self.signIn.clientID = call.arguments[@"clientId"];
- } else {
- self.signIn.clientID = plist[kClientIdKey];
+ GIDConfiguration *configuration =
+ [self configurationWithClientIdArgument:call.arguments[@"clientId"]
+ hostedDomainArgument:call.arguments[@"hostedDomain"]];
+ if (configuration != nil) {
+ if ([call.arguments[@"scopes"] isKindOfClass:[NSArray class]]) {
+ self.requestedScopes = [NSSet setWithArray:call.arguments[@"scopes"]];
}
-
- self.signIn.serverClientID = plist[kServerClientIdKey];
- self.signIn.scopes = call.arguments[@"scopes"];
- if (call.arguments[@"hostedDomain"] == [NSNull null]) {
- self.signIn.hostedDomain = nil;
- } else {
- self.signIn.hostedDomain = call.arguments[@"hostedDomain"];
- }
+ self.configuration = configuration;
result(nil);
} else {
result([FlutterError errorWithCode:@"missing-config"
@@ -104,26 +104,31 @@
details:nil]);
}
} else if ([call.method isEqualToString:@"signInSilently"]) {
- if ([self setAccountRequest:result]) {
- [self.signIn restorePreviousSignIn];
- }
+ [self.signIn restorePreviousSignInWithCallback:^(GIDGoogleUser *user, NSError *error) {
+ [self didSignInForUser:user result:result withError:error];
+ }];
} else if ([call.method isEqualToString:@"isSignedIn"]) {
result(@([self.signIn hasPreviousSignIn]));
} else if ([call.method isEqualToString:@"signIn"]) {
- self.signIn.presentingViewController = [self topViewController];
-
- if ([self setAccountRequest:result]) {
- @try {
- [self.signIn signIn];
- } @catch (NSException *e) {
- result([FlutterError errorWithCode:@"google_sign_in" message:e.reason details:e.name]);
- [e raise];
- }
+ @try {
+ GIDConfiguration *configuration = self.configuration
+ ?: [self configurationWithClientIdArgument:nil
+ hostedDomainArgument:nil];
+ [self.signIn signInWithConfiguration:configuration
+ presentingViewController:[self topViewController]
+ hint:nil
+ additionalScopes:self.requestedScopes.allObjects
+ callback:^(GIDGoogleUser *user, NSError *error) {
+ [self didSignInForUser:user result:result withError:error];
+ }];
+ } @catch (NSException *e) {
+ result([FlutterError errorWithCode:@"google_sign_in" message:e.reason details:e.name]);
+ [e raise];
}
} else if ([call.method isEqualToString:@"getTokens"]) {
GIDGoogleUser *currentUser = self.signIn.currentUser;
GIDAuthentication *auth = currentUser.authentication;
- [auth getTokensWithHandler:^void(GIDAuthentication *authentication, NSError *error) {
+ [auth doWithFreshTokens:^void(GIDAuthentication *authentication, NSError *error) {
result(error != nil ? getFlutterError(error) : @{
@"idToken" : authentication.idToken,
@"accessToken" : authentication.accessToken,
@@ -133,61 +138,49 @@
[self.signIn signOut];
result(nil);
} else if ([call.method isEqualToString:@"disconnect"]) {
- if ([self setAccountRequest:result]) {
- [self.signIn disconnect];
- }
+ [self.signIn disconnectWithCallback:^(NSError *error) {
+ [self respondWithAccount:@{} result:result error:nil];
+ }];
} else if ([call.method isEqualToString:@"requestScopes"]) {
- GIDGoogleUser *user = self.signIn.currentUser;
- if (user == nil) {
- result([FlutterError errorWithCode:@"sign_in_required"
- message:@"No account to grant scopes."
- details:nil]);
- return;
+ id scopeArgument = call.arguments[@"scopes"];
+ if ([scopeArgument isKindOfClass:[NSArray class]]) {
+ self.requestedScopes = [self.requestedScopes setByAddingObjectsFromArray:scopeArgument];
}
+ NSSet<NSString *> *requestedScopes = self.requestedScopes;
- NSArray<NSString *> *currentScopes = self.signIn.scopes;
- NSArray<NSString *> *scopes = call.arguments[@"scopes"];
- NSArray<NSString *> *missingScopes = [scopes
- filteredArrayUsingPredicate:[NSPredicate
- predicateWithBlock:^BOOL(id scope, NSDictionary *bindings) {
- return ![user.grantedScopes containsObject:scope];
- }]];
-
- if (!missingScopes || !missingScopes.count) {
- result(@(YES));
- return;
- }
-
- if ([self setAccountRequest:result]) {
- _additionalScopesRequest = missingScopes;
- self.signIn.scopes = [currentScopes arrayByAddingObjectsFromArray:missingScopes];
- self.signIn.presentingViewController = [self topViewController];
- self.signIn.loginHint = user.profile.email;
- @try {
- [self.signIn signIn];
- } @catch (NSException *e) {
- result([FlutterError errorWithCode:@"request_scopes" message:e.reason details:e.name]);
- }
+ @try {
+ [self.signIn addScopes:requestedScopes.allObjects
+ presentingViewController:[self topViewController]
+ callback:^(GIDGoogleUser *addedScopeUser, NSError *addedScopeError) {
+ if ([addedScopeError.domain isEqualToString:kGIDSignInErrorDomain] &&
+ addedScopeError.code == kGIDSignInErrorCodeNoCurrentUser) {
+ result([FlutterError errorWithCode:@"sign_in_required"
+ message:@"No account to grant scopes."
+ details:nil]);
+ } else if ([addedScopeError.domain
+ isEqualToString:kGIDSignInErrorDomain] &&
+ addedScopeError.code ==
+ kGIDSignInErrorCodeScopesAlreadyGranted) {
+ // Scopes already granted, report success.
+ result(@YES);
+ } else if (addedScopeUser == nil) {
+ result(@NO);
+ } else {
+ NSSet<NSString *> *grantedScopes =
+ [NSSet setWithArray:addedScopeUser.grantedScopes];
+ BOOL granted = [requestedScopes isSubsetOfSet:grantedScopes];
+ result(@(granted));
+ }
+ }];
+ } @catch (NSException *e) {
+ result([FlutterError errorWithCode:@"request_scopes" message:e.reason details:e.name]);
}
} else {
result(FlutterMethodNotImplemented);
}
}
-- (BOOL)setAccountRequest:(FlutterResult)request {
- if (_accountRequest != nil) {
- request([FlutterError errorWithCode:@"concurrent-requests"
- message:@"Concurrent requests to account signin"
- details:nil]);
- return NO;
- }
- _accountRequest = request;
- return YES;
-}
-
-- (BOOL)application:(UIApplication *)app
- openURL:(NSURL *)url
- options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options {
+- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options {
return [self.signIn handleURL:url];
}
@@ -203,57 +196,58 @@
[viewController dismissViewControllerAnimated:YES completion:nil];
}
-#pragma mark - <GIDSignInDelegate> protocol
+#pragma mark - private methods
-- (void)signIn:(GIDSignIn *)signIn
- didSignInForUser:(GIDGoogleUser *)user
- withError:(NSError *)error {
+/// @return @c nil if GoogleService-Info.plist not found.
+- (GIDConfiguration *)configurationWithClientIdArgument:(id)clientIDArg
+ hostedDomainArgument:(id)hostedDomainArg {
+ NSString *plistPath = [NSBundle.mainBundle pathForResource:@"GoogleService-Info" ofType:@"plist"];
+ if (plistPath == nil) {
+ return nil;
+ }
+
+ NSDictionary<NSString *, id> *plist = [[NSDictionary alloc] initWithContentsOfFile:plistPath];
+
+ BOOL hasDynamicClientId = [clientIDArg isKindOfClass:[NSString class]];
+ NSString *clientID = hasDynamicClientId ? clientIDArg : plist[kClientIdKey];
+
+ NSString *hostedDomain = nil;
+ if (hostedDomainArg != [NSNull null]) {
+ hostedDomain = hostedDomainArg;
+ }
+ return [[GIDConfiguration alloc] initWithClientID:clientID
+ serverClientID:plist[kServerClientIdKey]
+ hostedDomain:hostedDomain
+ openIDRealm:nil];
+}
+
+- (void)didSignInForUser:(GIDGoogleUser *)user
+ result:(FlutterResult)result
+ withError:(NSError *)error {
if (error != nil) {
// Forward all errors and let Dart side decide how to handle.
- [self respondWithAccount:nil error:error];
+ [self respondWithAccount:nil result:result error:error];
} else {
- if (_additionalScopesRequest) {
- bool granted = YES;
- for (NSString *scope in _additionalScopesRequest) {
- if (![user.grantedScopes containsObject:scope]) {
- granted = NO;
- break;
- }
- }
- _accountRequest(@(granted));
- _accountRequest = nil;
- _additionalScopesRequest = nil;
- return;
- } else {
- NSURL *photoUrl;
- if (user.profile.hasImage) {
- // Placeholder that will be replaced by on the Dart side based on screen
- // size
- photoUrl = [user.profile imageURLWithDimension:1337];
- }
- [self respondWithAccount:@{
- @"displayName" : user.profile.name ?: [NSNull null],
- @"email" : user.profile.email ?: [NSNull null],
- @"id" : user.userID ?: [NSNull null],
- @"photoUrl" : [photoUrl absoluteString] ?: [NSNull null],
- @"serverAuthCode" : user.serverAuthCode ?: [NSNull null]
- }
- error:nil];
+ NSURL *photoUrl;
+ if (user.profile.hasImage) {
+ // Placeholder that will be replaced by on the Dart side based on screen size.
+ photoUrl = [user.profile imageURLWithDimension:1337];
}
+ [self respondWithAccount:@{
+ @"displayName" : user.profile.name ?: [NSNull null],
+ @"email" : user.profile.email ?: [NSNull null],
+ @"id" : user.userID ?: [NSNull null],
+ @"photoUrl" : [photoUrl absoluteString] ?: [NSNull null],
+ @"serverAuthCode" : user.serverAuthCode ?: [NSNull null]
+ }
+ result:result
+ error:nil];
}
}
-- (void)signIn:(GIDSignIn *)signIn
- didDisconnectWithUser:(GIDGoogleUser *)user
- withError:(NSError *)error {
- [self respondWithAccount:@{} error:nil];
-}
-
-#pragma mark - private methods
-
-- (void)respondWithAccount:(NSDictionary<NSString *, id> *)account error:(NSError *)error {
- FlutterResult result = _accountRequest;
- _accountRequest = nil;
+- (void)respondWithAccount:(NSDictionary<NSString *, id> *)account
+ result:(FlutterResult)result
+ error:(NSError *)error {
result(error != nil ? getFlutterError(error) : account);
}
diff --git a/packages/google_sign_in/google_sign_in_ios/ios/google_sign_in_ios.podspec b/packages/google_sign_in/google_sign_in_ios/ios/google_sign_in_ios.podspec
index f583f6c..18a2135 100644
--- a/packages/google_sign_in/google_sign_in_ios/ios/google_sign_in_ios.podspec
+++ b/packages/google_sign_in/google_sign_in_ios/ios/google_sign_in_ios.podspec
@@ -16,11 +16,8 @@
s.public_header_files = 'Classes/**/*.h'
s.module_map = 'Classes/FLTGoogleSignInPlugin.modulemap'
s.dependency 'Flutter'
- s.dependency 'GoogleSignIn', '~> 5.0'
+ s.dependency 'GoogleSignIn', '~> 6.2'
s.static_framework = true
-
s.platform = :ios, '9.0'
-
- # GoogleSignIn ~> 5.0 does not support arm64 simulators.
- s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' }
+ s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }
end
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 b6f541b..5604ee6 100644
--- a/packages/google_sign_in/google_sign_in_ios/pubspec.yaml
+++ b/packages/google_sign_in/google_sign_in_ios/pubspec.yaml
@@ -1,8 +1,8 @@
name: google_sign_in_ios
-description: Android implementation of the google_sign_in plugin.
+description: iOS implementation of the google_sign_in plugin.
repository: https://github.com/flutter/plugins/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: 5.2.7
+version: 5.3.0
environment:
sdk: ">=2.14.0 <3.0.0"