blob: e9daf6e71596cc077f9159c04e62efc4ed72169f [file] [log] [blame]
// 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