1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/system/mac/CoreLocationLocationProvider.mm Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,196 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim:set ts=2 sw=2 sts=2 et cindent: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "nsCOMPtr.h" 1.11 +#include "nsGeoPosition.h" 1.12 +#include "nsIConsoleService.h" 1.13 +#include "nsServiceManagerUtils.h" 1.14 +#include "nsIDOMGeoPositionError.h" 1.15 +#include "CoreLocationLocationProvider.h" 1.16 +#include "nsCocoaFeatures.h" 1.17 +#include "prtime.h" 1.18 + 1.19 +#include <CoreLocation/CLError.h> 1.20 +#include <CoreLocation/CLLocation.h> 1.21 +#include <CoreLocation/CLLocationManager.h> 1.22 +#include <CoreLocation/CLLocationManagerDelegate.h> 1.23 + 1.24 +#include <objc/objc.h> 1.25 +#include <objc/objc-runtime.h> 1.26 + 1.27 +#include "nsObjCExceptions.h" 1.28 + 1.29 +using namespace mozilla; 1.30 + 1.31 +static const CLLocationAccuracy kHIGH_ACCURACY = kCLLocationAccuracyBest; 1.32 +static const CLLocationAccuracy kDEFAULT_ACCURACY = kCLLocationAccuracyNearestTenMeters; 1.33 + 1.34 +@interface LocationDelegate : NSObject <CLLocationManagerDelegate> 1.35 +{ 1.36 + CoreLocationLocationProvider* mProvider; 1.37 +} 1.38 + 1.39 +- (id)init:(CoreLocationLocationProvider*)aProvider; 1.40 +- (void)locationManager:(CLLocationManager*)aManager 1.41 + didFailWithError:(NSError *)aError; 1.42 + 1.43 +/* XXX (ggp) didUpdateToLocation is supposedly deprecated in favor of 1.44 + * locationManager:didUpdateLocations, which is undocumented and didn't seem to 1.45 + * work for me. This should be changed in the future, though. 1.46 + */ 1.47 +- (void)locationManager:(CLLocationManager*)aManager 1.48 + didUpdateToLocation:(CLLocation *)aNewLocation 1.49 + fromLocation:(CLLocation *)aOldLocation; 1.50 +@end 1.51 + 1.52 +@implementation LocationDelegate 1.53 +- (id) init:(CoreLocationLocationProvider*) aProvider 1.54 +{ 1.55 + if (self = [super init]) { 1.56 + mProvider = aProvider; 1.57 + } 1.58 + 1.59 + return self; 1.60 +} 1.61 + 1.62 +- (void)locationManager:(CLLocationManager*)aManager 1.63 + didFailWithError:(NSError *)aError 1.64 +{ 1.65 + nsCOMPtr<nsIConsoleService> console = 1.66 + do_GetService(NS_CONSOLESERVICE_CONTRACTID); 1.67 + 1.68 + NS_ENSURE_TRUE_VOID(console); 1.69 + 1.70 + NSString* message = 1.71 + [@"Failed to acquire position: " stringByAppendingString: [aError localizedDescription]]; 1.72 + 1.73 + console->LogStringMessage(NS_ConvertUTF8toUTF16([message UTF8String]).get()); 1.74 + 1.75 + uint16_t err = nsIDOMGeoPositionError::POSITION_UNAVAILABLE; 1.76 + if ([aError code] == kCLErrorDenied) { 1.77 + err = nsIDOMGeoPositionError::PERMISSION_DENIED; 1.78 + } 1.79 + 1.80 + mProvider->NotifyError(err); 1.81 +} 1.82 + 1.83 +- (void)locationManager:(CLLocationManager*)aManager 1.84 + didUpdateToLocation:(CLLocation *)aNewLocation 1.85 + fromLocation:(CLLocation *)aOldLocation 1.86 +{ 1.87 + nsCOMPtr<nsIDOMGeoPosition> geoPosition = 1.88 + new nsGeoPosition(aNewLocation.coordinate.latitude, 1.89 + aNewLocation.coordinate.longitude, 1.90 + aNewLocation.altitude, 1.91 + aNewLocation.horizontalAccuracy, 1.92 + aNewLocation.verticalAccuracy, 1.93 + aNewLocation.course, 1.94 + aNewLocation.speed, 1.95 + PR_Now()); 1.96 + 1.97 + mProvider->Update(geoPosition); 1.98 +} 1.99 +@end 1.100 + 1.101 +class CoreLocationObjects { 1.102 +public: 1.103 + NS_METHOD Init(CoreLocationLocationProvider* aProvider) { 1.104 + mLocationManager = [[CLLocationManager alloc] init]; 1.105 + NS_ENSURE_TRUE(mLocationManager, NS_ERROR_NOT_AVAILABLE); 1.106 + 1.107 + mLocationDelegate = [[LocationDelegate alloc] init:aProvider]; 1.108 + NS_ENSURE_TRUE(mLocationDelegate, NS_ERROR_NOT_AVAILABLE); 1.109 + 1.110 + mLocationManager.desiredAccuracy = kDEFAULT_ACCURACY; 1.111 + mLocationManager.delegate = mLocationDelegate; 1.112 + 1.113 + return NS_OK; 1.114 + } 1.115 + 1.116 + ~CoreLocationObjects() { 1.117 + if (mLocationManager) { 1.118 + [mLocationManager release]; 1.119 + } 1.120 + 1.121 + if (mLocationDelegate) { 1.122 + [mLocationDelegate release]; 1.123 + } 1.124 + } 1.125 + 1.126 + LocationDelegate* mLocationDelegate; 1.127 + CLLocationManager* mLocationManager; 1.128 +}; 1.129 + 1.130 +NS_IMPL_ISUPPORTS(CoreLocationLocationProvider, nsIGeolocationProvider) 1.131 + 1.132 +CoreLocationLocationProvider::CoreLocationLocationProvider() 1.133 + : mCLObjects(nullptr) 1.134 +{ 1.135 +} 1.136 + 1.137 +NS_IMETHODIMP 1.138 +CoreLocationLocationProvider::Startup() 1.139 +{ 1.140 + if (!mCLObjects) { 1.141 + nsAutoPtr<CoreLocationObjects> clObjs(new CoreLocationObjects()); 1.142 + 1.143 + nsresult rv = clObjs->Init(this); 1.144 + NS_ENSURE_SUCCESS(rv, rv); 1.145 + 1.146 + mCLObjects = clObjs.forget(); 1.147 + } 1.148 + 1.149 + [mCLObjects->mLocationManager startUpdatingLocation]; 1.150 + return NS_OK; 1.151 +} 1.152 + 1.153 +NS_IMETHODIMP 1.154 +CoreLocationLocationProvider::Watch(nsIGeolocationUpdate* aCallback) 1.155 +{ 1.156 + if (mCallback) { 1.157 + return NS_OK; 1.158 + } 1.159 + 1.160 + mCallback = aCallback; 1.161 + return NS_OK; 1.162 +} 1.163 + 1.164 +NS_IMETHODIMP 1.165 +CoreLocationLocationProvider::Shutdown() 1.166 +{ 1.167 + NS_ENSURE_STATE(mCLObjects); 1.168 + 1.169 + [mCLObjects->mLocationManager stopUpdatingLocation]; 1.170 + 1.171 + delete mCLObjects; 1.172 + mCLObjects = nullptr; 1.173 + return NS_OK; 1.174 +} 1.175 + 1.176 +NS_IMETHODIMP 1.177 +CoreLocationLocationProvider::SetHighAccuracy(bool aEnable) 1.178 +{ 1.179 + NS_ENSURE_STATE(mCLObjects); 1.180 + 1.181 + mCLObjects->mLocationManager.desiredAccuracy = 1.182 + (aEnable ? kHIGH_ACCURACY : kDEFAULT_ACCURACY); 1.183 + 1.184 + return NS_OK; 1.185 +} 1.186 + 1.187 +void 1.188 +CoreLocationLocationProvider::Update(nsIDOMGeoPosition* aSomewhere) 1.189 +{ 1.190 + if (aSomewhere && mCallback) { 1.191 + mCallback->Update(aSomewhere); 1.192 + } 1.193 +} 1.194 + 1.195 +void 1.196 +CoreLocationLocationProvider::NotifyError(uint16_t aErrorCode) 1.197 +{ 1.198 + mCallback->NotifyError(aErrorCode); 1.199 +}