diff options
author | joth@chromium.org <joth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-27 15:26:18 +0000 |
---|---|---|
committer | joth@chromium.org <joth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-27 15:26:18 +0000 |
commit | a2fd492a14c619f899623a0e0e05f5dd61751b6b (patch) | |
tree | a9bd46a7fe51f04ae6de7b53114ab892a064883e | |
parent | 300e4ea2cb2bfdb316cc0670cc1de8bffffe9d85 (diff) | |
download | chromium_src-a2fd492a14c619f899623a0e0e05f5dd61751b6b.zip chromium_src-a2fd492a14c619f899623a0e0e05f5dd61751b6b.tar.gz chromium_src-a2fd492a14c619f899623a0e0e05f5dd61751b6b.tar.bz2 |
First cut at GPS support in chrome linux
Uses libgps / gpsd to get gps fixes. Modified the location arbitrator to use GPS instead of network location provider.
Current version requires manual code edit to enable (ENABLE_LIBGPS_LOCATION_PROVIDER) See http://docs.google.com/View?id=dfbnm49n_1g8ktswhr for demo instructions (work in progress)
BUG=43868
TEST=Built with ENABLE_LIBGPS_LOCATION_PROVIDER and used gpsd's gpsfake script (see linked doc above)
Review URL: http://codereview.chromium.org/2032010
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@48393 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/DEPS | 1 | ||||
-rw-r--r-- | chrome/browser/geolocation/gps_location_provider_linux.cc | 122 | ||||
-rw-r--r-- | chrome/browser/geolocation/gps_location_provider_linux.h | 55 | ||||
-rw-r--r-- | chrome/browser/geolocation/libgps_2_38_wrapper_linux.cc | 72 | ||||
-rw-r--r-- | chrome/browser/geolocation/libgps_2_94_wrapper_linux.cc | 50 | ||||
-rw-r--r-- | chrome/browser/geolocation/libgps_wrapper_linux.cc | 202 | ||||
-rw-r--r-- | chrome/browser/geolocation/libgps_wrapper_linux.h | 115 | ||||
-rw-r--r-- | chrome/browser/geolocation/location_arbitrator.cc | 13 | ||||
-rw-r--r-- | chrome/browser/geolocation/location_provider.cc | 4 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 6 |
10 files changed, 634 insertions, 6 deletions
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS index 4035947..7120cb8 100644 --- a/chrome/browser/DEPS +++ b/chrome/browser/DEPS @@ -22,6 +22,7 @@ include_rules = [ "+media/base", "+third_party/cros", "+third_party/expat", + "+third_party/gpsd", "+third_party/sqlite", "+third_party/libevent", # For the remote V8 debugging server "+third_party/cld", diff --git a/chrome/browser/geolocation/gps_location_provider_linux.cc b/chrome/browser/geolocation/gps_location_provider_linux.cc new file mode 100644 index 0000000..64d56e8 --- /dev/null +++ b/chrome/browser/geolocation/gps_location_provider_linux.cc @@ -0,0 +1,122 @@ +// 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/gps_location_provider_linux.h" + +#include <algorithm> +#include <cmath> +#include "base/compiler_specific.h" +#include "base/logging.h" +#include "base/message_loop.h" +#include "chrome/browser/geolocation/libgps_wrapper_linux.h" + +// Uncomment this to force the arbitrator to use GPS instead of network +// location provider. Note this will break unit tests! +// TODO(joth): remove when arbitration is implemented. +//#define ENABLE_LIBGPS_LOCATION_PROVIDER 1 + +namespace { +// As per http://gpsd.berlios.de/performance.html#id374524, poll twice per sec. +const int kPollPeriodMovingMillis = 500; +// Poll less frequently whilst stationary. +const int kPollPeriodStationaryMillis = kPollPeriodMovingMillis * 3; +// GPS reading must differ by more than this amount to be considered movement. +const int kMovementThresholdMeters = 20; + +// This algorithm is reused from the corresponding code in the gears project. +// The arbitrary delta is decreased (gears used 100 meters); if we need to +// decrease it any further we'll likely want to do some smarter filtering to +// remove GPS location jitter noise. +bool PositionsDifferSiginificantly(const Geoposition& position_1, + const Geoposition& position_2) { + const bool pos_1_valid = position_1.IsValidFix(); + if (pos_1_valid != position_2.IsValidFix()) + return true; + if (!pos_1_valid) { + DCHECK(!position_2.IsValidFix()); + return false; + } + double delta = std::sqrt( + std::pow(std::fabs(position_1.latitude - position_2.latitude), 2) + + std::pow(std::fabs(position_1.longitude - position_2.longitude), 2)); + // Convert to meters. 1 minute of arc of latitude (or longitude at the + // equator) is 1 nautical mile or 1852m. + delta *= 60 * 1852; + return delta > kMovementThresholdMeters; +} +} // namespace + +GpsLocationProviderLinux::GpsLocationProviderLinux(LibGpsFactory libgps_factory) + : libgps_factory_(libgps_factory), + ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)) { + DCHECK(libgps_factory_); +} + +GpsLocationProviderLinux::~GpsLocationProviderLinux() { +} + +bool GpsLocationProviderLinux::StartProvider() { + position_.error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; + gps_.reset(libgps_factory_()); + if (gps_ == NULL) { + LOG(WARNING) << "libgps.so could not be loaded"; + // TODO(joth): return false once GeolocationArbitratorImpl can cope with it. + return true; + } + if (!gps_->Start(&error_msg_)) { + LOG(WARNING) << "Couldn't start GPS provider: " << error_msg_; + // TODO(joth): return false once GeolocationArbitratorImpl can cope with it. + return true; + } + ScheduleNextGpsPoll(0); + return true; +} + +void GpsLocationProviderLinux::GetPosition(Geoposition* position) { + DCHECK(position); + *position = position_; + DCHECK(position->IsInitialized()); +} + +void GpsLocationProviderLinux::UpdatePosition() { + ScheduleNextGpsPoll(0); +} + +void GpsLocationProviderLinux::OnPermissionGranted( + const GURL& requesting_frame) { +} + +void GpsLocationProviderLinux::DoGpsPollTask() { + if (!gps_->Poll()) { + gps_->Stop(); + return; + } + Geoposition new_position; + gps_->GetPosition(&new_position); + DCHECK(new_position.IsInitialized()); + const bool differ = PositionsDifferSiginificantly(position_, new_position); + ScheduleNextGpsPoll(differ ? kPollPeriodMovingMillis : + kPollPeriodStationaryMillis); + if (differ || new_position.error_code != Geoposition::ERROR_CODE_NONE) { + // Update if the new location is interesting or we have an error to report. + position_ = new_position; + UpdateListeners(); + } +} + +void GpsLocationProviderLinux::ScheduleNextGpsPoll(int interval) { + task_factory_.RevokeAll(); + MessageLoop::current()->PostDelayedTask( + FROM_HERE, + task_factory_.NewRunnableMethod(&GpsLocationProviderLinux::DoGpsPollTask), + interval); +} + +LocationProviderBase* NewGpsLocationProvider() { +#ifdef ENABLE_LIBGPS_LOCATION_PROVIDER + return new GpsLocationProviderLinux(LibGps::New); +#else + return NULL; +#endif +} diff --git a/chrome/browser/geolocation/gps_location_provider_linux.h b/chrome/browser/geolocation/gps_location_provider_linux.h new file mode 100644 index 0000000..816062e --- /dev/null +++ b/chrome/browser/geolocation/gps_location_provider_linux.h @@ -0,0 +1,55 @@ +// 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 GPS providers that run on linux. Currently, just uses +// the libgps (gpsd) API. 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_GPS_LOCATION_PROVIDER_LINUX_H_ +#define CHROME_BROWSER_GEOLOCATION_GPS_LOCATION_PROVIDER_LINUX_H_ + +#include "chrome/browser/geolocation/location_provider.h" + +#include "base/scoped_ptr.h" +#include "base/task.h" + +class LibGps; + +// Location provider for Linux, that uses libgps/gpsd to obtain position fixes. +// TODO(joth): Currently this runs entirely in the client thread (i.e. Chrome's +// IO thread). As the older libgps API is not designed to support polling, +// there's a chance it could block, so better move this into its own worker +// thread. +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). + GpsLocationProviderLinux(LibGpsFactory libgps_factory); + virtual ~GpsLocationProviderLinux(); + + // LocationProvider + virtual bool StartProvider(); + virtual void GetPosition(Geoposition* position); + virtual void UpdatePosition(); + virtual void OnPermissionGranted(const GURL& requesting_frame); + + private: + // Task which run in the child thread. + void DoGpsPollTask(); + + // Will schedule a poll; i.e. enqueue DoGpsPollTask deferred task. + void ScheduleNextGpsPoll(int interval); + + const LibGpsFactory libgps_factory_; + scoped_ptr<LibGps> gps_; + std::string error_msg_; + Geoposition position_; + + // Holder for the tasks which run on the thread; takes care of cleanup. + ScopedRunnableMethodFactory<GpsLocationProviderLinux> task_factory_; +}; + +#endif // CHROME_BROWSER_GEOLOCATION_GPS_LOCATION_PROVIDER_LINUX_H_ diff --git a/chrome/browser/geolocation/libgps_2_38_wrapper_linux.cc b/chrome/browser/geolocation/libgps_2_38_wrapper_linux.cc new file mode 100644 index 0000000..075df3e --- /dev/null +++ b/chrome/browser/geolocation/libgps_2_38_wrapper_linux.cc @@ -0,0 +1,72 @@ +// 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. + +// Defines a variant of libgps wrapper for use with the 2.38 release of the API. + +#include "chrome/browser/geolocation/libgps_wrapper_linux.h" + +// This lot needed for Poll() +#include <sys/socket.h> +#include <sys/time.h> + +#include "base/logging.h" +#include "chrome/common/geoposition.h" +#include "third_party/gpsd/release-2.38/gps.h" + +class LibGpsV238 : public LibGps { + public: + explicit LibGpsV238(LibGpsLibraryLoader* dl_wrapper) : LibGps(dl_wrapper) {} + + // LibGps + virtual bool StartStreaming() { + return library().query("w+x\n") == 0; + } + virtual bool DataWaiting(bool* ok) { + // Unfortunately the 2.38 API has no public method for non-blocking test + // for new data arrived, so we must contrive our own by doing a select() on + // the underlying struct's socket fd. + DCHECK(ok); + *ok = true; + fd_set fds; + struct timeval timeout = {0}; + int fd = library().data().gps_fd; + + FD_ZERO(&fds); + FD_SET(fd, &fds); + + int ret = select(fd + 1, &fds, NULL, NULL, &timeout); + if (ret == -1) { + LOG(INFO) << "libgps socket select failed: " << ret; + *ok = false; + return false; + } + DCHECK_EQ(!!ret, !!FD_ISSET(fd, &fds)); + return ret; + } + virtual bool GetPositionIfFixed(Geoposition* position) { + // This function is duplicated between the library versions, however it + // cannot be shared as each one must be strictly compiled against the + // corresponding version of gps.h. + DCHECK(position); + const gps_data_t& gps_data = library().data(); + if (gps_data.status == STATUS_NO_FIX) + return false; + position->timestamp = base::Time::FromDoubleT(gps_data.fix.time); + position->latitude = gps_data.fix.latitude; + position->longitude = gps_data.fix.longitude; + position->accuracy = library().data().fix.eph; + position->altitude = gps_data.fix.altitude; + position->altitude_accuracy = gps_data.fix.epv; + position->heading = gps_data.fix.track; + position->speed = gps_data.fix.speed; + return true; + } + + private: + DISALLOW_COPY_AND_ASSIGN(LibGpsV238); +}; + +LibGps* LibGps::NewV238(LibGpsLibraryLoader* dl_wrapper) { + return new LibGpsV238(dl_wrapper); +} diff --git a/chrome/browser/geolocation/libgps_2_94_wrapper_linux.cc b/chrome/browser/geolocation/libgps_2_94_wrapper_linux.cc new file mode 100644 index 0000000..9c9de30 --- /dev/null +++ b/chrome/browser/geolocation/libgps_2_94_wrapper_linux.cc @@ -0,0 +1,50 @@ +// 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. + +// Defines a variant of libgps wrapper for use with the 2.94 release of the API. + +#include "chrome/browser/geolocation/libgps_wrapper_linux.h" + +#include "base/logging.h" +#include "chrome/common/geoposition.h" +#include "third_party/gpsd/release-2.94/gps.h" + +class LibGpsV294 : public LibGps { + public: + explicit LibGpsV294(LibGpsLibraryLoader* dl_wrapper) : LibGps(dl_wrapper) {} + + // LibGps + virtual bool StartStreaming() { + return library().stream(WATCH_ENABLE) == 0; + } + virtual bool DataWaiting(bool* ok) { + *ok = true; + return library().waiting(); + } + virtual bool GetPositionIfFixed(Geoposition* position) { + // This function is duplicated between the library versions, however it + // cannot be shared as each one must be strictly compiled against the + // corresponding version of gps.h. + DCHECK(position); + const gps_data_t& gps_data = library().data(); + if (gps_data.status == STATUS_NO_FIX) + return false; + position->timestamp = base::Time::FromDoubleT(gps_data.fix.time); + position->latitude = gps_data.fix.latitude; + position->longitude = gps_data.fix.longitude; + position->accuracy = std::max(gps_data.fix.epx, gps_data.fix.epy); + position->altitude = gps_data.fix.altitude; + position->altitude_accuracy = gps_data.fix.epv; + position->heading = gps_data.fix.track; + position->speed = gps_data.fix.speed; + return true; + } + + private: + DISALLOW_COPY_AND_ASSIGN(LibGpsV294); +}; + +LibGps* LibGps::NewV294(LibGpsLibraryLoader* dl_wrapper) { + return new LibGpsV294(dl_wrapper); +} diff --git a/chrome/browser/geolocation/libgps_wrapper_linux.cc b/chrome/browser/geolocation/libgps_wrapper_linux.cc new file mode 100644 index 0000000..0dc743c --- /dev/null +++ b/chrome/browser/geolocation/libgps_wrapper_linux.cc @@ -0,0 +1,202 @@ +// 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/libgps_wrapper_linux.h" + +#include <dlfcn.h> + +#include "chrome/common/geoposition.h" +#include "base/logging.h" +#include "base/string_util.h" + +namespace { +LibGpsLibraryLoader* TryToOpen(const char* lib, + LibGpsLibraryLoader::InitMode mode) { + void* dl_handle = dlopen(lib, RTLD_LAZY); + if (dl_handle) { + LOG(INFO) << "Loaded " << lib; + scoped_ptr<LibGpsLibraryLoader> wrapper(new LibGpsLibraryLoader(dl_handle)); + if (wrapper->Init(mode)) + return wrapper.release(); + } else { + DLOG(INFO) << "Could not open " << lib << ": " << dlerror(); + } + return NULL; +} +} // namespace + +LibGps::LibGps(LibGpsLibraryLoader* dl_wrapper) + : library_(dl_wrapper) { + DCHECK(dl_wrapper != NULL); +} + +LibGps::~LibGps() { +} + +LibGps* LibGps::New() { + LibGpsLibraryLoader* wrapper; + wrapper = TryToOpen("libgps.so.19", LibGpsLibraryLoader::INITMODE_STREAM); + if (wrapper) + return NewV294(wrapper); + wrapper = TryToOpen("libgps.so.17", LibGpsLibraryLoader::INITMODE_QUERY); + if (wrapper) + return NewV238(wrapper); + wrapper = TryToOpen("libgps.so", LibGpsLibraryLoader::INITMODE_STREAM); + if (wrapper) + return NewV294(wrapper); + return NULL; +} + +bool LibGps::Start(std::string* error_out) { + if (!library().open(NULL, NULL, error_out)) + return false; + if (!StartStreaming()) { + library().close(); + return false; + } + return true; +} + +void LibGps::Stop() { + library().close(); +} + +bool LibGps::Poll() { + bool ret = true; + while (DataWaiting(&ret)) { + int error = library().poll(); + if (error) { + last_error_ = StringPrintf("poll() returned %d", error); + return false; + } + } + if (!ret) + last_error_ = "DataWaiting failed"; + return ret; +} + +bool LibGps::GetPosition(Geoposition* position) { + DCHECK(position); + position->error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; + if (!library().is_open()) { + position->error_message = L"No gpsd connection"; + return false; + } + if (!GetPositionIfFixed(position)) { + position->error_message = ASCIIToWide(last_error_); + return false; + } + position->error_code = Geoposition::ERROR_CODE_NONE; + if (!position->IsValidFix()) { + // GetPositionIfFixed returned true, yet we've not got a valid fix. + // This shouldn't happen; something went wrong in the conversion. + NOTREACHED() << "Invalid position from GetPositionIfFixed: lat,long " + << position->latitude << "," << position->longitude + << " accuracy " << position->accuracy << " time " + << position->timestamp.ToDoubleT(); + position->error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; + position->error_message = L"Bad fix from gps"; + return false; + } + return true; +} + +LibGpsLibraryLoader::LibGpsLibraryLoader(void* dl_handle) + : dl_handle_(dl_handle), + gps_open_(NULL), + gps_close_(NULL), + gps_poll_(NULL), + gps_query_(NULL), + gps_stream_(NULL), + gps_waiting_(NULL), + gps_data_(NULL) { + DCHECK(dl_handle_); +} + +// |mode| could be turned into a bit mask if required, but for now the +// two options are mutually exclusive. +bool LibGpsLibraryLoader::Init(InitMode mode) { + DCHECK(dl_handle_); + DCHECK(!gps_open_) << "Already initialized"; + #define SET_FN_POINTER(function, required) \ + function##_ = (function##_fn)dlsym(dl_handle_, #function); \ + if ((required) && !function##_) { \ + LOG(INFO) << "libgps " << #function << " error: " << dlerror(); \ + close(); \ + return false; \ + } + SET_FN_POINTER(gps_open, true); + SET_FN_POINTER(gps_close, true); + SET_FN_POINTER(gps_poll, true); + SET_FN_POINTER(gps_query, mode == INITMODE_QUERY); + SET_FN_POINTER(gps_stream, mode == INITMODE_STREAM); + SET_FN_POINTER(gps_waiting, mode == INITMODE_STREAM); + #undef SET_FN_POINTER + return true; +} + +LibGpsLibraryLoader::~LibGpsLibraryLoader() { + close(); + if (dlclose(dl_handle_) != 0) { + NOTREACHED() << "Error closing dl handle"; + } +} + +bool LibGpsLibraryLoader::open(const char* host, const char* port, + std::string* error_out) { + DCHECK(!gps_data_) << "libgps handle already opened"; + DCHECK(gps_open_) << "Must call Init() first"; + std::string dummy; + if (!error_out) error_out = &dummy; + + gps_data_ = gps_open_(host, port); + if (!gps_data_) { // GPS session was not created. + *error_out = "gps_open failed"; + close(); + } + return gps_data_; +} + +void LibGpsLibraryLoader::close() { + if (gps_data_) { + DCHECK(gps_close_); + gps_close_(gps_data_); + gps_data_ = NULL; + } +} + +int LibGpsLibraryLoader::poll() { + DCHECK(is_open()); + DCHECK(gps_poll_); + return gps_poll_(gps_data_); +} + +// This is intentionally ignoring the va_arg extension to query(): the caller +// can use base::StringPrintf to achieve the same effect. +int LibGpsLibraryLoader::query(const char* fmt) { + DCHECK(is_open()); + DCHECK(gps_query_); + return gps_query_(gps_data_, fmt); +} + +int LibGpsLibraryLoader::stream(int flags) { + DCHECK(is_open()); + DCHECK(gps_stream_); + return gps_stream_(gps_data_, flags, NULL); +} + +bool LibGpsLibraryLoader::waiting() { + DCHECK(is_open()); + DCHECK(gps_waiting_); + return gps_waiting_(gps_data_); +} + +const gps_data_t& LibGpsLibraryLoader::data() const { + DCHECK(is_open()); + return *gps_data_; +} + +bool LibGpsLibraryLoader::is_open() const { + return gps_data_ != NULL; +} diff --git a/chrome/browser/geolocation/libgps_wrapper_linux.h b/chrome/browser/geolocation/libgps_wrapper_linux.h new file mode 100644 index 0000000..f49b20d --- /dev/null +++ b/chrome/browser/geolocation/libgps_wrapper_linux.h @@ -0,0 +1,115 @@ +// 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. + +// Defines a wrapper around the C libgps API (gps.h). Similar to the libgpsmm.h +// API provided by that package, but adds: +// - shared object dynamic loading +// - support for (and abstraction from) different libgps.so versions +// - configurable for testing +// - more convenient error handling. + +#ifndef CHROME_BROWSER_GEOLOCATION_LIBGPS_WRAPPER_LINUX_H_ +#define CHROME_BROWSER_GEOLOCATION_LIBGPS_WRAPPER_LINUX_H_ + +#include <string> + +#include "base/scoped_ptr.h" +#include "base/time.h" + +struct Geoposition; +class LibGpsLibraryLoader; + +class LibGps { + public: + virtual ~LibGps(); + // Attempts to dynamically load the libgps.so library, and creates and + // appropriate LibGps instance for the version loaded. Returns NULL on + // failure. + static LibGps* New(); + + bool Start(std::string* error_out); + void Stop(); + bool Poll(); + bool GetPosition(Geoposition* position); + + protected: + // Takes ownership of |dl_wrapper|. + explicit LibGps(LibGpsLibraryLoader* dl_wrapper); + + LibGpsLibraryLoader& library() { + return *library_; + } + // Called be start Start after successful |gps_open| to setup streaming. + virtual bool StartStreaming() = 0; + virtual bool DataWaiting(bool* ok) = 0; + // Returns false if there is not fix available. + virtual bool GetPositionIfFixed(Geoposition* position) = 0; + + private: + // Factory functions to create instances of LibGps using the corresponding + // libgps API versions (v2.38 => libgps.so.17, v2.94 => libgps.so.19). + // See LibGps::New() for the public API to this. + // Takes ownership of |dl_wrapper|. + static LibGps* NewV238(LibGpsLibraryLoader* dl_wrapper); + static LibGps* NewV294(LibGpsLibraryLoader* dl_wrapper); + + scoped_ptr<LibGpsLibraryLoader> library_; + std::string last_error_; + + DISALLOW_COPY_AND_ASSIGN(LibGps); +}; + +struct gps_data_t; + +// Wraps the low-level shared object, binding C++ member functions onto the +// underlying C functions obtained from the library. +class LibGpsLibraryLoader { + public: + // Pass to Init() to indicate which functions should be wired up. + enum InitMode { + INITMODE_QUERY, + INITMODE_STREAM, + }; + + // Takes ownership of the handle passed in (will be released via dlclose). + explicit LibGpsLibraryLoader(void* dl_handle); + ~LibGpsLibraryLoader(); + // Must be successfully called before using any of the API methods below. + // Returns false on error. + bool Init(InitMode requirement); + + // Analogs of gps_xxx methods in gps.h + bool open(const char* host, const char* port, std::string* error_out); + void close(); + int poll(); + int query(const char* fmt); + int stream(int flags); + bool waiting(); + const gps_data_t& data() const; + bool is_open() const; + + private: + typedef gps_data_t* (*gps_open_fn)(const char*, const char*); + typedef int (*gps_close_fn)(gps_data_t*); + typedef int (*gps_poll_fn)(gps_data_t*); + // v2.34 only + typedef int (*gps_query_fn)(struct gps_data_t *gpsdata, const char* fmt, ...); + // v2.90+ + typedef int (*gps_stream_fn)(gps_data_t*, unsigned int, void*); + typedef bool (*gps_waiting_fn)(gps_data_t*); + + void* dl_handle_; + gps_open_fn gps_open_; + gps_close_fn gps_close_; + gps_poll_fn gps_poll_; + gps_query_fn gps_query_; + gps_stream_fn gps_stream_; + gps_waiting_fn gps_waiting_; + + gps_data_t* gps_data_; + + DISALLOW_COPY_AND_ASSIGN(LibGpsLibraryLoader); +}; + +#endif // CHROME_BROWSER_GEOLOCATION_LIBGPS_WRAPPER_LINUX_H_ diff --git a/chrome/browser/geolocation/location_arbitrator.cc b/chrome/browser/geolocation/location_arbitrator.cc index e0d513a..0eb9a10 100644 --- a/chrome/browser/geolocation/location_arbitrator.cc +++ b/chrome/browser/geolocation/location_arbitrator.cc @@ -153,11 +153,14 @@ void GeolocationArbitratorImpl::OnAccessTokenStoresLoaded( if (g_provider_factory_function_for_test) { provider_.reset(g_provider_factory_function_for_test()); } else { - // TODO(joth): When arbitration is implemented, iterate the whole - // set rather than cherry-pick our defaul url. - provider_.reset(NewNetworkLocationProvider( - access_token_store_.get(), context_getter_.get(), default_url_, - access_token_set[default_url_])); + provider_.reset(NewGpsLocationProvider()); + if (provider_ == NULL) { + // TODO(joth): When arbitration is implemented, iterate the whole + // set rather than cherry-pick our default url. + provider_.reset(NewNetworkLocationProvider( + access_token_store_.get(), context_getter_.get(), default_url_, + access_token_set[default_url_])); + } } DCHECK(provider_ != NULL); provider_->RegisterListener(this); diff --git a/chrome/browser/geolocation/location_provider.cc b/chrome/browser/geolocation/location_provider.cc index c8a9f67..858963f 100644 --- a/chrome/browser/geolocation/location_provider.cc +++ b/chrome/browser/geolocation/location_provider.cc @@ -65,7 +65,9 @@ void LocationProviderBase::InformListenersOfMovement() { } } -// Currently no platforms have a GPS location provider. +// Currently only Linux has a GPS provider. +#if !defined(OS_LINUX) LocationProviderBase* NewGpsLocationProvider() { return NULL; } +#endif diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index d8acb1f..9b0a20f 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -1187,6 +1187,12 @@ 'browser/geolocation/geolocation_exceptions_table_model.h', 'browser/geolocation/geolocation_settings_state.cc', 'browser/geolocation/geolocation_settings_state.h', + 'browser/geolocation/gps_location_provider_linux.cc', + 'browser/geolocation/gps_location_provider_linux.h', + 'browser/geolocation/libgps_2_38_wrapper_linux.cc', + 'browser/geolocation/libgps_2_94_wrapper_linux.cc', + 'browser/geolocation/libgps_wrapper_linux.cc', + 'browser/geolocation/libgps_wrapper_linux.h', 'browser/geolocation/location_arbitrator.cc', 'browser/geolocation/location_arbitrator.h', 'browser/geolocation/location_provider.cc', |