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

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

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

Powered by Google App Engine
This is Rietveld 408576698