Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(325)

Side by Side Diff: content/browser/geolocation/core_location_data_provider_mac.mm

Issue 6597044: Revert 76228 - Move core pieces of geolocation from chrome to content.This is... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // This file contains the class definitions for the CoreLocation data provider
6 // class and the accompanying Objective C wrapper class. This data provider
7 // is used to allow the CoreLocation wrapper to run on the UI thread, since
8 // CLLocationManager's start and stop updating methods must be called from a
9 // thread with an active NSRunLoop. Currently only the UI thread appears to
10 // fill that requirement.
11
12 #include "content/browser/geolocation/core_location_data_provider_mac.h"
13
14 #include "base/logging.h"
15 #include "base/time.h"
16 #include "content/browser/geolocation/core_location_provider_mac.h"
17 #include "content/browser/geolocation/geolocation_provider.h"
18
19 // A few required declarations since the CoreLocation headers are not available
20 // with the Mac OS X 10.5 SDK.
21 // TODO(jorgevillatoro): Remove these declarations when we build against 10.6
22
23 // This idea was borrowed from wifi_data_provider_corewlan_mac.mm
24 typedef double CLLocationDegrees;
25 typedef double CLLocationAccuracy;
26 typedef double CLLocationSpeed;
27 typedef double CLLocationDirection;
28 typedef double CLLocationDistance;
29 typedef struct {
30 CLLocationDegrees latitude;
31 CLLocationDegrees longitude;
32 } CLLocationCoordinate2D;
33
34 enum {
35 kCLErrorLocationUnknown = 0,
36 kCLErrorDenied
37 };
38
39 @interface CLLocationManager : NSObject
40 + (BOOL)locationServicesEnabled;
41 @property(assign) id delegate;
42 - (void)startUpdatingLocation;
43 - (void)stopUpdatingLocation;
44 @end
45
46 @interface CLLocation : NSObject<NSCopying, NSCoding>
47 @property(readonly) CLLocationCoordinate2D coordinate;
48 @property(readonly) CLLocationDistance altitude;
49 @property(readonly) CLLocationAccuracy horizontalAccuracy;
50 @property(readonly) CLLocationAccuracy verticalAccuracy;
51 @property(readonly) CLLocationDirection course;
52 @property(readonly) CLLocationSpeed speed;
53 @end
54
55 @protocol CLLocationManagerDelegate
56 - (void)locationManager:(CLLocationManager*)manager
57 didUpdateToLocation:(CLLocation*)newLocation
58 fromLocation:(CLLocation*)oldLocation;
59 - (void)locationManager:(CLLocationManager*)manager
60 didFailWithError:(NSError*)error;
61 @end
62
63 // This wrapper class receives CLLocation objects from CoreLocation, converts
64 // them to Geoposition objects, and passes them on to the data provider class
65 // Note: This class has some specific threading requirements, inherited from
66 // CLLocationManager. The location manaager's start and stop updating
67 // methods must be called from a thread that has an active run loop (which
68 // seems to only be the UI thread)
69 @interface CoreLocationWrapperMac : NSObject<CLLocationManagerDelegate>
70 {
71 @private
72 NSBundle* bundle_;
73 Class locationManagerClass_;
74 id locationManager_;
75 CoreLocationDataProviderMac* dataProvider_;
76 }
77
78 - (id)initWithDataProvider:(CoreLocationDataProviderMac*)dataProvider;
79 - (void)dealloc;
80
81 // Can be called from any thread since it does not require an NSRunLoop. However
82 // it is not threadsafe to receive concurrent calls until after it's first
83 // successful call (to avoid |bundle_| being double initialized)
84 - (BOOL)locationDataAvailable;
85
86 // These should always be called from BrowserThread::UI
87 - (void)startLocation;
88 - (void)stopLocation;
89
90 // These should only be called by CLLocationManager
91 - (void)locationManager:(CLLocationManager*)manager
92 didUpdateToLocation:(CLLocation*)newLocation
93 fromLocation:(CLLocation*)oldLocation;
94 - (void)locationManager:(CLLocationManager*)manager
95 didFailWithError:(NSError*)error;
96 - (BOOL)loadCoreLocationBundle;
97
98 @end
99
100 @implementation CoreLocationWrapperMac
101
102 - (id)initWithDataProvider:(CoreLocationDataProviderMac*)dataProvider {
103 DCHECK(dataProvider);
104 dataProvider_ = dataProvider;
105 self = [super init];
106 return self;
107 }
108
109 - (void)dealloc {
110 [locationManager_ release];
111 [locationManagerClass_ release];
112 [bundle_ release];
113 [super dealloc];
114 }
115
116 // Load the bundle and check to see if location services are enabled
117 // but don't do anything else
118 - (BOOL)locationDataAvailable {
119 return ([self loadCoreLocationBundle] &&
120 [locationManagerClass_ locationServicesEnabled]);
121 }
122
123 - (void)startLocation {
124 if ([self locationDataAvailable]) {
125 if (!locationManager_) {
126 locationManager_ = [[locationManagerClass_ alloc] init];
127 [locationManager_ setDelegate:self];
128 }
129 [locationManager_ startUpdatingLocation];
130 }
131 }
132
133 - (void)stopLocation {
134 [locationManager_ stopUpdatingLocation];
135 }
136
137 - (void)locationManager:(CLLocationManager*)manager
138 didUpdateToLocation:(CLLocation*)newLocation
139 fromLocation:(CLLocation*)oldLocation {
140 Geoposition position;
141 position.latitude = [newLocation coordinate].latitude;
142 position.longitude = [newLocation coordinate].longitude;
143 position.altitude = [newLocation altitude];
144 position.accuracy = [newLocation horizontalAccuracy];
145 position.altitude_accuracy = [newLocation verticalAccuracy];
146 position.speed = [newLocation speed];
147 position.heading = [newLocation course];
148 position.timestamp = base::Time::Now();
149 position.error_code = Geoposition::ERROR_CODE_NONE;
150 dataProvider_->UpdatePosition(&position);
151 }
152
153 - (void)locationManager:(CLLocationManager*)manager
154 didFailWithError:(NSError*)error {
155 Geoposition position;
156 switch ([error code]) {
157 case kCLErrorLocationUnknown:
158 position.error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
159 break;
160 case kCLErrorDenied:
161 position.error_code = Geoposition::ERROR_CODE_PERMISSION_DENIED;
162 break;
163 default:
164 NOTREACHED() << "Unknown CoreLocation error: " << [error code];
165 return;
166 }
167 dataProvider_->UpdatePosition(&position);
168 }
169
170 - (BOOL)loadCoreLocationBundle {
171 if (!bundle_) {
172 bundle_ = [[NSBundle alloc]
173 initWithPath:@"/System/Library/Frameworks/CoreLocation.framework"];
174 if (!bundle_) {
175 DLOG(WARNING) << "Couldn't load CoreLocation Framework";
176 return NO;
177 }
178
179 locationManagerClass_ = [bundle_ classNamed:@"CLLocationManager"];
180 }
181
182 return YES;
183 }
184
185 @end
186
187 CoreLocationDataProviderMac::CoreLocationDataProviderMac() {
188 if (MessageLoop::current() !=
189 GeolocationProvider::GetInstance()->message_loop()) {
190 NOTREACHED() << "CoreLocation data provider must be created on "
191 "the Geolocation thread.";
192 }
193 provider_ = NULL;
194 wrapper_.reset([[CoreLocationWrapperMac alloc] initWithDataProvider:this]);
195 }
196
197 CoreLocationDataProviderMac::~CoreLocationDataProviderMac() {
198 }
199
200 // Returns true if the CoreLocation wrapper can load the framework and
201 // location services are enabled. The pointer argument will only be accessed
202 // in the origin thread.
203 bool CoreLocationDataProviderMac::
204 StartUpdating(CoreLocationProviderMac* provider) {
205 DCHECK(provider);
206 DCHECK(!provider_) << "StartUpdating called twice";
207 if (![wrapper_ locationDataAvailable]) return false;
208 provider_ = provider;
209 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
210 NewRunnableMethod(this, &CoreLocationDataProviderMac::StartUpdatingTask));
211 return true;
212 }
213
214 // Clears provider_ so that any leftover messages from CoreLocation get ignored
215 void CoreLocationDataProviderMac::StopUpdating() {
216 provider_ = NULL;
217 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
218 NewRunnableMethod(this,
219 &CoreLocationDataProviderMac::StopUpdatingTask));
220 }
221
222 void CoreLocationDataProviderMac::UpdatePosition(Geoposition *position) {
223 GeolocationProvider::GetInstance()->message_loop()->PostTask(FROM_HERE,
224 NewRunnableMethod(this,
225 &CoreLocationDataProviderMac::PositionUpdated,
226 *position));
227 }
228
229 // Runs in BrowserThread::UI
230 void CoreLocationDataProviderMac::StartUpdatingTask() {
231 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
232 [wrapper_ startLocation];
233 }
234
235 // Runs in BrowserThread::UI
236 void CoreLocationDataProviderMac::StopUpdatingTask() {
237 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
238 [wrapper_ stopLocation];
239 }
240
241 void CoreLocationDataProviderMac::PositionUpdated(Geoposition position) {
242 DCHECK(MessageLoop::current() ==
243 GeolocationProvider::GetInstance()->message_loop());
244 if (provider_)
245 provider_->SetPosition(&position);
246 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698