| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #import "ios/chrome/browser/geolocation/location_manager.h" |
| |
| #import "ios/chrome/browser/geolocation/CLLocation+OmniboxGeolocation.h" |
| #import "ios/chrome/browser/geolocation/location_manager+Testing.h" |
| #import "ios/public/provider/chrome/browser/chrome_browser_provider.h" |
| #import "ios/public/provider/chrome/browser/geolocation_updater_provider.h" |
| |
| #if !defined(__has_feature) || !__has_feature(objc_arc) |
| #error "This file requires ARC support." |
| #endif |
| |
| namespace { |
| |
| const CLLocationDistance kLocationDesiredAccuracy = |
| kCLLocationAccuracyHundredMeters; |
| // Number of seconds to wait before automatically stopping location updates. |
| const NSTimeInterval kLocationStopUpdateDelay = 5.0; |
| // A large value to disable automatic location updates in GeolocationUpdater. |
| const NSTimeInterval kLocationUpdateInterval = 365.0 * 24.0 * 60.0 * 60.0; |
| |
| } // namespace |
| |
| @interface LocationManager () { |
| id<GeolocationUpdater> _locationUpdater; |
| NSDate* _startTime; |
| } |
| |
| // Handles GeolocationUpdater notification for an updated device location. |
| - (void)handleLocationUpdateNotification:(NSNotification*)notification; |
| // Handles GeolocationUpdater notification for ending device location updates. |
| - (void)handleLocationStopNotification:(NSNotification*)notification; |
| // Handles GeolocationUpdater notification for changing authorization. |
| - (void)handleAuthorizationChangeNotification:(NSNotification*)notification; |
| |
| @end |
| |
| @implementation LocationManager |
| @synthesize delegate = _delegate; |
| @synthesize currentLocation = _currentLocation; |
| |
| - (id)init { |
| self = [super init]; |
| if (self) { |
| ios::GeolocationUpdaterProvider* provider = |
| ios::GetChromeBrowserProvider()->GetGeolocationUpdaterProvider(); |
| |
| // |provider| may be null in tests. |
| if (provider) { |
| _locationUpdater = provider->CreateGeolocationUpdater(false); |
| [_locationUpdater setDesiredAccuracy:kLocationDesiredAccuracy |
| distanceFilter:kLocationDesiredAccuracy / 2]; |
| [_locationUpdater setStopUpdateDelay:kLocationStopUpdateDelay]; |
| [_locationUpdater setUpdateInterval:kLocationUpdateInterval]; |
| |
| NSNotificationCenter* defaultCenter = |
| [NSNotificationCenter defaultCenter]; |
| [defaultCenter addObserver:self |
| selector:@selector(handleLocationUpdateNotification:) |
| name:provider->GetUpdateNotificationName() |
| object:_locationUpdater]; |
| [defaultCenter addObserver:self |
| selector:@selector(handleLocationStopNotification:) |
| name:provider->GetStopNotificationName() |
| object:_locationUpdater]; |
| [defaultCenter |
| addObserver:self |
| selector:@selector(handleAuthorizationChangeNotification:) |
| name:provider->GetAuthorizationChangeNotificationName() |
| object:nil]; |
| } |
| } |
| return self; |
| } |
| |
| - (void)dealloc { |
| [[NSNotificationCenter defaultCenter] removeObserver:self]; |
| } |
| |
| - (CLAuthorizationStatus)authorizationStatus { |
| return [CLLocationManager authorizationStatus]; |
| } |
| |
| - (CLLocation*)currentLocation { |
| if (!_currentLocation) |
| _currentLocation = [_locationUpdater currentLocation]; |
| return _currentLocation; |
| } |
| |
| - (BOOL)locationServicesEnabled { |
| return [CLLocationManager locationServicesEnabled]; |
| } |
| |
| - (void)startUpdatingLocation { |
| CLLocation* currentLocation = self.currentLocation; |
| if (!currentLocation || [currentLocation cr_shouldRefresh]) { |
| if (![_locationUpdater isEnabled]) |
| _startTime = [[NSDate alloc] init]; |
| |
| [_locationUpdater requestWhenInUseAuthorization]; |
| [_locationUpdater setEnabled:YES]; |
| } |
| } |
| |
| - (void)stopUpdatingLocation { |
| [_locationUpdater setEnabled:NO]; |
| } |
| |
| #pragma mark - Private |
| |
| - (void)handleLocationUpdateNotification:(NSNotification*)notification { |
| NSString* newLocationKey = ios::GetChromeBrowserProvider() |
| ->GetGeolocationUpdaterProvider() |
| ->GetUpdateNewLocationKey(); |
| CLLocation* location = [[notification userInfo] objectForKey:newLocationKey]; |
| if (location) { |
| _currentLocation = location; |
| |
| if (_startTime) { |
| NSTimeInterval interval = -[_startTime timeIntervalSinceNow]; |
| [_currentLocation cr_setAcquisitionInterval:interval]; |
| } |
| } |
| } |
| |
| - (void)handleLocationStopNotification:(NSNotification*)notification { |
| [_locationUpdater setEnabled:NO]; |
| } |
| |
| - (void)handleAuthorizationChangeNotification:(NSNotification*)notification { |
| [_delegate locationManagerDidChangeAuthorizationStatus:self]; |
| } |
| |
| #pragma mark - LocationManager+Testing |
| |
| - (void)setGeolocationUpdater:(id<GeolocationUpdater>)geolocationUpdater { |
| _locationUpdater = geolocationUpdater; |
| } |
| |
| @end |