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

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

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

Powered by Google App Engine
This is Rietveld 408576698