1// Copyright 2016-present 650 Industries. All rights reserved.
2
3#import <EXLocation/EXBackgroundLocationPermissionRequester.h>
4
5#import <objc/message.h>
6#import <CoreLocation/CLLocationManagerDelegate.h>
7
8static SEL alwaysAuthorizationSelector;
9
10@interface EXBackgroundLocationPermissionRequester ()
11
12@property (nonatomic, assign) bool wasAsked;
13
14@end
15
16@implementation EXBackgroundLocationPermissionRequester
17
18- (instancetype)init
19{
20  if (self = [super init]) {
21    _wasAsked = false;
22  }
23  return self;
24}
25
26+ (NSString *)permissionType
27{
28  return @"locationBackground";
29}
30
31+ (void)load
32{
33  alwaysAuthorizationSelector = NSSelectorFromString([@"request" stringByAppendingString:@"AlwaysAuthorization"]);
34}
35
36- (void)requestLocationPermissions
37{
38  if ([EXBaseLocationRequester isConfiguredForAlwaysAuthorization] && [self.locationManager respondsToSelector:alwaysAuthorizationSelector]) {
39    _wasAsked = true;
40    [[NSNotificationCenter defaultCenter] addObserver:self
41                                             selector:@selector(handleAppBecomingActive)
42                                                 name:UIApplicationDidBecomeActiveNotification
43                                               object:nil];
44    ((void (*)(id, SEL))objc_msgSend)(self.locationManager, alwaysAuthorizationSelector);
45  } else {
46    self.reject(@"ERR_LOCATION_INFO_PLIST", @"One of the `NSLocation*UsageDescription` keys must be present in Info.plist to be able to use geolocation.", nil);
47
48    self.resolve = nil;
49    self.reject = nil;
50  }
51}
52
53// If user selects "Keep Only While Using" option, the `locationManagerDidChangeAuthorization` won't be called.
54// So we don't know when we should resolve promise.
55// Hovewer, we can check for `UIApplicationDidBecomeActiveNotification` event which is called when permissions modal disappears.
56- (void)handleAppBecomingActive
57{
58  [[NSNotificationCenter defaultCenter] removeObserver:self];
59  if (self.resolve) {
60    self.resolve([self getPermissions]);
61    self.resolve = nil;
62    self.reject = nil;
63  }
64}
65
66- (NSDictionary *)parsePermissions:(CLAuthorizationStatus)systemStatus
67{
68  EXPermissionStatus status;
69
70  switch (systemStatus) {
71    case kCLAuthorizationStatusAuthorizedAlways: {
72      status = EXPermissionStatusGranted;
73      break;
74    }
75    case kCLAuthorizationStatusDenied:
76    case kCLAuthorizationStatusRestricted: {
77      status = EXPermissionStatusDenied;
78      break;
79    }
80    case kCLAuthorizationStatusAuthorizedWhenInUse: {
81      if (_wasAsked) {
82        status = EXPermissionStatusDenied;
83      } else {
84        status = EXPermissionStatusUndetermined;
85      }
86      break;
87    }
88    case kCLAuthorizationStatusNotDetermined:
89    default: {
90
91      status = EXPermissionStatusUndetermined;
92      break;
93    }
94  }
95
96  return @{ @"status": @(status) };
97}
98
99@end
100