Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/google_sign_in/google_sign_in_ios/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 5.7.0

* Adds support for macOS.

## 5.6.4

* Converts platform communication to Pigeon.
Expand Down
17 changes: 16 additions & 1 deletion packages/google_sign_in/google_sign_in_ios/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# google\_sign\_in\_ios

The iOS implementation of [`google_sign_in`][1].
The iOS and macOS implementation of [`google_sign_in`][1].

## Usage

Expand All @@ -11,5 +11,20 @@ so you do not need to add it to your `pubspec.yaml`.
However, if you `import` this package to use any of its APIs directly, you
should add it to your `pubspec.yaml` as usual.

### macOS setup

The GoogleSignIn SDK requires keychain sharing to be enabled, by [adding the
following entitlements](https://docs.flutter.dev/platform-integration/macos/building#entitlements-and-the-app-sandbox):

```xml
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)com.google.GIDSignIn</string>
</array>
```

Without this step, the plugin will throw a `keychain error` `PlatformException`
when trying to sign in.

[1]: https://pub.dev/packages/google_sign_in
[2]: https://flutter.dev/docs/development/packages-and-plugins/developing-packages#endorsed-federated-plugin
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#if TARGET_OS_OSX
#import <FlutterMacOS/FlutterMacOS.h>
#else
#import <Flutter/Flutter.h>
#endif

#import "messages.g.h"

@interface FLTGoogleSignInPlugin : NSObject <FlutterPlugin, FSIGoogleSignInApi>
- (instancetype)init NS_UNAVAILABLE;
@end
Original file line number Diff line number Diff line change
Expand Up @@ -64,32 +64,39 @@ @interface FLTGoogleSignInPlugin ()
// The contents of GoogleService-Info.plist, if it exists.
@property(strong, nullable) NSDictionary<NSString *, id> *googleServiceProperties;

// Redeclared as not a designated initializer.
- (instancetype)init;
// The plugin registrar, for querying views.
@property(strong, nonnull) id<FlutterPluginRegistrar> registrar;

- (instancetype)initWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar;

@end

@implementation FLTGoogleSignInPlugin

+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
FLTGoogleSignInPlugin *instance = [[FLTGoogleSignInPlugin alloc] init];
FLTGoogleSignInPlugin *instance = [[FLTGoogleSignInPlugin alloc] initWithRegistrar:registrar];
[registrar addApplicationDelegate:instance];
FSIGoogleSignInApiSetup(registrar.messenger, instance);
}

- (instancetype)init {
return [self initWithSignIn:GIDSignIn.sharedInstance];
- (instancetype)initWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
return [self initWithSignIn:GIDSignIn.sharedInstance registrar:registrar];
}

- (instancetype)initWithSignIn:(GIDSignIn *)signIn {
return [self initWithSignIn:signIn withGoogleServiceProperties:loadGoogleServiceInfo()];
- (instancetype)initWithSignIn:(GIDSignIn *)signIn
registrar:(NSObject<FlutterPluginRegistrar> *)registrar {
return [self initWithSignIn:signIn
registrar:registrar
googleServiceProperties:loadGoogleServiceInfo()];
}

- (instancetype)initWithSignIn:(GIDSignIn *)signIn
withGoogleServiceProperties:(nullable NSDictionary<NSString *, id> *)googleServiceProperties {
registrar:(NSObject<FlutterPluginRegistrar> *)registrar
googleServiceProperties:(nullable NSDictionary<NSString *, id> *)googleServiceProperties {
self = [super init];
if (self) {
_signIn = signIn;
_registrar = registrar;
_googleServiceProperties = googleServiceProperties;

// On the iOS simulator, we get "Broken pipe" errors after sign-in for some
Expand All @@ -102,9 +109,19 @@ - (instancetype)initWithSignIn:(GIDSignIn *)signIn

#pragma mark - <FlutterPlugin> protocol

#if TARGET_OS_IOS
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options {
return [self.signIn handleURL:url];
}
#else
- (BOOL)handleOpenURLs:(NSArray<NSURL *> *)urls {
BOOL handled = NO;
for (NSURL *url in urls) {
handled = handled || [self.signIn handleURL:url];
}
return handled;
}
#endif

#pragma mark - FSIGoogleSignInApi

Expand Down Expand Up @@ -143,15 +160,12 @@ - (void)signInWithCompletion:(nonnull void (^)(FSIUserData *_Nullable,
?: [self configurationWithClientIdArgument:nil
serverClientIdArgument:nil
hostedDomainArgument:nil];
[self.signIn signInWithConfiguration:configuration
presentingViewController:[self topViewController]
hint:nil
additionalScopes:self.requestedScopes.allObjects
callback:^(GIDGoogleUser *user, NSError *error) {
[self didSignInForUser:user
withCompletion:completion
error:error];
}];
[self signInWithConfiguration:configuration
hint:nil
additionalScopes:self.requestedScopes.allObjects
callback:^(GIDGoogleUser *user, NSError *error) {
[self didSignInForUser:user withCompletion:completion error:error];
}];
} @catch (NSException *e) {
completion(nil, [FlutterError errorWithCode:@"google_sign_in" message:e.reason details:e.name]);
[e raise];
Expand Down Expand Up @@ -190,50 +204,65 @@ - (void)requestScopes:(nonnull NSArray<NSString *> *)scopes
NSSet<NSString *> *requestedScopes = self.requestedScopes;

@try {
[self.signIn addScopes:requestedScopes.allObjects
presentingViewController:[self topViewController]
callback:^(GIDGoogleUser *addedScopeUser, NSError *addedScopeError) {
BOOL granted = NO;
FlutterError *error = nil;
if ([addedScopeError.domain isEqualToString:kGIDSignInErrorDomain] &&
addedScopeError.code == kGIDSignInErrorCodeNoCurrentUser) {
error = [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.
granted = YES;
} else if (addedScopeUser == nil) {
granted = NO;
} else {
NSSet<NSString *> *grantedScopes =
[NSSet setWithArray:addedScopeUser.grantedScopes];
granted = [requestedScopes isSubsetOfSet:grantedScopes];
}
completion(error == nil ? @(granted) : nil, error);
}];
[self addScopes:requestedScopes.allObjects
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason it looks like there are a lot of changes here (and in the previous block) is that switching to the new helper function without presentingViewController changed the indentation of the whole block. The code in the block doesn't have any non-whitespace changes.

callback:^(GIDGoogleUser *addedScopeUser, NSError *addedScopeError) {
BOOL granted = NO;
FlutterError *error = nil;
if ([addedScopeError.domain isEqualToString:kGIDSignInErrorDomain] &&
addedScopeError.code == kGIDSignInErrorCodeNoCurrentUser) {
error = [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.
granted = YES;
} else if (addedScopeUser == nil) {
granted = NO;
} else {
NSSet<NSString *> *grantedScopes = [NSSet setWithArray:addedScopeUser.grantedScopes];
granted = [requestedScopes isSubsetOfSet:grantedScopes];
}
completion(error == nil ? @(granted) : nil, error);
}];
} @catch (NSException *e) {
completion(nil, [FlutterError errorWithCode:@"request_scopes" message:e.reason details:e.name]);
}
}

#pragma mark - <GIDSignInUIDelegate> protocol
#pragma mark - private methods

- (void)signIn:(GIDSignIn *)signIn presentViewController:(UIViewController *)viewController {
UIViewController *rootViewController =
[UIApplication sharedApplication].delegate.window.rootViewController;
[rootViewController presentViewController:viewController animated:YES completion:nil];
// Wraps the iOS and macOS sign in display methods.
- (void)signInWithConfiguration:(GIDConfiguration *)configuration
hint:(nullable NSString *)hint
additionalScopes:(nullable NSArray<NSString *> *)additionalScopes
callback:(nullable GIDSignInCallback)callback {
#if TARGET_OS_OSX
[self.signIn signInWithConfiguration:configuration
presentingWindow:self.registrar.view.window
hint:hint
additionalScopes:additionalScopes
callback:callback];
#else
[self.signIn signInWithConfiguration:configuration
presentingViewController:[self topViewController]
hint:hint
additionalScopes:additionalScopes
callback:callback];
#endif
}

- (void)signIn:(GIDSignIn *)signIn dismissViewController:(UIViewController *)viewController {
[viewController dismissViewControllerAnimated:YES completion:nil];
// Wraps the iOS and macOS scope addition methods.
- (void)addScopes:(NSArray<NSString *> *)scopes callback:(nullable GIDSignInCallback)callback {
#if TARGET_OS_OSX
[self.signIn addScopes:scopes presentingWindow:self.registrar.view.window callback:callback];
#else
[self.signIn addScopes:scopes
presentingViewController:[self topViewController]
callback:callback];
#endif
}

#pragma mark - private methods

/// @return @c nil if GoogleService-Info.plist not found and clientId is not provided.
- (GIDConfiguration *)configurationWithClientIdArgument:(id)clientIDArg
serverClientIdArgument:(id)serverClientIDArg
Expand Down Expand Up @@ -286,6 +315,8 @@ - (void)didSignInForUser:(GIDGoogleUser *)user
}
}

#if TARGET_OS_IOS

- (UIViewController *)topViewController {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
Expand Down Expand Up @@ -324,4 +355,6 @@ - (UIViewController *)topViewControllerFromViewController:(UIViewController *)vi
return viewController;
}

#endif

@end
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ NS_ASSUME_NONNULL_BEGIN
@interface FLTGoogleSignInPlugin ()

/// Inject @c GIDSignIn for testing.
- (instancetype)initWithSignIn:(GIDSignIn *)signIn;
- (instancetype)initWithSignIn:(GIDSignIn *)signIn
registrar:(NSObject<FlutterPluginRegistrar> *)registrar;

/// Inject @c GIDSignIn and @c googleServiceProperties for testing.
- (instancetype)initWithSignIn:(GIDSignIn *)signIn
withGoogleServiceProperties:(nullable NSDictionary<NSString *, id> *)googleServiceProperties
registrar:(NSObject<FlutterPluginRegistrar> *)registrar
googleServiceProperties:(nullable NSDictionary<NSString *, id> *)googleServiceProperties
NS_DESIGNATED_INITIALIZER;

@end
Expand Down
Loading