summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjoth@chromium.org <joth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-28 13:50:04 +0000
committerjoth@chromium.org <joth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-28 13:50:04 +0000
commit8f9238fdc4ecd0032423625679ccfa2e71a5edb6 (patch)
tree2fa5d0fdfa069c25d8d9c491ec2fddbd5b71a299
parent10d1c7cd03001c4b58e648257cc72986f8762112 (diff)
downloadchromium_src-8f9238fdc4ecd0032423625679ccfa2e71a5edb6.zip
chromium_src-8f9238fdc4ecd0032423625679ccfa2e71a5edb6.tar.gz
chromium_src-8f9238fdc4ecd0032423625679ccfa2e71a5edb6.tar.bz2
Add more gears geolocaiton files into chromium: locaiton provider, network location provider, and backoff maanger.
All files are from svn checkout http://gears.googlecode.com/svn/trunk/ gears-read-only r3414 Only modification is #if 0 around each file, to avoid build / checkdeps breakage. BUG=11246 TEST=None (just importing code, tests to follow) Review URL: http://codereview.chromium.org/555148 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@37400 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/geolocation/backoff_manager.cc83
-rw-r--r--chrome/browser/geolocation/backoff_manager.h63
-rw-r--r--chrome/browser/geolocation/location_provider.cc110
-rw-r--r--chrome/browser/geolocation/location_provider.h125
-rw-r--r--chrome/browser/geolocation/location_provider_pool.cc182
-rw-r--r--chrome/browser/geolocation/location_provider_pool.h89
-rw-r--r--chrome/browser/geolocation/network_location_provider.cc508
-rw-r--r--chrome/browser/geolocation/network_location_provider.h144
-rw-r--r--chrome/browser/geolocation/network_location_request.cc561
-rw-r--r--chrome/browser/geolocation/network_location_request.h141
10 files changed, 2006 insertions, 0 deletions
diff --git a/chrome/browser/geolocation/backoff_manager.cc b/chrome/browser/geolocation/backoff_manager.cc
new file mode 100644
index 0000000..bbdae739
--- /dev/null
+++ b/chrome/browser/geolocation/backoff_manager.cc
@@ -0,0 +1,83 @@
+// Copyright 2008, Google Inc.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// 3. Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// TODO(joth): port to chromium
+#if 0
+
+#include "gears/geolocation/backoff_manager.h"
+
+#include <assert.h>
+
+// The baseline minimum period between network requests.
+static const int kBaselineMinimumRequestInterval = 1000 * 5; // 5 seconds
+// The upper limit of the minimum period between network requests.
+static const int kMinimumRequestIntervalLimit = 1000 * 60 * 60 * 3; // 3 hours
+
+
+// static
+BackoffManager::ServerMap BackoffManager::servers_;
+
+// static
+Mutex BackoffManager::servers_mutex_;
+
+// static
+void BackoffManager::ReportRequest(const std::string16 &url) {
+ MutexLock lock(&servers_mutex_);
+ ServerMap::iterator iter = servers_.find(url);
+ if (iter != servers_.end()) {
+ iter->second.first = GetCurrentTimeMillis();
+ } else {
+ servers_[url] = std::make_pair(GetCurrentTimeMillis(),
+ kBaselineMinimumRequestInterval);
+ }
+}
+
+// static
+int64 BackoffManager::ReportResponse(const std::string16 &url,
+ bool server_error) {
+ // Use exponential back-off on server error.
+ MutexLock lock(&servers_mutex_);
+ ServerMap::iterator iter = servers_.find(url);
+ assert(iter != servers_.end());
+ int64 *interval = &iter->second.second;
+ if (server_error) {
+ if (*interval < kMinimumRequestIntervalLimit) {
+ // Increase interval by between 90% and 110%.
+ srand(static_cast<unsigned int>(GetCurrentTimeMillis()));
+ double increment_proportion = 0.9 + 0.2 * rand() / RAND_MAX;
+ int64 increment = static_cast<int64>(*interval * increment_proportion);
+ if (increment > kMinimumRequestIntervalLimit - *interval) {
+ *interval = kMinimumRequestIntervalLimit;
+ } else {
+ *interval += increment;
+ }
+ }
+ } else {
+ *interval = kBaselineMinimumRequestInterval;
+ }
+ return iter->second.first + *interval;
+}
+
+#endif // if 0
diff --git a/chrome/browser/geolocation/backoff_manager.h b/chrome/browser/geolocation/backoff_manager.h
new file mode 100644
index 0000000..395d0e9
--- /dev/null
+++ b/chrome/browser/geolocation/backoff_manager.h
@@ -0,0 +1,63 @@
+// Copyright 2008, Google Inc.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// 3. Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The BackoffManager class is used to implement exponential back-off for
+// network requests in case of sever errors. Users report to the BackoffManager
+// class when they make a request to or receive a response from a given url. The
+// BackoffManager class provides the earliest time at which subsequent requests
+// should be made.
+
+#ifndef GEARS_GEOLOCATION_BACKOFF_MANAGER_H__
+#define GEARS_GEOLOCATION_BACKOFF_MANAGER_H__
+
+// TODO(joth): port to chromium
+#if 0
+
+#include "gears/base/common/common.h"
+#include "gears/base/common/mutex.h"
+#include "gears/base/common/stopwatch.h" // For GetCurrentTimeMillis
+#include <map>
+
+class BackoffManager {
+ public:
+ static void ReportRequest(const std::string16 &url);
+ static int64 ReportResponse(const std::string16 &url, bool server_error);
+
+ private:
+ // A map from server URL to a pair of integers representing the last request
+ // time and the current minimum interval between requests, both in
+ // milliseconds.
+ typedef std::map<std::string16, std::pair<int64, int64> > ServerMap;
+ static ServerMap servers_;
+
+ // The mutex used to protect the map.
+ static Mutex servers_mutex_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(BackoffManager);
+};
+
+#endif // if 0
+
+#endif // GEARS_GEOLOCATION_BACKOFF_MANAGER_H__
diff --git a/chrome/browser/geolocation/location_provider.cc b/chrome/browser/geolocation/location_provider.cc
new file mode 100644
index 0000000..71bf33a
--- /dev/null
+++ b/chrome/browser/geolocation/location_provider.cc
@@ -0,0 +1,110 @@
+// Copyright 2008, Google Inc.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// 3. Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// This file implements a mock location provider and the factory functions for
+// creating various types of location provider.
+
+// TODO(joth): port to chromium
+#if 0
+
+#include "gears/geolocation/location_provider.h"
+
+#include <assert.h>
+#include "gears/base/common/scoped_refptr.h" // For RefCount
+
+void LocationProviderBase::RegisterListener(ListenerInterface *listener,
+ bool request_address) {
+ assert(listener);
+ MutexLock lock(&listeners_mutex_);
+ ListenerMap::iterator iter = listeners_.find(listener);
+ if (iter == listeners_.end()) {
+ std::pair<ListenerMap::iterator, bool> result =
+ listeners_.insert(
+ std::make_pair(listener,
+ std::make_pair(request_address, new RefCount())));
+ assert(result.second);
+ iter = result.first;
+ }
+ RefCount *count = iter->second.second;
+ assert(count);
+ count->Ref();
+}
+
+void LocationProviderBase::UnregisterListener(ListenerInterface *listener) {
+ assert(listener);
+ MutexLock lock(&listeners_mutex_);
+ ListenerMap::iterator iter = listeners_.find(listener);
+ if (iter != listeners_.end()) {
+ RefCount *count = iter->second.second;
+ assert(count);
+ if (count->Unref()) {
+ delete count;
+ listeners_.erase(iter);
+ }
+ }
+}
+
+void LocationProviderBase::UpdateListeners() {
+ MutexLock lock(&listeners_mutex_);
+ for (ListenerMap::const_iterator iter = listeners_.begin();
+ iter != listeners_.end();
+ ++iter) {
+ iter->first->LocationUpdateAvailable(this);
+ }
+}
+
+void LocationProviderBase::InformListenersOfMovement() {
+ MutexLock lock(&listeners_mutex_);
+ for (ListenerMap::const_iterator iter = listeners_.begin();
+ iter != listeners_.end();
+ ++iter) {
+ iter->first->MovementDetected(this);
+ }
+}
+
+LocationProviderBase::ListenerMap *LocationProviderBase::GetListeners() {
+ return &listeners_;
+}
+
+Mutex *LocationProviderBase::GetListenersMutex() {
+ return &listeners_mutex_;
+}
+
+// Win32, Linux and OSX do not have a GPS location provider.
+#if (defined(WIN32) && !defined(OS_WINCE)) || \
+ defined(LINUX) || \
+ defined(OS_MACOSX)
+
+LocationProviderBase *NewGpsLocationProvider(
+ BrowsingContext *browsing_context,
+ const std::string16 &reverse_geocode_url,
+ const std::string16 &host_name,
+ const std::string16 &address_language) {
+ return NULL;
+}
+
+#endif
+
+#endif // if 0
diff --git a/chrome/browser/geolocation/location_provider.h b/chrome/browser/geolocation/location_provider.h
new file mode 100644
index 0000000..5383dd8
--- /dev/null
+++ b/chrome/browser/geolocation/location_provider.h
@@ -0,0 +1,125 @@
+// Copyright 2008, Google Inc.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// 3. Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// A location provider provides position information from a particular source
+// (GPS, network etc). The GearsGeolocation object uses a set of location
+// providers to obtain a position fix.
+//
+// This file declares a base class to be used by all location providers.
+// Primarily, this class declares interface methods to be implemented by derived
+// classes.
+
+#ifndef GEARS_GEOLOCATION_LOCATION_PROVIDER_H__
+#define GEARS_GEOLOCATION_LOCATION_PROVIDER_H__
+
+// TODO(joth): port to chromium
+#if 0
+
+#include <map>
+#include "gears/base/common/base_class.h"
+#include "gears/base/common/mutex.h"
+#include "gears/base/common/string16.h"
+
+struct Position;
+class RefCount;
+
+// The base class used by all location providers.
+class LocationProviderBase {
+ public:
+ class ListenerInterface {
+ public:
+ // Used to inform listener that a new position fix is available or that a
+ // fatal error has occurred. Providers should call this for new listeners
+ // as soon as a position is available.
+ virtual bool LocationUpdateAvailable(LocationProviderBase *provider) = 0;
+ // Used to inform listener that movement has been detected. If obtaining the
+ // position succeeds, this will be followed by a call to
+ // LocationUpdateAvailable. Some providers may not be able to detect
+ // movement before a new fix is obtained, so will never call this method.
+ // Note that this is not called in response to registration of a new
+ // listener.
+ virtual bool MovementDetected(LocationProviderBase *provider) = 0;
+ virtual ~ListenerInterface() {}
+ };
+
+ virtual ~LocationProviderBase() {}
+
+ // Registers a listener, which will be called back on
+ // ListenerInterface::LocationUpdateAvailable as soon as a position is
+ // available and again whenever a new position is available. Ref counts the
+ // listener to handle multiple calls to this method.
+ virtual void RegisterListener(ListenerInterface *listener,
+ bool request_address);
+ // Unregisters a listener. Unrefs the listener to handle multiple calls to
+ // this method. Once the ref count reaches zero, the listener is removed and
+ // once this method returns, no further calls to
+ // ListenerInterface::LocationUpdateAvailable will be made for this listener.
+ // It may block if a callback is in progress.
+ virtual void UnregisterListener(ListenerInterface *listener);
+
+ // Interface methods
+ // Gets the current best position estimate.
+ virtual void GetPosition(Position *position) = 0;
+ // Provides a hint to the provider that new location data is needed as soon
+ // as possible. Default implementation does nothing.
+ virtual void UpdatePosition() {}
+
+ // Accessor methods.
+ typedef std::pair<bool, RefCount*> ListenerPair;
+ typedef std::map<ListenerInterface*, ListenerPair> ListenerMap;
+ ListenerMap *GetListeners();
+ Mutex *GetListenersMutex();
+
+ protected:
+ // Inform listeners that a new position or error is available, using
+ // LocationUpdateAvailable.
+ virtual void UpdateListeners();
+ // Inform listeners that movement has been detected, using MovementDetected.
+ virtual void InformListenersOfMovement();
+
+ private:
+ // The listeners registered to this provider. For each listener, we store a
+ // ref count and whether it requires an address.
+ ListenerMap listeners_;
+ Mutex listeners_mutex_;
+};
+
+// Factory functions for the various types of location provider to abstract over
+// the platform-dependent implementations.
+LocationProviderBase *NewMockLocationProvider();
+LocationProviderBase *NewGpsLocationProvider(
+ BrowsingContext *browsing_context,
+ const std::string16 &reverse_geocode_url,
+ const std::string16 &host_name,
+ const std::string16 &address_language);
+LocationProviderBase *NewNetworkLocationProvider(
+ BrowsingContext *browsing_context,
+ const std::string16 &url,
+ const std::string16 &host_name,
+ const std::string16 &language);
+
+#endif // if 0
+
+#endif // GEARS_GEOLOCATION_LOCATION_PROVIDER_H__
diff --git a/chrome/browser/geolocation/location_provider_pool.cc b/chrome/browser/geolocation/location_provider_pool.cc
new file mode 100644
index 0000000..32d6f92
--- /dev/null
+++ b/chrome/browser/geolocation/location_provider_pool.cc
@@ -0,0 +1,182 @@
+// Copyright 2008, Google Inc.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// 3. Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// TODO(joth): port to chromium
+#if 0
+
+#include "gears/geolocation/location_provider_pool.h"
+
+#include <assert.h>
+
+static const char16 *kMockString = STRING16(L"MOCK");
+static const char16 *kGpsString = STRING16(L"GPS");
+static const char16 *kNetworkString = STRING16(L"NETWORK");
+
+// Local functions
+static std::string16 MakeKey(const std::string16 &type,
+ const std::string16 &url,
+ const std::string16 &host,
+ const std::string16 &language);
+
+// static member variables
+LocationProviderPool LocationProviderPool::instance_;
+
+LocationProviderPool::LocationProviderPool()
+ : use_mock_location_provider_(false) {
+}
+
+LocationProviderPool::~LocationProviderPool() {
+#if BROWSER_IEMOBILE
+ // The lack of unload monitoring on IE Mobile on WinCE means that we may leak
+ // providers.
+#else
+ assert(providers_.empty());
+#endif // BROWSER_IEMOBILE
+}
+
+// static
+LocationProviderPool *LocationProviderPool::GetInstance() {
+ return &instance_;
+}
+
+LocationProviderBase *LocationProviderPool::Register(
+ BrowsingContext *browsing_context,
+ const std::string16 &type,
+ const std::string16 &url,
+ const std::string16 &host,
+ bool request_address,
+ const std::string16 &language,
+ LocationProviderBase::ListenerInterface *listener) {
+ assert(listener);
+ MutexLock lock(&providers_mutex_);
+ std::string16 key = MakeKey(type, url, host, language);
+ ProviderMap::iterator iter = providers_.find(key);
+ if (iter == providers_.end()) {
+ LocationProviderBase *provider = NewProvider(browsing_context, type, url,
+ host, language);
+ if (!provider) {
+ return NULL;
+ }
+ std::pair<ProviderMap::iterator, bool> result =
+ providers_.insert(
+ std::make_pair(key,
+ std::make_pair(provider, new RefCount())));
+ assert(result.second);
+ iter = result.first;
+ }
+ LocationProviderBase *provider = iter->second.first;
+ assert(provider);
+ provider->RegisterListener(listener, request_address);
+ RefCount *count = iter->second.second;
+ assert(count);
+ count->Ref();
+ return provider;
+}
+
+bool LocationProviderPool::Unregister(
+ LocationProviderBase *provider,
+ LocationProviderBase::ListenerInterface *listener) {
+ assert(provider);
+ assert(listener);
+ MutexLock lock(&providers_mutex_);
+ for (ProviderMap::iterator iter = providers_.begin();
+ iter != providers_.end();
+ ++iter) {
+ LocationProviderBase *current_provider = iter->second.first;
+ if (current_provider == provider) {
+ current_provider->UnregisterListener(listener);
+ RefCount *count = iter->second.second;
+ assert(count);
+ if (count->Unref()) {
+ delete current_provider;
+ delete count;
+ providers_.erase(iter);
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+void LocationProviderPool::UseMockLocationProvider(
+ bool use_mock_location_provider) {
+ use_mock_location_provider_ = use_mock_location_provider;
+}
+
+LocationProviderBase *LocationProviderPool::NewProvider(
+ BrowsingContext *browsing_context,
+ const std::string16 &type,
+ const std::string16 &url,
+ const std::string16 &host,
+ const std::string16 &language) {
+ if (type == kMockString) {
+ // use_mock_location_provider_ can only be set to true in a build that uses
+ // USING_CCTESTS.
+#if USING_CCTESTS
+ if (use_mock_location_provider_) {
+ return NewMockLocationProvider();
+ } else {
+ return NULL;
+ }
+#else
+ return NULL;
+#endif // USING_CCTESTS
+ } else if (type == kGpsString) {
+ return NewGpsLocationProvider(browsing_context, url, host, language);
+ } else if (type == kNetworkString) {
+ return NewNetworkLocationProvider(browsing_context, url, host, language);
+ }
+ assert(false);
+ return NULL;
+}
+
+// Local function
+static std::string16 MakeKey(const std::string16 &type,
+ const std::string16 &url,
+ const std::string16 &host,
+ const std::string16 &language) {
+ // Network requests are made from a specific host and use a specific language.
+ // Therefore we must key network and GPS providers on server URL, host and
+ // language.
+ if (type == kMockString) {
+ return type;
+ } else if (type == kGpsString || type == kNetworkString) {
+ std::string16 key = type;
+ if (!url.empty()) {
+ key += STRING16(L" url=") + url;
+ }
+ if (!host.empty()) {
+ key += STRING16(L" host=") + host;
+ }
+ if (!language.empty()) {
+ key += STRING16(L" language=") + language;
+ }
+ return key;
+ }
+ assert(false);
+ return STRING16(L"");
+}
+
+#endif // if 0
diff --git a/chrome/browser/geolocation/location_provider_pool.h b/chrome/browser/geolocation/location_provider_pool.h
new file mode 100644
index 0000000..c15e54f
--- /dev/null
+++ b/chrome/browser/geolocation/location_provider_pool.h
@@ -0,0 +1,89 @@
+// Copyright 2008, Google Inc.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// 3. Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GEARS_GEOLOCATION_LOCATION_PROVIDER_POOL_H__
+#define GEARS_GEOLOCATION_LOCATION_PROVIDER_POOL_H__
+
+// TODO(joth): port to chromium
+#if 0
+
+#include <map>
+#include "gears/base/common/common.h"
+#include "gears/base/common/mutex.h"
+#include "gears/base/common/scoped_refptr.h" // For RefCount
+#include "gears/base/common/string16.h"
+#include "gears/geolocation/location_provider.h"
+
+class LocationProviderPool {
+ public:
+ LocationProviderPool();
+ ~LocationProviderPool();
+
+ static LocationProviderPool *GetInstance();
+
+ // Registers a listener with a given type of location provider. Creates the
+ // provider if the pool does not alrerady contain an instance of that
+ // provider. Returns the provider, or NULL if it cannot be created.
+ LocationProviderBase *Register(
+ BrowsingContext *browsing_context,
+ const std::string16 &type,
+ const std::string16 &url,
+ const std::string16 &host,
+ bool request_address,
+ const std::string16 &language,
+ LocationProviderBase::ListenerInterface *listener);
+
+ // Unregister a listener from a given location provider. Deletes the provider
+ // if there are no remaining listeners registered with it. Return value
+ // indicates whether the provider was found in the pool.
+ bool Unregister(LocationProviderBase *provider,
+ LocationProviderBase::ListenerInterface *listener);
+
+ // Configures the pool to return a mock location provider for the type "MOCK".
+ // This method is used only by the Gears test object.
+ void UseMockLocationProvider(bool use_mock_location_provider);
+
+ LocationProviderBase *NewProvider(BrowsingContext *browsing_context,
+ const std::string16 &type,
+ const std::string16 &url,
+ const std::string16 &host,
+ const std::string16 &language);
+
+ private:
+ static LocationProviderPool instance_;
+
+ typedef std::pair<LocationProviderBase*, RefCount*> ProviderPair;
+ typedef std::map<std::string16, ProviderPair> ProviderMap;
+ ProviderMap providers_;
+ Mutex providers_mutex_;
+
+ bool use_mock_location_provider_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(LocationProviderPool);
+};
+
+#endif // if 0
+
+#endif // GEARS_GEOLOCATION_LOCATION_PROVIDER_POOL_H__
diff --git a/chrome/browser/geolocation/network_location_provider.cc b/chrome/browser/geolocation/network_location_provider.cc
new file mode 100644
index 0000000..df4c8cb
--- /dev/null
+++ b/chrome/browser/geolocation/network_location_provider.cc
@@ -0,0 +1,508 @@
+// Copyright 2008, Google Inc.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// 3. Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// TODO(joth): port to chromium
+#if 0
+
+#include "gears/geolocation/network_location_provider.h"
+
+#include "gears/base/common/base_class.h"
+#include "gears/base/common/stopwatch.h" // For GetCurrentTimeMillis
+#include "gears/geolocation/access_token_manager.h"
+#include "gears/geolocation/backoff_manager.h"
+
+// The maximum period of time we'll wait for a complete set of device data
+// before sending the request.
+static const int kDataCompleteWaitPeriod = 1000 * 2; // 2 seconds
+
+// The maximum size of the cache of positions for previously requested device
+// data.
+static const size_t kMaximumCacheSize = 10;
+
+
+// The PositionCache handles caching and retrieving a position returned by a
+// network location provider. It is not thread safe. It's methods are called on
+// multiple threads by NetworkLocationProvider, but the timing is such that
+// thread safety is not required.
+class PositionCache {
+ public:
+ // Caches the current position response for the current set of cell ID and
+ // WiFi data. Returns true on success, false otherwise.
+ bool CachePosition(const RadioData &radio_data,
+ const WifiData &wifi_data,
+ const Position &position) {
+ // Check that we can generate a valid key for the device data.
+ std::string16 key;
+ if (!MakeKey(radio_data, wifi_data, &key)) {
+ return false;
+ }
+ // If the cache is full, remove the oldest entry.
+ if (cache_.size() == kMaximumCacheSize) {
+ assert(cache_times_.size() == kMaximumCacheSize);
+ CacheTimesMap::iterator oldest_entry = cache_times_.begin();
+ assert(oldest_entry != cache_times_.end());
+ cache_.erase(oldest_entry->second);
+ cache_times_.erase(oldest_entry);
+ }
+ // Insert the position into the cache.
+ std::pair<CacheMap::iterator, bool> result =
+ cache_.insert(std::make_pair(key, position));
+ assert(result.second);
+ cache_times_[position.timestamp] = result.first;
+ assert(cache_.size() == cache_times_.size());
+ return true;
+ }
+
+ // Searches for a cached position response for the current set of cell ID and
+ // WiFi data. Returns the cached position if available, NULL otherwise.
+ const Position *FindPosition(const RadioData &radio_data,
+ const WifiData &wifi_data) {
+ std::string16 key;
+ if (!MakeKey(radio_data, wifi_data, &key)) {
+ return NULL;
+ }
+ CacheMap::const_iterator iter = cache_.find(key);
+ return iter == cache_.end() ? NULL : &iter->second;
+ }
+
+ // Makes the key for the map of cached positions, using a set of
+ // device data. Returns true if a good key was generated, false otherwise.
+ static bool MakeKey(const RadioData& /*radio_data*/,
+ const WifiData &wifi_data,
+ std::string16 *key) {
+ // Currently we use only the WiFi data, and base the key only on the MAC
+ // addresses.
+ // TODO(steveblock): Make use of radio_data.
+ key->clear();
+ for (WifiData::AccessPointDataSet::const_iterator iter =
+ wifi_data.access_point_data.begin();
+ iter != wifi_data.access_point_data.begin();
+ iter++) {
+ key->append(STRING16(L"|") + iter->mac_address + STRING16(L"|"));
+ }
+ // If the key is the empty string, return false, as we don't want to cache a
+ // position for such a set of device data.
+ return !key->empty();
+ }
+
+private:
+ // The cache of positions. This is stored using two maps. One map is keyed on
+ // a string that represents a set of device data, the other is keyed on the
+ // timestamp of the position.
+ typedef std::map<std::string16, Position> CacheMap;
+ CacheMap cache_;
+ typedef std::map<int64, CacheMap::iterator> CacheTimesMap;
+ CacheTimesMap cache_times_;
+};
+
+
+// NetworkLocationProvider factory function
+LocationProviderBase *NewNetworkLocationProvider(
+ BrowsingContext *browsing_context,
+ const std::string16 &url,
+ const std::string16 &host_name,
+ const std::string16 &language) {
+ return new NetworkLocationProvider(browsing_context, url, host_name,
+ language);
+}
+
+
+// NetworkLocationProvider
+NetworkLocationProvider::NetworkLocationProvider(
+ BrowsingContext *browsing_context,
+ const std::string16 &url,
+ const std::string16 &host_name,
+ const std::string16 &language)
+ : request_(NULL),
+ url_(url),
+ host_name_(host_name),
+ request_address_(false),
+ request_address_from_last_request_(false),
+ address_language_(language),
+ is_shutting_down_(false),
+ is_new_data_available_(false),
+ is_new_listener_waiting_(false),
+ browsing_context_(browsing_context) {
+ // TODO(steveblock): Consider allowing multiple values for "address_language"
+ // in the network protocol to allow better sharing of network location
+ // providers.
+
+ // Get the device data providers. The first call to Register will create the
+ // provider and it will be deleted by ref counting.
+ radio_data_provider_ = RadioDataProvider::Register(this);
+ wifi_data_provider_ = WifiDataProvider::Register(this);
+
+ AccessTokenManager::GetInstance()->Register(url_);
+
+ // Create the position cache.
+ position_cache_.reset(new PositionCache());
+
+ // Start the worker thread
+ if (!Start()) {
+ // This should never happen.
+ LOG(("Could not start the NLR"));
+ assert(false);
+ }
+}
+
+NetworkLocationProvider::~NetworkLocationProvider() {
+ // Shut down the worker thread
+ is_shutting_down_ = true;
+ thread_notification_event_.Signal();
+ Join();
+
+ // Must keep the request around until our worker thread has stopped.
+ if (request_) {
+ request_->StopThreadAndDelete();
+ request_ = NULL;
+ }
+
+ radio_data_provider_->Unregister(this);
+ wifi_data_provider_->Unregister(this);
+
+ AccessTokenManager::GetInstance()->Unregister();
+}
+
+void NetworkLocationProvider::RegisterListener(
+ LocationProviderBase::ListenerInterface *listener,
+ bool request_address) {
+ // Determine whether this listener requires an address when the last request
+ // does not.
+ bool new_listener_requires_address =
+ !request_address_from_last_request_ && request_address;
+
+ // Update whether or not we need to request an address.
+ request_address_ |= request_address;
+
+ // If we now need to request an address when we did not before, we don't add
+ // the listener. This is because if a request is currently in progress, we
+ // don't want the new listener to be called back with a position without an
+ // address. We add the listener when we make the next request.
+ if (new_listener_requires_address) {
+ MutexLock lock(&new_listeners_requiring_address_mutex_);
+ new_listeners_requiring_address_.insert(listener);
+ } else {
+ LocationProviderBase::RegisterListener(listener, request_address);
+ }
+
+ // Signal to the worker thread that there is a new listener.
+ is_new_listener_waiting_ = true;
+ thread_notification_event_.Signal();
+}
+
+void NetworkLocationProvider::UnregisterListener(
+ LocationProviderBase::ListenerInterface *listener) {
+ assert(listener);
+
+ // First try removing the listener from the set of new listeners waiting for
+ // an address. Otherwise, try the regular listeners.
+ MutexLock new_listeners_lock(&new_listeners_requiring_address_mutex_);
+ ListenerSet::iterator iter = new_listeners_requiring_address_.find(listener);
+ if (iter != new_listeners_requiring_address_.end()) {
+ new_listeners_requiring_address_.erase(iter);
+ } else {
+ LocationProviderBase::UnregisterListener(listener);
+ }
+
+ // Update whether or not we need to request an address.
+ if (request_address_) {
+ if (!new_listeners_requiring_address_.empty()) {
+ return;
+ }
+ MutexLock listeners_lock(GetListenersMutex());
+ ListenerMap *listeners = GetListeners();
+ for (ListenerMap::const_iterator iter = listeners->begin();
+ iter != listeners->end();
+ iter++) {
+ if (iter->second.first == true) {
+ return;
+ }
+ }
+ request_address_ = false;
+ }
+}
+
+// LocationProviderBase implementation
+void NetworkLocationProvider::GetPosition(Position *position) {
+ assert(position);
+ MutexLock lock(&position_mutex_);
+ *position = position_;
+}
+
+// DeviceDataProviderInterface::ListenerInterface implementation.
+void NetworkLocationProvider::DeviceDataUpdateAvailable(
+ RadioDataProvider *provider) {
+ MutexLock lock(&data_mutex_);
+ assert(provider == radio_data_provider_);
+ is_radio_data_complete_ = radio_data_provider_->GetData(&radio_data_);
+
+ DeviceDataUpdateAvailableImpl();
+}
+
+void NetworkLocationProvider::DeviceDataUpdateAvailable(
+ WifiDataProvider *provider) {
+ assert(provider == wifi_data_provider_);
+ MutexLock lock(&data_mutex_);
+ is_wifi_data_complete_ = wifi_data_provider_->GetData(&wifi_data_);
+
+ DeviceDataUpdateAvailableImpl();
+}
+
+// NetworkLocationRequest::ListenerInterface implementation.
+void NetworkLocationProvider::LocationResponseAvailable(
+ const Position &position,
+ bool server_error,
+ const std::string16 &access_token) {
+ // Record the position and update our cache.
+ position_mutex_.Lock();
+ position_ = position;
+ if (position_.IsGoodFix()) {
+ MutexLock lock(&data_mutex_);
+ position_cache_->CachePosition(radio_data_, wifi_data_, position_);
+ }
+ position_mutex_.Unlock();
+
+ // Record access_token if it's set.
+ if (!access_token.empty()) {
+ AccessTokenManager::GetInstance()->SetToken(url_, access_token);
+ }
+
+ // Get earliest time for next request.
+ earliest_next_request_time_ = BackoffManager::ReportResponse(url_,
+ server_error);
+
+ // Signal to the worker thread that this request has completed.
+ is_last_request_complete_ = true;
+ thread_notification_event_.Signal();
+
+ // Let listeners know that we now have a position available.
+ UpdateListeners();
+}
+
+// Thread implementation
+void NetworkLocationProvider::Run() {
+ // Create the network request object. We must do this on the same thread from
+ // which we'll call Start().
+ request_ = NetworkLocationRequest::Create(browsing_context_, url_,
+ host_name_, this);
+ if (!request_) {
+ LOG(("Failed to create NetworkLocationRequest object.\n"));
+ assert(false);
+ return;
+ }
+
+ // Get the device data.
+ data_mutex_.Lock();
+ is_radio_data_complete_ = radio_data_provider_->GetData(&radio_data_);
+ is_wifi_data_complete_ = wifi_data_provider_->GetData(&wifi_data_);
+ timestamp_ = GetCurrentTimeMillis();
+
+ // For the first request, wait for a certain maximum time period to get as
+ // much device data as possible.
+ int64 start_time = timestamp_;
+ while (true) {
+ if (is_radio_data_complete_ && is_wifi_data_complete_) {
+ data_mutex_.Unlock();
+ break;
+ }
+ data_mutex_.Unlock();
+
+ int64 elapsed_time = GetCurrentTimeMillis() - start_time;
+ int timeout = kDataCompleteWaitPeriod - static_cast<int>(elapsed_time);
+ if (timeout <= 0) {
+ break;
+ }
+ if (!thread_notification_event_.WaitWithTimeout(timeout)) {
+ // Quit waiting if we time out.
+ break;
+ }
+ // Terminate the thread if requested.
+ if (is_shutting_down_) {
+ return;
+ }
+ // The event should be due to new device data or a new listener.
+ assert(is_new_data_available_ || is_new_listener_waiting_);
+ // If we have new data available, inform listeners of movement.
+ if (is_new_data_available_) {
+ InformListenersOfMovement();
+ }
+ // Lock the data mutex to test is_radio_data_complete_ and
+ // is_wifi_data_complete_ on the next loop.
+ data_mutex_.Lock();
+ }
+
+ earliest_next_request_time_ = 0;
+ MakeRequest();
+
+ // Loop continually, making requests whenever new data becomes available,
+ // subject to the minimum interval.
+ //
+ // This loop is structured such that we don't require mutex locks to
+ // synchronise changes to is_new_data_available_ etc with signals on
+ // thread_notification_event_. Note that if we get a signal before we wait,
+ // the wait will proceed immediately, so we don't miss signals.
+ int64 remaining_time = 1;
+ while (!is_shutting_down_) {
+ if (remaining_time > 0) {
+ remaining_time = earliest_next_request_time_ - GetCurrentTimeMillis();
+ }
+
+ // If the minimum time period has not yet elapsed, set the timeout such
+ // that the wait expires when the period has elapsed.
+ if (remaining_time > 0) {
+ thread_notification_event_.WaitWithTimeout(
+ static_cast<int>(remaining_time));
+ } else {
+ thread_notification_event_.Wait();
+ }
+
+ // Update remaining time now we've woken up. Note that it can never
+ // transition from <= 0 to > 0.
+ if (remaining_time > 0) {
+ remaining_time = earliest_next_request_time_ - GetCurrentTimeMillis();
+ }
+
+ bool make_request = false;
+ if (is_new_listener_waiting_) {
+ // A new listener has just registered with this provider. If new data is
+ // available, force a new request now, unless a request is already in
+ // progress. If not, update listeners with the last known position,
+ // provided we have one.
+ if (is_new_data_available_) {
+ if (is_last_request_complete_) {
+ make_request = true;
+ }
+ } else {
+ // Before the first network request completes, position_ may not be
+ // valid, so we do not update the listeners. They will be updated once
+ // the network request completes.
+ if (position_.IsInitialized()) {
+ // Update listeners with the last known position.
+ UpdateListeners();
+ }
+ }
+ is_new_listener_waiting_ = false;
+ }
+
+ // If a new listener has now registered such that we now require an address,
+ // we make a new request once the current request completes.
+ new_listeners_requiring_address_mutex_.Lock();
+ if (!new_listeners_requiring_address_.empty()) {
+ if (is_last_request_complete_) {
+ make_request = true;
+ }
+ }
+ new_listeners_requiring_address_mutex_.Unlock();
+
+ // If the thread is not shutting down, we have new data, the last request
+ // has completed, and the minimum time has elapsed, make the next request.
+ if (!is_shutting_down_ &&
+ is_new_data_available_ &&
+ is_last_request_complete_ &&
+ remaining_time <= 0) {
+ make_request = true;
+ }
+
+ // If we have new data available, inform listeners of movement.
+ if (is_new_data_available_) {
+ InformListenersOfMovement();
+ }
+
+ // TODO(steveblock): If the request does not complete within some maximum
+ // time period, we should kill it and start a new request.
+ if (make_request) {
+ MakeRequest();
+ remaining_time = 1;
+ }
+ }
+}
+
+// Other methods
+
+bool NetworkLocationProvider::MakeRequest() {
+ // If we have new listeners waiting for an address, request_address_
+ // must be true.
+ assert(new_listeners_requiring_address_.empty() || request_address_);
+
+ // Move the new listeners waiting for an address to the list of listeners.
+ MutexLock lock(&new_listeners_requiring_address_mutex_);
+ for (ListenerSet::const_iterator iter =
+ new_listeners_requiring_address_.begin();
+ iter != new_listeners_requiring_address_.end();
+ iter++) {
+ LocationProviderBase::RegisterListener(*iter, true);
+ }
+ new_listeners_requiring_address_.clear();
+
+ request_address_from_last_request_ = request_address_;
+
+ BackoffManager::ReportRequest(url_);
+
+ std::string16 access_token;
+ AccessTokenManager::GetInstance()->GetToken(url_, &access_token);
+
+ // Reset flags
+ is_new_data_available_ = false;
+ is_new_listener_waiting_ = false;
+
+ data_mutex_.Lock();
+ const Position *cached_position =
+ position_cache_->FindPosition(radio_data_, wifi_data_);
+ data_mutex_.Unlock();
+ if (cached_position) {
+ assert(cached_position->IsGoodFix());
+ // Record the position and update its timestamp.
+ position_mutex_.Lock();
+ position_ = *cached_position;
+ position_.timestamp = timestamp_;
+ position_mutex_.Unlock();
+
+ // Let listeners know that we now have a position available.
+ UpdateListeners();
+ return true;
+ }
+
+ assert(request_);
+ is_last_request_complete_ = false;
+ MutexLock data_lock(&data_mutex_);
+ return request_->MakeRequest(access_token,
+ radio_data_,
+ wifi_data_,
+ request_address_,
+ address_language_,
+ kBadLatLng, // We don't have a position to pass
+ kBadLatLng, // to the server.
+ timestamp_);
+}
+
+void NetworkLocationProvider::DeviceDataUpdateAvailableImpl() {
+ timestamp_ = GetCurrentTimeMillis();
+
+ // Signal to the worker thread that new data is available.
+ is_new_data_available_ = true;
+ thread_notification_event_.Signal();
+}
+
+#endif // if 0
diff --git a/chrome/browser/geolocation/network_location_provider.h b/chrome/browser/geolocation/network_location_provider.h
new file mode 100644
index 0000000..fed0001
--- /dev/null
+++ b/chrome/browser/geolocation/network_location_provider.h
@@ -0,0 +1,144 @@
+// Copyright 2008, Google Inc.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// 3. Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GEARS_GEOLOCATION_NETWORK_LOCATION_PROVIDER_H__
+#define GEARS_GEOLOCATION_NETWORK_LOCATION_PROVIDER_H__
+
+// TODO(joth): port to chromium
+#if 0
+
+#include "gears/base/common/common.h"
+#include "gears/base/common/mutex.h"
+#include "gears/base/common/string16.h"
+#include "gears/base/common/thread.h"
+#include "gears/geolocation/device_data_provider.h"
+#include "gears/geolocation/location_provider.h"
+#include "gears/geolocation/network_location_request.h"
+
+// PositionCache is an implementation detail of NetworkLocationProvider.
+class PositionCache;
+
+class NetworkLocationProvider
+ : public LocationProviderBase,
+ public RadioDataProvider::ListenerInterface,
+ public WifiDataProvider::ListenerInterface,
+ public NetworkLocationRequest::ListenerInterface,
+ public Thread {
+ public:
+ NetworkLocationProvider(BrowsingContext *browsing_context,
+ const std::string16 &url,
+ const std::string16 &host_name,
+ const std::string16 &language);
+ virtual ~NetworkLocationProvider();
+
+ // Override LocationProviderBase implementation.
+ virtual void RegisterListener(
+ LocationProviderBase::ListenerInterface *listener,
+ bool request_address);
+ virtual void UnregisterListener(
+ LocationProviderBase::ListenerInterface *listener);
+
+ // LocationProviderBase implementation
+ virtual void GetPosition(Position *position);
+
+ private:
+ // DeviceDataProvider::ListenerInterface implementation.
+ virtual void DeviceDataUpdateAvailable(RadioDataProvider *provider);
+ virtual void DeviceDataUpdateAvailable(WifiDataProvider *provider);
+
+ // NetworkLocationRequest::ListenerInterface implementation.
+ virtual void LocationResponseAvailable(const Position &position,
+ bool server_error,
+ const std::string16 &access_token);
+
+ // Thread implementation
+ virtual void Run();
+
+ // Internal helper used by worker thread to make a network request
+ bool MakeRequest();
+
+ // Internal helper used by DeviceDataUpdateAvailable
+ void DeviceDataUpdateAvailableImpl();
+
+ // The network location request object and the url and host name it will use.
+ NetworkLocationRequest *request_;
+ std::string16 url_;
+ std::string16 host_name_;
+
+ // The device data providers
+ RadioDataProvider *radio_data_provider_;
+ WifiDataProvider *wifi_data_provider_;
+
+ // The radio and wifi data, flags to indicate if each data set is complete,
+ // and their guarding mutex.
+ RadioData radio_data_;
+ WifiData wifi_data_;
+ bool is_radio_data_complete_;
+ bool is_wifi_data_complete_;
+ Mutex data_mutex_;
+
+ // The timestamp for the latest device data update.
+ int64 timestamp_;
+
+ // Parameters for the network request
+ bool request_address_;
+ bool request_address_from_last_request_;
+ std::string16 address_language_;
+
+ // The current best position estimate and its guarding mutex
+ Position position_;
+ Mutex position_mutex_;
+
+ // The event used to notify this object's (ie the network location provider)
+ // worker thread about changes in available data, the network request status
+ // and whether we're shutting down. The booleans are used to indicate what the
+ // event signals.
+ Event thread_notification_event_;
+ bool is_shutting_down_;
+ bool is_new_data_available_;
+ bool is_last_request_complete_;
+ bool is_new_listener_waiting_;
+
+ // When the last request did not request an address, this stores any new
+ // listeners which have been added and require an address to be requested.
+ typedef std::set<LocationProviderBase::ListenerInterface*> ListenerSet;
+ ListenerSet new_listeners_requiring_address_;
+ Mutex new_listeners_requiring_address_mutex_;
+
+ // The earliest timestamp at which the next request can be made, in
+ // milliseconds.
+ int64 earliest_next_request_time_;
+
+ BrowsingContext *browsing_context_;
+
+ // The cache of positions.
+ scoped_ptr<PositionCache> position_cache_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(NetworkLocationProvider);
+};
+
+#endif // if 0
+
+#endif // GEARS_GEOLOCATION_NETWORK_LOCATION_PROVIDER_H__
diff --git a/chrome/browser/geolocation/network_location_request.cc b/chrome/browser/geolocation/network_location_request.cc
new file mode 100644
index 0000000..47bcffe
--- /dev/null
+++ b/chrome/browser/geolocation/network_location_request.cc
@@ -0,0 +1,561 @@
+// Copyright 2008, Google Inc.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// 3. Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// TODO(joth): port to chromium
+#if 0
+
+#include "gears/geolocation/network_location_request.h"
+
+#include "gears/blob/blob_utils.h"
+#include "gears/blob/buffer_blob.h"
+#include "gears/localserver/common/http_constants.h"
+#include "third_party/jsoncpp/reader.h"
+#include "third_party/jsoncpp/value.h"
+#include "third_party/jsoncpp/writer.h"
+
+static const char *kGearsNetworkLocationProtocolVersion = "1.1.0";
+
+static const char *kAccessTokenString = "access_token";
+static const char *kLatitudeString = "latitude";
+static const char *kLongitudeString = "longitude";
+static const char *kAltitudeString = "altitude";
+static const char *kAccuracyString = "accuracy";
+static const char *kAltitudeAccuracyString = "altitude_accuracy";
+// Note that the corresponding JavaScript Position property is 'gearsAddress'.
+static const char *kAddressString = "address";
+static const char *kStreetNumberString = "street_number";
+static const char *kStreetString = "street";
+static const char *kPremisesString = "premises";
+static const char *kCityString = "city";
+static const char *kCountyString = "county";
+static const char *kRegionString = "region";
+static const char *kCountryString = "country";
+static const char *kCountryCodeString = "country_code";
+static const char *kPostalCodeString = "postal_code";
+
+// Local functions
+static const char16* RadioTypeToString(RadioType type);
+// Adds a string if it's valid to the JSON object.
+static void AddString(const std::string &property_name,
+ const std::string16 &value,
+ Json::Value *object);
+// Adds an integer if it's valid to the JSON object.
+static void AddInteger(const std::string &property_name,
+ const int &value,
+ Json::Value *object);
+// Returns true if the value is a valid angle.
+static bool IsValidAngle(const double &value);
+// Parses the server response body. Returns true if parsing was successful.
+static bool ParseServerResponse(const std::string &response_body,
+ int64 timestamp,
+ bool is_reverse_geocode,
+ Position *position,
+ std::string16 *access_token);
+static void AddRadioData(const RadioData &radio_data, Json::Value *body_object);
+static void AddWifiData(const WifiData &wifi_data, Json::Value *body_object);
+
+// static
+NetworkLocationRequest *NetworkLocationRequest::Create(
+ BrowsingContext *browsing_context,
+ const std::string16 &url,
+ const std::string16 &host_name,
+ ListenerInterface *listener) {
+ scoped_ptr<NetworkLocationRequest> request(
+ new NetworkLocationRequest(browsing_context, url, host_name, listener));
+ assert(request.get());
+ if (!request.get() || !request->Init() || !request->Start()) {
+ return NULL;
+ }
+ return request.release();
+}
+
+NetworkLocationRequest::NetworkLocationRequest(
+ BrowsingContext *browsing_context,
+ const std::string16 &url,
+ const std::string16 &host_name,
+ ListenerInterface *listener)
+ : AsyncTask(browsing_context),
+ listener_(listener),
+ url_(url),
+ host_name_(host_name),
+ is_shutting_down_(false) {
+}
+
+bool NetworkLocationRequest::MakeRequest(const std::string16 &access_token,
+ const RadioData &radio_data,
+ const WifiData &wifi_data,
+ bool request_address,
+ const std::string16 &address_language,
+ double latitude,
+ double longitude,
+ int64 timestamp) {
+ is_reverse_geocode_ = request_address &&
+ IsValidAngle(latitude) &&
+ IsValidAngle(longitude);
+ if (!FormRequestBody(host_name_, access_token, radio_data, wifi_data,
+ request_address, address_language, latitude, longitude,
+ is_reverse_geocode_, &post_body_)) {
+ return false;
+ }
+ timestamp_ = timestamp;
+
+ thread_event_.Signal();
+ return true;
+}
+
+// AsyncTask implementation.
+void NetworkLocationRequest::Run() {
+ while (true) {
+ thread_event_.Wait();
+ if (is_shutting_down_) {
+ break;
+ }
+ MakeRequestImpl();
+ }
+}
+
+void NetworkLocationRequest::MakeRequestImpl() {
+ WebCacheDB::PayloadInfo payload;
+ // TODO(andreip): remove this once WebCacheDB::PayloadInfo.data is a Blob.
+ scoped_refptr<BlobInterface> payload_data;
+ bool result = HttpPost(url_.c_str(),
+ false, // Not capturing, so follow redirects
+ NULL, // reason_header_value
+ HttpConstants::kMimeApplicationJson, // Content-Type
+ NULL, // mod_since_date
+ NULL, // required_cookie
+ true, // disable_browser_cookies
+ post_body_.get(),
+ &payload,
+ &payload_data,
+ NULL, // was_redirected
+ NULL, // full_redirect_url
+ NULL); // error_message
+
+ MutexLock lock(&is_processing_response_mutex_);
+ // is_aborted_ may be true even if HttpPost succeeded.
+ if (is_aborted_) {
+ LOG(("NetworkLocationRequest::Run() : HttpPost request was cancelled.\n"));
+ return;
+ }
+
+ if (listener_) {
+ Position position;
+ std::string response_body;
+ if (result) {
+ // If HttpPost succeeded, payload_data is guaranteed to be non-NULL.
+ assert(payload_data.get());
+ if (!payload_data->Length() ||
+ !BlobToString(payload_data.get(), &response_body)) {
+ LOG(("NetworkLocationRequest::Run() : Failed to get response body.\n"));
+ }
+ }
+ std::string16 access_token;
+ GetLocationFromResponse(result, payload.status_code, response_body,
+ timestamp_, url_, is_reverse_geocode_,
+ &position, &access_token);
+
+ LOG(("NetworkLocationRequest::Run() : Calling listener with position.\n"));
+ bool server_error =
+ !result || (payload.status_code >= 500 && payload.status_code < 600);
+ listener_->LocationResponseAvailable(position, server_error, access_token);
+ }
+}
+
+// static
+bool NetworkLocationRequest::FormRequestBody(
+ const std::string16 &host_name,
+ const std::string16 &access_token,
+ const RadioData &radio_data,
+ const WifiData &wifi_data,
+ bool request_address,
+ std::string16 address_language,
+ double latitude,
+ double longitude,
+ bool is_reverse_geocode,
+ scoped_refptr<BlobInterface> *blob) {
+ assert(blob);
+ Json::Value body_object;
+ assert(body_object.isObject());
+ // Version and host are required.
+ if (host_name.empty()) {
+ return false;
+ }
+ body_object["version"] = Json::Value(kGearsNetworkLocationProtocolVersion);
+ AddString("host", host_name, &body_object);
+
+ AddString("access_token", access_token, &body_object);
+
+ body_object["request_address"] = request_address;
+ AddString("address_language", address_language, &body_object);
+
+ if (is_reverse_geocode) {
+ assert(request_address);
+ assert(IsValidAngle(latitude) && IsValidAngle(longitude));
+ Json::Value location;
+ location["latitude"] = Json::Value(latitude);
+ location["longitude"] = Json::Value(longitude);
+ body_object["location"] = location;
+ } else {
+ AddRadioData(radio_data, &body_object);
+ AddWifiData(wifi_data, &body_object);
+ }
+
+ Json::FastWriter writer;
+ // We always use the platform independent 'C' locale when writing the JSON
+ // request, irrespective of the browser's locale. This avoids the need for
+ // the network location provider to determine the locale of the request and
+ // parse the JSON accordingly.
+#ifdef OS_WINCE
+ // WinCE does not support setlocale.
+#else
+ char *current_locale = setlocale(LC_NUMERIC, "C");
+#endif
+ std::string body_string = writer.write(body_object);
+#ifdef OS_WINCE
+ // WinCE does not support setlocale.
+#else
+ setlocale(LC_NUMERIC, current_locale);
+#endif
+ LOG(("NetworkLocationRequest::FormRequestBody(): Formed body %s.\n",
+ body_string.c_str()));
+
+ blob->reset(new BufferBlob(body_string.c_str(), body_string.size()));
+ return true;
+}
+
+// static
+void NetworkLocationRequest::GetLocationFromResponse(
+ bool http_post_result,
+ int status_code,
+ const std::string &response_body,
+ int64 timestamp,
+ const std::string16 &server_url,
+ bool is_reverse_geocode,
+ Position *position,
+ std::string16 *access_token) {
+ assert(position);
+ assert(access_token);
+
+ // HttpPost can fail for a number of reasons. Most likely this is because
+ // we're offline, or there was no response.
+ if (!http_post_result) {
+ LOG(("NetworkLocationRequest::GetLocationFromResponse() : HttpPost request "
+ "failed.\n"));
+ position->error_code = Position::ERROR_CODE_POSITION_UNAVAILABLE;
+ position->error_message = STRING16(L"No response from network provider "
+ L"at ");
+ position->error_message += server_url.c_str();
+ position->error_message += STRING16(L".");
+ } else if (status_code == HttpConstants::HTTP_OK) {
+ // We use the timestamp from the device data that was used to generate
+ // this position fix.
+ if (ParseServerResponse(response_body, timestamp, is_reverse_geocode,
+ position, access_token)) {
+ // The response was successfully parsed, but it may not be a valid
+ // position fix.
+ if (!position->IsGoodFix()) {
+ position->error_code = Position::ERROR_CODE_POSITION_UNAVAILABLE;
+ position->error_message = STRING16(L"Network provider at ");
+ position->error_message += server_url.c_str();
+ position->error_message += STRING16(L" did not provide a good position "
+ L"fix.");
+ }
+ } else {
+ // We failed to parse the repsonse.
+ LOG(("NetworkLocationRequest::GetLocationFromResponse() : Response "
+ "malformed.\n"));
+ position->error_code = Position::ERROR_CODE_POSITION_UNAVAILABLE;
+ position->error_message = STRING16(L"Response from network provider at ");
+ position->error_message += server_url.c_str();
+ position->error_message += STRING16(L" was malformed.");
+ }
+ } else {
+ // The response was bad.
+ LOG(("NetworkLocationRequest::GetLocationFromResponse() : HttpPost "
+ "response was bad.\n"));
+ position->error_code = Position::ERROR_CODE_POSITION_UNAVAILABLE;
+ position->error_message = STRING16(L"Network provider at ");
+ position->error_message += server_url.c_str();
+ position->error_message += STRING16(L" returned error code ");
+ position->error_message += IntegerToString16(status_code);
+ position->error_message += STRING16(L".");
+ }
+}
+
+void NetworkLocationRequest::StopThreadAndDelete() {
+ // The FF implementation of AsyncTask::Abort() delivers a message to the UI
+ // thread to cancel the request. So if we call this method on the UI thread,
+ // we must return to the OS before the call to Abort() will take effect. In
+ // particular, we can't call Abort() then block here waiting for HttpPost to
+ // return.
+ is_shutting_down_ = true;
+ thread_event_.Signal();
+ is_processing_response_mutex_.Lock();
+ Abort();
+ is_processing_response_mutex_.Unlock();
+ DeleteWhenDone();
+}
+
+// Local functions.
+
+static const char16* RadioTypeToString(RadioType type) {
+ switch (type) {
+ case RADIO_TYPE_UNKNOWN:
+ return STRING16(L"unknown");
+ case RADIO_TYPE_GSM:
+ return STRING16(L"gsm");
+ case RADIO_TYPE_CDMA:
+ return STRING16(L"cdma");
+ case RADIO_TYPE_WCDMA:
+ return STRING16(L"wcdma");
+ default:
+ assert(false);
+ }
+ return NULL;
+}
+
+static void AddString(const std::string &property_name,
+ const std::string16 &value,
+ Json::Value *object) {
+ assert(object);
+ assert(object->isObject());
+ if (!value.empty()) {
+ std::string value_utf8;
+ if (String16ToUTF8(value.c_str(), value.size(), &value_utf8)) {
+ (*object)[property_name] = Json::Value(value_utf8);
+ }
+ }
+}
+
+static void AddInteger(const std::string &property_name,
+ const int &value,
+ Json::Value *object) {
+ assert(object);
+ assert(object->isObject());
+ if (kint32min != value) {
+ (*object)[property_name] = Json::Value(value);
+ }
+}
+
+static bool IsValidAngle(const double &value) {
+ return value >= -180.0 && value <= 180.0;
+}
+
+// Numeric values without a decimal point have type integer and IsDouble() will
+// return false. This is convenience function for detecting integer or floating
+// point numeric values. Note that isIntegral() includes boolean values, which
+// is not what we want.
+static bool IsDoubleOrInt(const Json::Value &object,
+ const std::string &property_name) {
+ return object[property_name].isDouble() || object[property_name].isInt();
+}
+
+// The JsValue::asXXX() methods return zero if a property isn't specified. For
+// our purposes, zero is a valid value, so we have to test for existence.
+
+// Gets a double if it's present.
+static bool GetAsDouble(const Json::Value &object,
+ const std::string &property_name,
+ double *out) {
+ assert(out);
+ if (!IsDoubleOrInt(object, property_name)) {
+ return false;
+ }
+ *out = object[property_name].asDouble();
+ return true;
+}
+
+// Gets a string if it's present.
+static bool GetAsString(const Json::Value &object,
+ const std::string &property_name,
+ std::string16 *out) {
+ assert(out);
+ if (!object[property_name].isString()) {
+ return false;
+ }
+ std::string out_utf8 = object[property_name].asString();
+ return UTF8ToString16(out_utf8.c_str(), out_utf8.size(), out);
+}
+
+static bool ParseServerResponse(const std::string &response_body,
+ int64 timestamp,
+ bool is_reverse_geocode,
+ Position *position,
+ std::string16 *access_token) {
+ assert(position);
+ assert(access_token);
+
+ if (response_body.empty()) {
+ LOG(("ParseServerResponse() : Response was empty.\n"));
+ return false;
+ }
+ LOG(("ParseServerResponse() : Parsing response %s.\n",
+ response_body.c_str()));
+
+ // Parse the response, ignoring comments. The JSON reposne from the network
+ // location provider should always use the 'C' locale.
+ Json::Reader reader;
+ Json::Value response_object;
+#ifdef OS_WINCE
+ // WinCE does not support setlocale.
+#else
+ char *current_locale = setlocale(LC_NUMERIC, "C");
+#endif
+ bool res = reader.parse(response_body, response_object, false);
+#ifdef OS_WINCE
+ // WinCE does not support setlocale.
+#else
+ setlocale(LC_NUMERIC, current_locale);
+#endif
+ if (!res) {
+ LOG(("ParseServerResponse() : Failed to parse response : %s.\n",
+ reader.getFormatedErrorMessages().c_str()));
+ return false;
+ }
+
+ if (!response_object.isObject()) {
+ LOG(("ParseServerResponse() : Unexpected response type: %d.\n",
+ response_object.type()));
+ return false;
+ }
+
+ // Get the access token.
+ GetAsString(response_object, kAccessTokenString, access_token);
+
+ // Get the location
+ Json::Value location = response_object["location"];
+
+ // If the network provider was unable to provide a position fix, it should
+ // return a 200 with location == null.
+ if (location.type() == Json::nullValue) {
+ LOG(("ParseServerResponse() : Location is null.\n"));
+ return true;
+ }
+
+ // If location is not null, it must be an object.
+ if (!location.isObject()) {
+ return false;
+ }
+
+ // latitude and longitude fields are always required.
+ if (!GetAsDouble(location, kLatitudeString, &position->latitude) ||
+ !GetAsDouble(location, kLongitudeString, &position->longitude)) {
+ return false;
+ }
+
+ // If it's not a reverse geocode request, the accuracy field is also required.
+ if (is_reverse_geocode) {
+ position->accuracy = 0.0;
+ } else {
+ if (!GetAsDouble(location, kAccuracyString, &position->accuracy)) {
+ return false;
+ }
+ }
+
+ // Other fields are optional.
+ GetAsDouble(location, kAltitudeString, &position->altitude);
+ GetAsDouble(location, kAltitudeAccuracyString, &position->altitude_accuracy);
+ Json::Value address = location[kAddressString];
+ if (address.isObject()) {
+ GetAsString(address, kStreetNumberString, &position->address.street_number);
+ GetAsString(address, kStreetString, &position->address.street);
+ GetAsString(address, kPremisesString, &position->address.premises);
+ GetAsString(address, kCityString, &position->address.city);
+ GetAsString(address, kCountyString, &position->address.county);
+ GetAsString(address, kRegionString, &position->address.region);
+ GetAsString(address, kCountryString, &position->address.country);
+ GetAsString(address, kCountryCodeString, &position->address.country_code);
+ GetAsString(address, kPostalCodeString, &position->address.postal_code);
+ }
+
+ position->timestamp = timestamp;
+ return true;
+}
+
+static void AddRadioData(const RadioData &radio_data,
+ Json::Value *body_object) {
+ assert(body_object);
+
+ AddInteger("home_mobile_country_code", radio_data.home_mobile_country_code,
+ body_object);
+ AddInteger("home_mobile_network_code", radio_data.home_mobile_network_code,
+ body_object);
+ AddString("radio_type", RadioTypeToString(radio_data.radio_type),
+ body_object);
+ AddString("carrier", radio_data.carrier, body_object);
+
+ Json::Value cell_towers;
+ assert(cell_towers.isArray());
+ int num_cell_towers = static_cast<int>(radio_data.cell_data.size());
+ for (int i = 0; i < num_cell_towers; ++i) {
+ Json::Value cell_tower;
+ assert(cell_tower.isObject());
+ AddInteger("cell_id", radio_data.cell_data[i].cell_id, &cell_tower);
+ AddInteger("location_area_code", radio_data.cell_data[i].location_area_code,
+ &cell_tower);
+ AddInteger("mobile_country_code",
+ radio_data.cell_data[i].mobile_country_code, &cell_tower);
+ AddInteger("mobile_network_code",
+ radio_data.cell_data[i].mobile_network_code, &cell_tower);
+ AddInteger("age", radio_data.cell_data[i].age, &cell_tower);
+ AddInteger("signal_strength", radio_data.cell_data[i].radio_signal_strength,
+ &cell_tower);
+ AddInteger("timing_advance", radio_data.cell_data[i].timing_advance,
+ &cell_tower);
+ cell_towers[i] = cell_tower;
+ }
+ if (num_cell_towers > 0) {
+ (*body_object)["cell_towers"] = cell_towers;
+ }
+}
+
+static void AddWifiData(const WifiData &wifi_data, Json::Value *body_object) {
+ assert(body_object);
+
+ if (wifi_data.access_point_data.empty()) {
+ return;
+ }
+
+ Json::Value wifi_towers;
+ assert(wifi_towers.isArray());
+ for (WifiData::AccessPointDataSet::const_iterator iter =
+ wifi_data.access_point_data.begin();
+ iter != wifi_data.access_point_data.end();
+ iter++) {
+ Json::Value wifi_tower;
+ assert(wifi_tower.isObject());
+ AddString("mac_address", iter->mac_address, &wifi_tower);
+ AddInteger("signal_strength", iter->radio_signal_strength, &wifi_tower);
+ AddInteger("age", iter->age, &wifi_tower);
+ AddInteger("channel", iter->channel, &wifi_tower);
+ AddInteger("signal_to_noise", iter->signal_to_noise, &wifi_tower);
+ AddString("ssid", iter->ssid, &wifi_tower);
+ wifi_towers.append(wifi_tower);
+ }
+ (*body_object)["wifi_towers"] = wifi_towers;
+}
+
+#endif // if 0
diff --git a/chrome/browser/geolocation/network_location_request.h b/chrome/browser/geolocation/network_location_request.h
new file mode 100644
index 0000000..18a9081
--- /dev/null
+++ b/chrome/browser/geolocation/network_location_request.h
@@ -0,0 +1,141 @@
+// Copyright 2008, Google Inc.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// 3. Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GEARS_GEOLOCATION_NETWORK_LOCATION_REQUEST_H__
+#define GEARS_GEOLOCATION_NETWORK_LOCATION_REQUEST_H__
+
+// TODO(joth): port to chromium
+#if 0
+
+#include <vector>
+#include "gears/base/common/basictypes.h" // For int64
+#include "gears/base/common/common.h"
+#include "gears/base/common/event.h"
+#include "gears/blob/blob.h"
+#include "gears/geolocation/geolocation.h"
+#include "gears/geolocation/device_data_provider.h"
+#include "gears/localserver/common/async_task.h"
+
+// An implementation of an AsyncTask that takes a set of device data and sends
+// it to a server to get a position fix. It performs formatting of the request
+// and interpretation of the response.
+class NetworkLocationRequest : public AsyncTask {
+ public:
+ friend class scoped_ptr<NetworkLocationRequest>; // For use in Create().
+
+ // Interface for receiving callbacks from a NetworkLocationRequest object.
+ class ListenerInterface {
+ public:
+ // Updates the listener with a new position. server_error indicates whether
+ // was a server or network error - either no response or a 500 error code.
+ virtual void LocationResponseAvailable(
+ const Position &position,
+ bool server_error,
+ const std::string16 &access_token) = 0;
+ };
+
+ // Creates the object and starts its worker thread running. Returns NULL if
+ // creation or initialisation fails.
+ static NetworkLocationRequest* Create(BrowsingContext *browsing_context,
+ const std::string16 &url,
+ const std::string16 &host_name,
+ ListenerInterface *listener);
+ bool MakeRequest(const std::string16 &access_token,
+ const RadioData &radio_data,
+ const WifiData &wifi_data,
+ bool request_address,
+ const std::string16 &address_language,
+ double latitude,
+ double longitude,
+ int64 timestamp);
+ // This method aborts any pending request and instructs the worker thread to
+ // terminate. The object is destructed once the thread terminates. This
+ // method blocks until the AsyncTask::Run() implementation is complete, after
+ // which the thread will not attempt to access external resources such as the
+ // listener.
+ void StopThreadAndDelete();
+
+ private:
+ // Private constructor and destructor. Callers should use Create() and
+ // StopThreadAndDelete().
+ NetworkLocationRequest(BrowsingContext *browsing_context,
+ const std::string16 &url,
+ const std::string16 &host_name,
+ ListenerInterface *listener);
+ virtual ~NetworkLocationRequest() {}
+
+ void MakeRequestImpl();
+
+ // AsyncTask implementation.
+ virtual void Run();
+
+ static bool FormRequestBody(const std::string16 &host_name,
+ const std::string16 &access_token,
+ const RadioData &radio_data,
+ const WifiData &wifi_data,
+ bool request_address,
+ std::string16 address_language,
+ double latitude,
+ double longitude,
+ bool is_reverse_geocode,
+ scoped_refptr<BlobInterface> *blob);
+
+ static void GetLocationFromResponse(bool http_post_result,
+ int status_code,
+ const std::string &response_body,
+ int64 timestamp,
+ const std::string16 &server_url,
+ bool is_reverse_geocode,
+ Position *position,
+ std::string16 *access_token);
+
+ int64 timestamp_; // The timestamp of the data used to make the request.
+ scoped_refptr<BlobInterface> post_body_;
+ ListenerInterface *listener_;
+ std::string16 url_;
+ std::string16 host_name_;
+
+ Mutex is_processing_response_mutex_;
+
+ bool is_reverse_geocode_;
+
+ Event thread_event_;
+ bool is_shutting_down_;
+
+#ifdef USING_CCTESTS
+ // Uses FormRequestBody for testing.
+ friend void TestGeolocationFormRequestBody(JsCallContext *context);
+ // Uses GetLocationFromResponse for testing.
+ friend void TestGeolocationGetLocationFromResponse(
+ JsCallContext *context,
+ JsRunnerInterface *js_runner);
+#endif
+
+ DISALLOW_EVIL_CONSTRUCTORS(NetworkLocationRequest);
+};
+
+#endif // if 0
+
+#endif // GEARS_GEOLOCATION_NETWORK_LOCATION_REQUEST_H__