OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "ios/chrome/browser/geolocation/location_manager.h" | 5 #import "ios/chrome/browser/geolocation/location_manager.h" |
6 | 6 |
7 #import "base/ios/weak_nsobject.h" | |
8 #include "base/mac/scoped_nsobject.h" | |
9 #import "ios/chrome/browser/geolocation/CLLocation+OmniboxGeolocation.h" | 7 #import "ios/chrome/browser/geolocation/CLLocation+OmniboxGeolocation.h" |
10 #import "ios/chrome/browser/geolocation/location_manager+Testing.h" | 8 #import "ios/chrome/browser/geolocation/location_manager+Testing.h" |
11 #import "ios/public/provider/chrome/browser/chrome_browser_provider.h" | 9 #import "ios/public/provider/chrome/browser/chrome_browser_provider.h" |
12 #import "ios/public/provider/chrome/browser/geolocation_updater_provider.h" | 10 #import "ios/public/provider/chrome/browser/geolocation_updater_provider.h" |
13 | 11 |
| 12 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 13 #error "This file requires ARC support." |
| 14 #endif |
| 15 |
14 namespace { | 16 namespace { |
15 | 17 |
16 const CLLocationDistance kLocationDesiredAccuracy = | 18 const CLLocationDistance kLocationDesiredAccuracy = |
17 kCLLocationAccuracyHundredMeters; | 19 kCLLocationAccuracyHundredMeters; |
18 // Number of seconds to wait before automatically stopping location updates. | 20 // Number of seconds to wait before automatically stopping location updates. |
19 const NSTimeInterval kLocationStopUpdateDelay = 5.0; | 21 const NSTimeInterval kLocationStopUpdateDelay = 5.0; |
20 // A large value to disable automatic location updates in GeolocationUpdater. | 22 // A large value to disable automatic location updates in GeolocationUpdater. |
21 const NSTimeInterval kLocationUpdateInterval = 365.0 * 24.0 * 60.0 * 60.0; | 23 const NSTimeInterval kLocationUpdateInterval = 365.0 * 24.0 * 60.0 * 60.0; |
22 | 24 |
23 } // namespace | 25 } // namespace |
24 | 26 |
25 @interface LocationManager () { | 27 @interface LocationManager () { |
26 base::scoped_nsprotocol<id<GeolocationUpdater>> _locationUpdater; | 28 id<GeolocationUpdater> _locationUpdater; |
27 base::scoped_nsobject<CLLocation> _currentLocation; | 29 NSDate* _startTime; |
28 base::WeakNSProtocol<id<LocationManagerDelegate>> _delegate; | |
29 base::scoped_nsobject<NSDate> _startTime; | |
30 } | 30 } |
31 | 31 |
32 // Handles GeolocationUpdater notification for an updated device location. | 32 // Handles GeolocationUpdater notification for an updated device location. |
33 - (void)handleLocationUpdateNotification:(NSNotification*)notification; | 33 - (void)handleLocationUpdateNotification:(NSNotification*)notification; |
34 // Handles GeolocationUpdater notification for ending device location updates. | 34 // Handles GeolocationUpdater notification for ending device location updates. |
35 - (void)handleLocationStopNotification:(NSNotification*)notification; | 35 - (void)handleLocationStopNotification:(NSNotification*)notification; |
36 // Handles GeolocationUpdater notification for changing authorization. | 36 // Handles GeolocationUpdater notification for changing authorization. |
37 - (void)handleAuthorizationChangeNotification:(NSNotification*)notification; | 37 - (void)handleAuthorizationChangeNotification:(NSNotification*)notification; |
38 | 38 |
39 @end | 39 @end |
40 | 40 |
41 @implementation LocationManager | 41 @implementation LocationManager |
| 42 @synthesize delegate = _delegate; |
| 43 @synthesize currentLocation = _currentLocation; |
42 | 44 |
43 - (id)init { | 45 - (id)init { |
44 self = [super init]; | 46 self = [super init]; |
45 if (self) { | 47 if (self) { |
46 ios::GeolocationUpdaterProvider* provider = | 48 ios::GeolocationUpdaterProvider* provider = |
47 ios::GetChromeBrowserProvider()->GetGeolocationUpdaterProvider(); | 49 ios::GetChromeBrowserProvider()->GetGeolocationUpdaterProvider(); |
48 | 50 |
49 // |provider| may be null in tests. | 51 // |provider| may be null in tests. |
50 if (provider) { | 52 if (provider) { |
51 _locationUpdater.reset(provider->CreateGeolocationUpdater(false)); | 53 _locationUpdater = provider->CreateGeolocationUpdater(false); |
52 [_locationUpdater setDesiredAccuracy:kLocationDesiredAccuracy | 54 [_locationUpdater setDesiredAccuracy:kLocationDesiredAccuracy |
53 distanceFilter:kLocationDesiredAccuracy / 2]; | 55 distanceFilter:kLocationDesiredAccuracy / 2]; |
54 [_locationUpdater setStopUpdateDelay:kLocationStopUpdateDelay]; | 56 [_locationUpdater setStopUpdateDelay:kLocationStopUpdateDelay]; |
55 [_locationUpdater setUpdateInterval:kLocationUpdateInterval]; | 57 [_locationUpdater setUpdateInterval:kLocationUpdateInterval]; |
56 | 58 |
57 NSNotificationCenter* defaultCenter = | 59 NSNotificationCenter* defaultCenter = |
58 [NSNotificationCenter defaultCenter]; | 60 [NSNotificationCenter defaultCenter]; |
59 [defaultCenter addObserver:self | 61 [defaultCenter addObserver:self |
60 selector:@selector(handleLocationUpdateNotification:) | 62 selector:@selector(handleLocationUpdateNotification:) |
61 name:provider->GetUpdateNotificationName() | 63 name:provider->GetUpdateNotificationName() |
62 object:_locationUpdater]; | 64 object:_locationUpdater]; |
63 [defaultCenter addObserver:self | 65 [defaultCenter addObserver:self |
64 selector:@selector(handleLocationStopNotification:) | 66 selector:@selector(handleLocationStopNotification:) |
65 name:provider->GetStopNotificationName() | 67 name:provider->GetStopNotificationName() |
66 object:_locationUpdater]; | 68 object:_locationUpdater]; |
67 [defaultCenter | 69 [defaultCenter |
68 addObserver:self | 70 addObserver:self |
69 selector:@selector(handleAuthorizationChangeNotification:) | 71 selector:@selector(handleAuthorizationChangeNotification:) |
70 name:provider->GetAuthorizationChangeNotificationName() | 72 name:provider->GetAuthorizationChangeNotificationName() |
71 object:nil]; | 73 object:nil]; |
72 } | 74 } |
73 } | 75 } |
74 return self; | 76 return self; |
75 } | 77 } |
76 | 78 |
77 - (void)dealloc { | 79 - (void)dealloc { |
78 [[NSNotificationCenter defaultCenter] removeObserver:self]; | 80 [[NSNotificationCenter defaultCenter] removeObserver:self]; |
79 [super dealloc]; | |
80 } | 81 } |
81 | 82 |
82 - (CLAuthorizationStatus)authorizationStatus { | 83 - (CLAuthorizationStatus)authorizationStatus { |
83 return [CLLocationManager authorizationStatus]; | 84 return [CLLocationManager authorizationStatus]; |
84 } | 85 } |
85 | 86 |
86 - (CLLocation*)currentLocation { | 87 - (CLLocation*)currentLocation { |
87 if (!_currentLocation) | 88 if (!_currentLocation) |
88 _currentLocation.reset([[_locationUpdater currentLocation] retain]); | 89 _currentLocation = [_locationUpdater currentLocation]; |
89 return _currentLocation; | 90 return _currentLocation; |
90 } | 91 } |
91 | 92 |
92 - (id<LocationManagerDelegate>)delegate { | |
93 return _delegate; | |
94 } | |
95 | |
96 - (void)setDelegate:(id<LocationManagerDelegate>)delegate { | |
97 _delegate.reset(delegate); | |
98 } | |
99 | |
100 - (BOOL)locationServicesEnabled { | 93 - (BOOL)locationServicesEnabled { |
101 return [CLLocationManager locationServicesEnabled]; | 94 return [CLLocationManager locationServicesEnabled]; |
102 } | 95 } |
103 | 96 |
104 - (void)startUpdatingLocation { | 97 - (void)startUpdatingLocation { |
105 CLLocation* currentLocation = self.currentLocation; | 98 CLLocation* currentLocation = self.currentLocation; |
106 if (!currentLocation || [currentLocation cr_shouldRefresh]) { | 99 if (!currentLocation || [currentLocation cr_shouldRefresh]) { |
107 if (![_locationUpdater isEnabled]) | 100 if (![_locationUpdater isEnabled]) |
108 _startTime.reset([[NSDate alloc] init]); | 101 _startTime = [[NSDate alloc] init]; |
109 | 102 |
110 [_locationUpdater requestWhenInUseAuthorization]; | 103 [_locationUpdater requestWhenInUseAuthorization]; |
111 [_locationUpdater setEnabled:YES]; | 104 [_locationUpdater setEnabled:YES]; |
112 } | 105 } |
113 } | 106 } |
114 | 107 |
115 - (void)stopUpdatingLocation { | 108 - (void)stopUpdatingLocation { |
116 [_locationUpdater setEnabled:NO]; | 109 [_locationUpdater setEnabled:NO]; |
117 } | 110 } |
118 | 111 |
119 #pragma mark - Private | 112 #pragma mark - Private |
120 | 113 |
121 - (void)handleLocationUpdateNotification:(NSNotification*)notification { | 114 - (void)handleLocationUpdateNotification:(NSNotification*)notification { |
122 NSString* newLocationKey = ios::GetChromeBrowserProvider() | 115 NSString* newLocationKey = ios::GetChromeBrowserProvider() |
123 ->GetGeolocationUpdaterProvider() | 116 ->GetGeolocationUpdaterProvider() |
124 ->GetUpdateNewLocationKey(); | 117 ->GetUpdateNewLocationKey(); |
125 CLLocation* location = [[notification userInfo] objectForKey:newLocationKey]; | 118 CLLocation* location = [[notification userInfo] objectForKey:newLocationKey]; |
126 if (location) { | 119 if (location) { |
127 _currentLocation.reset([location retain]); | 120 _currentLocation = location; |
128 | 121 |
129 if (_startTime) { | 122 if (_startTime) { |
130 NSTimeInterval interval = -[_startTime timeIntervalSinceNow]; | 123 NSTimeInterval interval = -[_startTime timeIntervalSinceNow]; |
131 [_currentLocation cr_setAcquisitionInterval:interval]; | 124 [_currentLocation cr_setAcquisitionInterval:interval]; |
132 } | 125 } |
133 } | 126 } |
134 } | 127 } |
135 | 128 |
136 - (void)handleLocationStopNotification:(NSNotification*)notification { | 129 - (void)handleLocationStopNotification:(NSNotification*)notification { |
137 [_locationUpdater setEnabled:NO]; | 130 [_locationUpdater setEnabled:NO]; |
138 } | 131 } |
139 | 132 |
140 - (void)handleAuthorizationChangeNotification:(NSNotification*)notification { | 133 - (void)handleAuthorizationChangeNotification:(NSNotification*)notification { |
141 [_delegate locationManagerDidChangeAuthorizationStatus:self]; | 134 [_delegate locationManagerDidChangeAuthorizationStatus:self]; |
142 } | 135 } |
143 | 136 |
144 #pragma mark - LocationManager+Testing | 137 #pragma mark - LocationManager+Testing |
145 | 138 |
146 - (void)setGeolocationUpdater:(id<GeolocationUpdater>)geolocationUpdater { | 139 - (void)setGeolocationUpdater:(id<GeolocationUpdater>)geolocationUpdater { |
147 _locationUpdater.reset([geolocationUpdater retain]); | 140 _locationUpdater = geolocationUpdater; |
148 } | 141 } |
149 | 142 |
150 @end | 143 @end |
OLD | NEW |