summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AUTHORS1
-rw-r--r--chrome/browser/geolocation/core_location_data_provider_mac.h53
-rw-r--r--chrome/browser/geolocation/core_location_data_provider_mac.mm241
-rw-r--r--chrome/browser/geolocation/core_location_provider_mac.h36
-rw-r--r--chrome/browser/geolocation/core_location_provider_mac.mm51
-rw-r--r--chrome/browser/geolocation/gps_location_provider_linux.h2
-rw-r--r--chrome/browser/geolocation/location_provider.cc2
-rw-r--r--chrome/chrome_browser.gypi4
-rw-r--r--chrome/common/chrome_switches.cc3
-rw-r--r--chrome/common/chrome_switches.h1
10 files changed, 392 insertions, 2 deletions
diff --git a/AUTHORS b/AUTHORS
index eef80e31..8a4a5b7 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -84,3 +84,4 @@ litl LLC
James Willcox <jwillcox@litl.com>
Shreyas VA <v.a.shreyas@gmail.com>
Steven Pennington <spenn@engr.uvic.ca>
+Jorge Villatoro <jorge@tomatocannon.com>
diff --git a/chrome/browser/geolocation/core_location_data_provider_mac.h b/chrome/browser/geolocation/core_location_data_provider_mac.h
new file mode 100644
index 0000000..8eafd3c
--- /dev/null
+++ b/chrome/browser/geolocation/core_location_data_provider_mac.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file declares a CoreLocation data provider class that allows the
+// CoreLocation framework to run on the UI thread, since the Geolocation API's
+// providers all live on the IO thread
+
+#ifndef CHROME_BROWSER_GEOLOCATION_CORE_LOCATION_DATA_PROVIDER_H_
+#define CHROME_BROWSER_GEOLOCATION_CORE_LOCATION_DATA_PROVIDER_H_
+#pragma once
+
+#include "base/ref_counted.h"
+#include "base/scoped_nsobject.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/common/geoposition.h"
+
+#import <Foundation/Foundation.h>
+
+class CoreLocationProviderMac;
+@class CoreLocationWrapperMac;
+
+// Data provider class that allows CoreLocation to run in Chrome's UI thread
+// while existing on any of Chrome's threads (in this case the IO thread)
+class CoreLocationDataProviderMac
+ : public base::RefCountedThreadSafe<CoreLocationDataProviderMac> {
+ public:
+ CoreLocationDataProviderMac();
+
+ bool StartUpdating(CoreLocationProviderMac* provider);
+ void StopUpdating();
+
+ void UpdatePosition(Geoposition *position);
+
+ protected:
+ friend class base::RefCountedThreadSafe<CoreLocationDataProviderMac>;
+ ~CoreLocationDataProviderMac();
+
+ private:
+ // These must execute in ChromeThread::UI
+ void StartUpdatingTask();
+ void StopUpdatingTask();
+ // This must execute in the origin thread (IO thread)
+ void PositionUpdated(Geoposition position);
+
+ // The wrapper class that supplies this class with position data
+ scoped_nsobject<CoreLocationWrapperMac> wrapper_;
+ // The LocationProviderBase class that should receive position data
+ CoreLocationProviderMac* provider_;
+ ChromeThread::ID origin_thread_id_;
+};
+
+#endif
diff --git a/chrome/browser/geolocation/core_location_data_provider_mac.mm b/chrome/browser/geolocation/core_location_data_provider_mac.mm
new file mode 100644
index 0000000..ae8e749
--- /dev/null
+++ b/chrome/browser/geolocation/core_location_data_provider_mac.mm
@@ -0,0 +1,241 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file contains the class definitions for the CoreLocation data provider
+// class and the accompanying Objective C wrapper class. This data provider
+// is used to allow the CoreLocation wrapper to run on the UI thread, since
+// CLLocationManager's start and stop updating methods must be called from a
+// thread with an active NSRunLoop. Currently only the UI thread appears to
+// fill that requirement.
+
+#include "chrome/browser/geolocation/core_location_data_provider_mac.h"
+#include "chrome/browser/geolocation/core_location_provider_mac.h"
+#include "base/logging.h"
+#include "base/time.h"
+
+// A few required declarations since the CoreLocation headers are not available
+// with the Mac OS X 10.5 SDK.
+// TODO(jorgevillatoro): Remove these declarations when we build against 10.6
+
+// This idea was borrowed from wifi_data_provider_corewlan_mac.mm
+typedef double CLLocationDegrees;
+typedef double CLLocationAccuracy;
+typedef double CLLocationSpeed;
+typedef double CLLocationDirection;
+typedef double CLLocationDistance;
+typedef struct {
+ CLLocationDegrees latitude;
+ CLLocationDegrees longitude;
+} CLLocationCoordinate2D;
+
+enum {
+ kCLErrorLocationUnknown = 0,
+ kCLErrorDenied
+};
+
+@interface CLLocationManager : NSObject
++ (BOOL)locationServicesEnabled;
+@property(assign) id delegate;
+- (void)startUpdatingLocation;
+- (void)stopUpdatingLocation;
+@end
+
+@interface CLLocation : NSObject <NSCopying, NSCoding>
+@property(readonly) CLLocationCoordinate2D coordinate;
+@property(readonly) CLLocationDistance altitude;
+@property(readonly) CLLocationAccuracy horizontalAccuracy;
+@property(readonly) CLLocationAccuracy verticalAccuracy;
+@property(readonly) CLLocationDirection course;
+@property(readonly) CLLocationSpeed speed;
+@end
+
+@protocol CLLocationManagerDelegate
+- (void)locationManager:(CLLocationManager*)manager
+ didUpdateToLocation:(CLLocation*)newLocation
+ fromLocation:(CLLocation*)oldLocation;
+- (void)locationManager:(CLLocationManager*)manager
+ didFailWithError:(NSError*)error;
+@end
+
+// This wrapper class receives CLLocation objects from CoreLocation, converts
+// them to Geoposition objects, and passes them on to the data provider class
+// Note: This class has some specific threading requirements, inherited from
+// CLLocationManager. The location manaager's start and stop updating
+// methods must be called from a thread that has an active run loop (which
+// seems to only be the UI thread)
+@interface CoreLocationWrapperMac : NSObject <CLLocationManagerDelegate>
+{
+@private
+ NSBundle* bundle_;
+ Class locationManagerClass_;
+ id locationManager_;
+ CoreLocationDataProviderMac* dataProvider_;
+}
+
+- (id)initWithDataProvider:(CoreLocationDataProviderMac*)dataProvider;
+- (void)dealloc;
+
+// Can be called from any thread since it does not require an NSRunLoop. However
+// it is not threadsafe to receive concurrent calls until after it's first
+// successful call (to avoid |bundle_| being double initialized)
+- (BOOL)locationDataAvailable;
+
+// These should always be called from ChromeThread::UI
+- (void)startLocation;
+- (void)stopLocation;
+
+// These should only be called by CLLocationManager
+- (void)locationManager:(CLLocationManager*)manager
+ didUpdateToLocation:(CLLocation*)newLocation
+ fromLocation:(CLLocation*)oldLocation;
+- (void)locationManager:(CLLocationManager*)manager
+ didFailWithError:(NSError*)error;
+- (BOOL)loadCoreLocationBundle;
+
+@end
+
+@implementation CoreLocationWrapperMac
+
+- (id)initWithDataProvider:(CoreLocationDataProviderMac*)dataProvider {
+ DCHECK(dataProvider);
+ dataProvider_ = dataProvider;
+ self = [super init];
+ return self;
+}
+
+- (void)dealloc {
+ [locationManager_ release];
+ [locationManagerClass_ release];
+ [bundle_ release];
+ [super dealloc];
+}
+
+// Load the bundle and check to see if location services are enabled
+// but don't do anything else
+- (BOOL)locationDataAvailable {
+ return ([self loadCoreLocationBundle] &&
+ [locationManagerClass_ locationServicesEnabled]);
+}
+
+- (void)startLocation {
+ if([self locationDataAvailable]) {
+ if(!locationManager_) {
+ locationManager_ = [[locationManagerClass_ alloc] init];
+ [locationManager_ setDelegate:self];
+ }
+ [locationManager_ startUpdatingLocation];
+ }
+}
+
+- (void)stopLocation {
+ [locationManager_ stopUpdatingLocation];
+}
+
+- (void)locationManager:(CLLocationManager*)manager
+ didUpdateToLocation:(CLLocation*)newLocation
+ fromLocation:(CLLocation*)oldLocation {
+ Geoposition position;
+ position.latitude = [newLocation coordinate].latitude;
+ position.longitude = [newLocation coordinate].longitude;
+ position.altitude = [newLocation altitude];
+ position.accuracy = [newLocation horizontalAccuracy];
+ position.altitude_accuracy = [newLocation verticalAccuracy];
+ position.speed = [newLocation speed];
+ position.heading = [newLocation course];
+ position.timestamp = base::Time::Now();
+ position.error_code = Geoposition::ERROR_CODE_NONE;
+ dataProvider_->UpdatePosition(&position);
+}
+
+- (void)locationManager:(CLLocationManager*)manager
+ didFailWithError:(NSError*)error {
+ Geoposition position;
+ switch([error code]) {
+ case kCLErrorLocationUnknown:
+ position.error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
+ break;
+ case kCLErrorDenied:
+ position.error_code = Geoposition::ERROR_CODE_PERMISSION_DENIED;
+ break;
+ default:
+ NOTREACHED() << "Unknown CoreLocation error: " << [error code];
+ return;
+ }
+ dataProvider_->UpdatePosition(&position);
+}
+
+- (BOOL)loadCoreLocationBundle {
+ if(!bundle_) {
+ bundle_ = [[NSBundle alloc]
+ initWithPath:@"/System/Library/Frameworks/CoreLocation.framework"];
+ if(!bundle_) {
+ DLOG(WARNING) << "Couldn't load CoreLocation Framework";
+ return NO;
+ }
+
+ locationManagerClass_ = [bundle_ classNamed:@"CLLocationManager"];
+ }
+
+ return YES;
+}
+
+@end
+
+CoreLocationDataProviderMac::CoreLocationDataProviderMac() {
+ if(!ChromeThread::GetCurrentThreadIdentifier(&origin_thread_id_))
+ NOTREACHED() <<
+ "CoreLocation data provider must be created in a valid ChromeThread.";
+ provider_ = NULL;
+ wrapper_.reset([[CoreLocationWrapperMac alloc] initWithDataProvider:this]);
+}
+
+CoreLocationDataProviderMac::~CoreLocationDataProviderMac() {
+}
+
+// Returns true if the CoreLocation wrapper can load the framework and
+// location services are enabled. The pointer argument will only be accessed
+// in the origin thread.
+bool CoreLocationDataProviderMac::
+ StartUpdating(CoreLocationProviderMac* provider) {
+ DCHECK(provider);
+ DCHECK(!provider_) << "StartUpdating called twice";
+ if(![wrapper_ locationDataAvailable]) return false;
+ provider_ = provider;
+ ChromeThread::PostTask(ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &CoreLocationDataProviderMac::StartUpdatingTask));
+ return true;
+}
+
+// Clears provider_ so that any leftover messages from CoreLocation get ignored
+void CoreLocationDataProviderMac::StopUpdating() {
+ provider_ = NULL;
+ ChromeThread::PostTask(ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(this,
+ &CoreLocationDataProviderMac::StopUpdatingTask));
+}
+
+void CoreLocationDataProviderMac::UpdatePosition(Geoposition *position) {
+ ChromeThread::PostTask(origin_thread_id_, FROM_HERE,
+ NewRunnableMethod(this,
+ &CoreLocationDataProviderMac::PositionUpdated,
+ *position));
+}
+
+// Runs in ChromeThread::UI
+void CoreLocationDataProviderMac::StartUpdatingTask() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ [wrapper_ startLocation];
+}
+
+// Runs in ChromeThread::UI
+void CoreLocationDataProviderMac::StopUpdatingTask() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ [wrapper_ stopLocation];
+}
+
+void CoreLocationDataProviderMac::PositionUpdated(Geoposition position) {
+ DCHECK(ChromeThread::CurrentlyOn(origin_thread_id_));
+ if(provider_)
+ provider_->SetPosition(&position);
+}
diff --git a/chrome/browser/geolocation/core_location_provider_mac.h b/chrome/browser/geolocation/core_location_provider_mac.h
new file mode 100644
index 0000000..0d7d7470
--- /dev/null
+++ b/chrome/browser/geolocation/core_location_provider_mac.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file declares a CoreLocation provider that runs on Mac OS X (10.6).
+// Public for testing only - for normal usage this header should not be
+// required, as location_provider.h declares the needed factory function.
+
+#ifndef CHROME_BROWSER_GEOLOCATION_CORE_LOCATION_PROVIDER_MAC_H_
+#define CHROME_BROWSER_GEOLOCATION_CORE_LOCATION_PROVIDER_MAC_H_
+#pragma once
+
+#include "chrome/browser/geolocation/location_provider.h"
+#include "chrome/common/geoposition.h"
+
+class CoreLocationDataProviderMac;
+
+class CoreLocationProviderMac : public LocationProviderBase {
+ public:
+ explicit CoreLocationProviderMac();
+ ~CoreLocationProviderMac();
+
+ // LocationProvider
+ virtual bool StartProvider(bool high_accuracy);
+ virtual void StopProvider();
+ virtual void GetPosition(Geoposition* position);
+
+ // Receives new positions and calls UpdateListeners
+ void SetPosition(Geoposition* position);
+
+ private:
+ CoreLocationDataProviderMac* data_provider_;
+ Geoposition position_;
+};
+
+#endif
diff --git a/chrome/browser/geolocation/core_location_provider_mac.mm b/chrome/browser/geolocation/core_location_provider_mac.mm
new file mode 100644
index 0000000..e410426
--- /dev/null
+++ b/chrome/browser/geolocation/core_location_provider_mac.mm
@@ -0,0 +1,51 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/geolocation/core_location_provider_mac.h"
+#include "chrome/browser/geolocation/core_location_data_provider_mac.h"
+
+#include "base/logging.h"
+#include "base/command_line.h"
+#include "chrome/common/chrome_switches.h"
+
+CoreLocationProviderMac::CoreLocationProviderMac() {
+ data_provider_ = new CoreLocationDataProviderMac();
+ data_provider_->AddRef();
+}
+
+CoreLocationProviderMac::~CoreLocationProviderMac() {
+ data_provider_->StopUpdating();
+ data_provider_->Release();
+}
+
+bool CoreLocationProviderMac::StartProvider(bool high_accuracy) {
+ data_provider_->StartUpdating(this);
+ return true;
+}
+
+void CoreLocationProviderMac::StopProvider() {
+ data_provider_->StopUpdating();
+}
+
+void CoreLocationProviderMac::GetPosition(Geoposition* position) {
+ DCHECK(position);
+ *position = position_;
+ DCHECK(position->IsInitialized());
+}
+
+void CoreLocationProviderMac::SetPosition(Geoposition* position) {
+ DCHECK(position);
+ position_ = *position;
+ DCHECK(position->IsInitialized());
+
+ UpdateListeners();
+}
+
+LocationProviderBase* NewSystemLocationProvider() {
+ if(CommandLine::ForCurrentProcess()
+ ->HasSwitch(switches::kEnableCoreLocation)) {
+ return new CoreLocationProviderMac;
+ }
+ return NULL;
+}
diff --git a/chrome/browser/geolocation/gps_location_provider_linux.h b/chrome/browser/geolocation/gps_location_provider_linux.h
index 68fff23..a06ccbd2 100644
--- a/chrome/browser/geolocation/gps_location_provider_linux.h
+++ b/chrome/browser/geolocation/gps_location_provider_linux.h
@@ -27,7 +27,7 @@ class GpsLocationProviderLinux : public LocationProviderBase {
public:
typedef LibGps* (*LibGpsFactory)();
// |factory| will be used to create the gpsd client library wrapper. (Note
- // NewGpsLocationProvider() will use the default factory).
+ // NewSystemLocationProvider() will use the default factory).
explicit GpsLocationProviderLinux(LibGpsFactory libgps_factory);
virtual ~GpsLocationProviderLinux();
diff --git a/chrome/browser/geolocation/location_provider.cc b/chrome/browser/geolocation/location_provider.cc
index ecd066e..7a868d7 100644
--- a/chrome/browser/geolocation/location_provider.cc
+++ b/chrome/browser/geolocation/location_provider.cc
@@ -56,7 +56,7 @@ void LocationProviderBase::UpdateListeners() {
}
}
-#if !defined(OS_LINUX) && !defined(OS_WIN)
+#if !defined(OS_LINUX) && !defined(OS_MACOSX) && !defined(OS_WIN)
LocationProviderBase* NewSystemLocationProvider() {
return NULL;
}
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 3a6884c..b0640b2 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1540,6 +1540,10 @@
'browser/gears_integration.h',
'browser/geolocation/access_token_store.cc',
'browser/geolocation/access_token_store.h',
+ 'browser/geolocation/core_location_data_provider_mac.h',
+ 'browser/geolocation/core_location_data_provider_mac.mm',
+ 'browser/geolocation/core_location_provider_mac.h',
+ 'browser/geolocation/core_location_provider_mac.mm',
'browser/geolocation/device_data_provider.h',
'browser/geolocation/empty_device_data_provider.cc',
'browser/geolocation/empty_device_data_provider.h',
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 9d38d74..ba036a4 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -393,6 +393,9 @@ const char kEnableContentPrefetch[] = "enable-content-prefetch";
// Enables the cookie prompt.
const char kEnableCookiePrompt[] = "enable-cookie-prompt";
+// Enable CoreLocation geoposition data provider
+const char kEnableCoreLocation[] = "enable-core-location";
+
// Enables device motion events.
const char kEnableDeviceMotion[] = "enable-device-motion";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index bcaacfe..efc74ec 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -122,6 +122,7 @@ extern const char kEnableCloudPrint[];
extern const char kEnableConnectBackupJobs[];
extern const char kEnableContentPrefetch[];
extern const char kEnableCookiePrompt[];
+extern const char kEnableCoreLocation[];
extern const char kEnableDeviceMotion[];
extern const char kEnableDNSSECCerts[];
extern const char kEnableExperimentalExtensionApis[];