dom/system/mac/CoreLocationLocationProvider.mm

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:ee2b1620b980
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "nsCOMPtr.h"
8 #include "nsGeoPosition.h"
9 #include "nsIConsoleService.h"
10 #include "nsServiceManagerUtils.h"
11 #include "nsIDOMGeoPositionError.h"
12 #include "CoreLocationLocationProvider.h"
13 #include "nsCocoaFeatures.h"
14 #include "prtime.h"
15
16 #include <CoreLocation/CLError.h>
17 #include <CoreLocation/CLLocation.h>
18 #include <CoreLocation/CLLocationManager.h>
19 #include <CoreLocation/CLLocationManagerDelegate.h>
20
21 #include <objc/objc.h>
22 #include <objc/objc-runtime.h>
23
24 #include "nsObjCExceptions.h"
25
26 using namespace mozilla;
27
28 static const CLLocationAccuracy kHIGH_ACCURACY = kCLLocationAccuracyBest;
29 static const CLLocationAccuracy kDEFAULT_ACCURACY = kCLLocationAccuracyNearestTenMeters;
30
31 @interface LocationDelegate : NSObject <CLLocationManagerDelegate>
32 {
33 CoreLocationLocationProvider* mProvider;
34 }
35
36 - (id)init:(CoreLocationLocationProvider*)aProvider;
37 - (void)locationManager:(CLLocationManager*)aManager
38 didFailWithError:(NSError *)aError;
39
40 /* XXX (ggp) didUpdateToLocation is supposedly deprecated in favor of
41 * locationManager:didUpdateLocations, which is undocumented and didn't seem to
42 * work for me. This should be changed in the future, though.
43 */
44 - (void)locationManager:(CLLocationManager*)aManager
45 didUpdateToLocation:(CLLocation *)aNewLocation
46 fromLocation:(CLLocation *)aOldLocation;
47 @end
48
49 @implementation LocationDelegate
50 - (id) init:(CoreLocationLocationProvider*) aProvider
51 {
52 if (self = [super init]) {
53 mProvider = aProvider;
54 }
55
56 return self;
57 }
58
59 - (void)locationManager:(CLLocationManager*)aManager
60 didFailWithError:(NSError *)aError
61 {
62 nsCOMPtr<nsIConsoleService> console =
63 do_GetService(NS_CONSOLESERVICE_CONTRACTID);
64
65 NS_ENSURE_TRUE_VOID(console);
66
67 NSString* message =
68 [@"Failed to acquire position: " stringByAppendingString: [aError localizedDescription]];
69
70 console->LogStringMessage(NS_ConvertUTF8toUTF16([message UTF8String]).get());
71
72 uint16_t err = nsIDOMGeoPositionError::POSITION_UNAVAILABLE;
73 if ([aError code] == kCLErrorDenied) {
74 err = nsIDOMGeoPositionError::PERMISSION_DENIED;
75 }
76
77 mProvider->NotifyError(err);
78 }
79
80 - (void)locationManager:(CLLocationManager*)aManager
81 didUpdateToLocation:(CLLocation *)aNewLocation
82 fromLocation:(CLLocation *)aOldLocation
83 {
84 nsCOMPtr<nsIDOMGeoPosition> geoPosition =
85 new nsGeoPosition(aNewLocation.coordinate.latitude,
86 aNewLocation.coordinate.longitude,
87 aNewLocation.altitude,
88 aNewLocation.horizontalAccuracy,
89 aNewLocation.verticalAccuracy,
90 aNewLocation.course,
91 aNewLocation.speed,
92 PR_Now());
93
94 mProvider->Update(geoPosition);
95 }
96 @end
97
98 class CoreLocationObjects {
99 public:
100 NS_METHOD Init(CoreLocationLocationProvider* aProvider) {
101 mLocationManager = [[CLLocationManager alloc] init];
102 NS_ENSURE_TRUE(mLocationManager, NS_ERROR_NOT_AVAILABLE);
103
104 mLocationDelegate = [[LocationDelegate alloc] init:aProvider];
105 NS_ENSURE_TRUE(mLocationDelegate, NS_ERROR_NOT_AVAILABLE);
106
107 mLocationManager.desiredAccuracy = kDEFAULT_ACCURACY;
108 mLocationManager.delegate = mLocationDelegate;
109
110 return NS_OK;
111 }
112
113 ~CoreLocationObjects() {
114 if (mLocationManager) {
115 [mLocationManager release];
116 }
117
118 if (mLocationDelegate) {
119 [mLocationDelegate release];
120 }
121 }
122
123 LocationDelegate* mLocationDelegate;
124 CLLocationManager* mLocationManager;
125 };
126
127 NS_IMPL_ISUPPORTS(CoreLocationLocationProvider, nsIGeolocationProvider)
128
129 CoreLocationLocationProvider::CoreLocationLocationProvider()
130 : mCLObjects(nullptr)
131 {
132 }
133
134 NS_IMETHODIMP
135 CoreLocationLocationProvider::Startup()
136 {
137 if (!mCLObjects) {
138 nsAutoPtr<CoreLocationObjects> clObjs(new CoreLocationObjects());
139
140 nsresult rv = clObjs->Init(this);
141 NS_ENSURE_SUCCESS(rv, rv);
142
143 mCLObjects = clObjs.forget();
144 }
145
146 [mCLObjects->mLocationManager startUpdatingLocation];
147 return NS_OK;
148 }
149
150 NS_IMETHODIMP
151 CoreLocationLocationProvider::Watch(nsIGeolocationUpdate* aCallback)
152 {
153 if (mCallback) {
154 return NS_OK;
155 }
156
157 mCallback = aCallback;
158 return NS_OK;
159 }
160
161 NS_IMETHODIMP
162 CoreLocationLocationProvider::Shutdown()
163 {
164 NS_ENSURE_STATE(mCLObjects);
165
166 [mCLObjects->mLocationManager stopUpdatingLocation];
167
168 delete mCLObjects;
169 mCLObjects = nullptr;
170 return NS_OK;
171 }
172
173 NS_IMETHODIMP
174 CoreLocationLocationProvider::SetHighAccuracy(bool aEnable)
175 {
176 NS_ENSURE_STATE(mCLObjects);
177
178 mCLObjects->mLocationManager.desiredAccuracy =
179 (aEnable ? kHIGH_ACCURACY : kDEFAULT_ACCURACY);
180
181 return NS_OK;
182 }
183
184 void
185 CoreLocationLocationProvider::Update(nsIDOMGeoPosition* aSomewhere)
186 {
187 if (aSomewhere && mCallback) {
188 mCallback->Update(aSomewhere);
189 }
190 }
191
192 void
193 CoreLocationLocationProvider::NotifyError(uint16_t aErrorCode)
194 {
195 mCallback->NotifyError(aErrorCode);
196 }

mercurial