summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authormvanouwerkerk@chromium.org <mvanouwerkerk@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-23 15:01:17 +0000
committermvanouwerkerk@chromium.org <mvanouwerkerk@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-23 15:01:17 +0000
commit296a9999fb46f314cfcc5492265273d99e6ced5c (patch)
treefd6b1d2e11937ef1b0988ee23f994c54b48cbd4e /content
parentdda540b9975640716d72b9b954750541a826f2c2 (diff)
downloadchromium_src-296a9999fb46f314cfcc5492265273d99e6ced5c.zip
chromium_src-296a9999fb46f314cfcc5492265273d99e6ced5c.tar.gz
chromium_src-296a9999fb46f314cfcc5492265273d99e6ced5c.tar.bz2
Replace DeviceDataProvider with the non-templated WifiDataProvider.
Also replace DeviceDataProvider::ListenerInterface with WifiDataProvider::WifiDataUpdateCallback. I would have preferred to do that as a separate change, but removing the templating revealed a nasty circular dependency that involved this nested class, which made forward declarations impossible. So, all in one go then. I also deleted device_data_provider_unittest.cc as its purpose was to test for threading failures. These data providers no longer start their own threads, see https://codereview.chromium.org/22866005/ BUG=103713 TBR=jam Review URL: https://chromiumcodereview.appspot.com/23181009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@219279 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/browser/geolocation/device_data_provider.h297
-rw-r--r--content/browser/geolocation/device_data_provider_unittest.cc41
-rw-r--r--content/browser/geolocation/empty_device_data_provider.cc18
-rw-r--r--content/browser/geolocation/empty_device_data_provider.h36
-rw-r--r--content/browser/geolocation/empty_wifi_data_provider.cc29
-rw-r--r--content/browser/geolocation/empty_wifi_data_provider.h31
-rw-r--r--content/browser/geolocation/network_location_provider.cc62
-rw-r--r--content/browser/geolocation/network_location_provider.h37
-rw-r--r--content/browser/geolocation/network_location_provider_unittest.cc59
-rw-r--r--content/browser/geolocation/network_location_request.cc2
-rw-r--r--content/browser/geolocation/network_location_request.h4
-rw-r--r--content/browser/geolocation/wifi_data.cc (renamed from content/browser/geolocation/device_data_provider.cc)14
-rw-r--r--content/browser/geolocation/wifi_data.h54
-rw-r--r--content/browser/geolocation/wifi_data_provider.cc95
-rw-r--r--content/browser/geolocation/wifi_data_provider.h195
-rw-r--r--content/browser/geolocation/wifi_data_provider_chromeos.cc9
-rw-r--r--content/browser/geolocation/wifi_data_provider_chromeos.h2
-rw-r--r--content/browser/geolocation/wifi_data_provider_common.cc2
-rw-r--r--content/browser/geolocation/wifi_data_provider_common.h10
-rw-r--r--content/browser/geolocation/wifi_data_provider_common_unittest.cc49
-rw-r--r--content/browser/geolocation/wifi_data_provider_common_win.cc1
-rw-r--r--content/browser/geolocation/wifi_data_provider_common_win.h2
-rw-r--r--content/browser/geolocation/wifi_data_provider_linux.cc1
-rw-r--r--content/browser/geolocation/wifi_data_provider_mac.cc1
-rw-r--r--content/browser/geolocation/wifi_data_provider_win.cc1
-rw-r--r--content/content_browser.gypi10
-rw-r--r--content/content_tests.gypi4
27 files changed, 532 insertions, 534 deletions
diff --git a/content/browser/geolocation/device_data_provider.h b/content/browser/geolocation/device_data_provider.h
deleted file mode 100644
index 3c69fe8..0000000
--- a/content/browser/geolocation/device_data_provider.h
+++ /dev/null
@@ -1,297 +0,0 @@
-// Copyright (c) 2012 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.
-
-// A device data provider provides data from the device that is used by a
-// NetworkLocationProvider to obtain a position fix. This data may be either
-// wifi data or (currently not used) cell radio data. For a given type of data,
-// we use a singleton instance of the device data provider, which is used by
-// multiple NetworkLocationProvider objects.
-//
-// This file provides DeviceDataProvider, which provides static methods to
-// access the singleton instance. The singleton instance uses a private
-// implementation to abstract across platforms and also to allow mock providers
-// to be used for testing.
-//
-// This file also provides DeviceDataProviderImplBase, a base class which
-// provides common functionality for the private implementations.
-//
-// This file also declares the data structure used to represent wifi data.
-
-#ifndef CONTENT_BROWSER_GEOLOCATION_DEVICE_DATA_PROVIDER_H_
-#define CONTENT_BROWSER_GEOLOCATION_DEVICE_DATA_PROVIDER_H_
-
-#include <set>
-
-#include "base/basictypes.h"
-#include "base/bind.h"
-#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_util.h"
-#include "content/common/content_export.h"
-
-namespace content {
-
-// Wifi data relating to a single access point.
-struct CONTENT_EXPORT AccessPointData {
- AccessPointData();
- ~AccessPointData();
-
- // MAC address, formatted as per MacAddressAsString16.
- string16 mac_address;
- int radio_signal_strength; // Measured in dBm
- int channel;
- int signal_to_noise; // Ratio in dB
- string16 ssid; // Network identifier
-};
-
-// This is to allow AccessPointData to be used in std::set. We order
-// lexicographically by MAC address.
-struct AccessPointDataLess {
- bool operator()(const AccessPointData& data1,
- const AccessPointData& data2) const {
- return data1.mac_address < data2.mac_address;
- }
-};
-
-// All data for wifi.
-struct CONTENT_EXPORT WifiData {
- WifiData();
- ~WifiData();
-
- // Determines whether a new set of WiFi data differs significantly from this.
- bool DiffersSignificantly(const WifiData& other) const;
-
- // Store access points as a set, sorted by MAC address. This allows quick
- // comparison of sets for detecting changes and for caching.
- typedef std::set<AccessPointData, AccessPointDataLess> AccessPointDataSet;
- AccessPointDataSet access_point_data;
-};
-
-template<typename DataType>
-class DeviceDataProvider;
-
-// This class just exists to work-around MSVC2005 not being able to have a
-// template class implement RefCountedThreadSafe
-class CONTENT_EXPORT DeviceDataProviderImplBaseHack
- : public base::RefCountedThreadSafe<DeviceDataProviderImplBaseHack> {
- protected:
- friend class base::RefCountedThreadSafe<DeviceDataProviderImplBaseHack>;
- virtual ~DeviceDataProviderImplBaseHack() {}
-};
-
-// See class DeviceDataProvider for the public client API.
-// DeviceDataProvider uses containment to hide platform-specific implementation
-// details from common code. This class provides common functionality for these
-// contained implementation classes. This is a modified pimpl pattern: this
-// class needs to be in the public header due to use of templating.
-template<typename DataType>
-class DeviceDataProviderImplBase : public DeviceDataProviderImplBaseHack {
- public:
- DeviceDataProviderImplBase()
- : container_(NULL), client_loop_(base::MessageLoop::current()) {
- DCHECK(client_loop_);
- }
-
- // Tells the provider to start looking for data. Listeners will start
- // receiving notifications after this call.
- virtual void StartDataProvider() = 0;
- // Tells the provider to stop looking for data. Listeners will stop
- // receiving notifications after this call.
- virtual void StopDataProvider() = 0;
- virtual bool GetData(DataType* data) = 0;
-
- // Sets the container of this class, which is of type DeviceDataProvider.
- // This is required to pass as a parameter when making the callback to
- // listeners.
- void SetContainer(DeviceDataProvider<DataType>* container) {
- container_ = container;
- }
-
- typedef typename DeviceDataProvider<DataType>::ListenerInterface
- ListenerInterface;
- void AddListener(ListenerInterface* listener) {
- listeners_.insert(listener);
- }
- bool RemoveListener(ListenerInterface* listener) {
- return listeners_.erase(listener) == 1;
- }
-
- bool has_listeners() const {
- return !listeners_.empty();
- }
-
- protected:
- virtual ~DeviceDataProviderImplBase() {}
-
- // Calls DeviceDataUpdateAvailable() on all registered listeners.
- typedef std::set<ListenerInterface*> ListenersSet;
- void NotifyListeners() {
- // Always make the notify callback via a posted task, so we can unwind
- // callstack here and make callback without causing client re-entrancy.
- client_loop_->PostTask(FROM_HERE, base::Bind(
- &DeviceDataProviderImplBase<DataType>::DoNotifyListeners,
- this));
- }
-
- bool CalledOnClientThread() const {
- return base::MessageLoop::current() == this->client_loop_;
- }
-
- base::MessageLoop* client_loop() const { return client_loop_; }
-
- private:
- void DoNotifyListeners() {
- // It's possible that all the listeners (and the container) went away
- // whilst this task was pending. This is fine; the loop will be a no-op.
- typename ListenersSet::const_iterator iter = listeners_.begin();
- while (iter != listeners_.end()) {
- ListenerInterface* listener = *iter;
- ++iter; // Advance iter before callback, in case listener unregisters.
- listener->DeviceDataUpdateAvailable(container_);
- }
- }
-
- DeviceDataProvider<DataType>* container_;
-
- // Reference to the client's message loop, all callbacks and access to
- // the listeners_ member should happen in this context.
- base::MessageLoop* client_loop_;
-
- ListenersSet listeners_;
-
- DISALLOW_COPY_AND_ASSIGN(DeviceDataProviderImplBase);
-};
-
-typedef DeviceDataProviderImplBase<WifiData> WifiDataProviderImplBase;
-
-// A device data provider
-//
-// We use a singleton instance of this class which is shared by multiple network
-// location providers. These location providers access the instance through the
-// Register and Unregister methods.
-template<typename DataType>
-class DeviceDataProvider {
- public:
- // Interface to be implemented by listeners to a device data provider.
- class ListenerInterface {
- public:
- // Will be called in the context of the thread that called Register().
- virtual void DeviceDataUpdateAvailable(
- DeviceDataProvider<DataType>* provider) = 0;
- virtual ~ListenerInterface() {}
- };
-
- // Sets the factory function which will be used by Register to create the
- // implementation used by the singleton instance. This factory approach is
- // used both to abstract accross platform-specific implementations and to
- // inject mock implementations for testing.
- typedef DeviceDataProviderImplBase<DataType>* (*ImplFactoryFunction)(void);
- static void SetFactory(ImplFactoryFunction factory_function_in) {
- factory_function_ = factory_function_in;
- }
-
- static void ResetFactory() {
- factory_function_ = DefaultFactoryFunction;
- }
-
- // Adds a listener, which will be called back with DeviceDataUpdateAvailable
- // whenever new data is available. Returns the singleton instance.
- static DeviceDataProvider* Register(ListenerInterface* listener) {
- bool need_to_start_provider = false;
- if (!instance_) {
- instance_ = new DeviceDataProvider();
- need_to_start_provider = true;
- }
- DCHECK(instance_);
- instance_->AddListener(listener);
- // Start the provider after adding the listener, to avoid any race in
- // it receiving an early callback.
- if (need_to_start_provider)
- instance_->StartDataProvider();
- return instance_;
- }
-
- // Removes a listener. If this is the last listener, deletes the singleton
- // instance. Return value indicates success.
- static bool Unregister(ListenerInterface* listener) {
- DCHECK(instance_);
- DCHECK(instance_->has_listeners());
- if (!instance_->RemoveListener(listener)) {
- return false;
- }
- if (!instance_->has_listeners()) {
- // Must stop the provider (and any implementation threads) before
- // destroying to avoid any race conditions in access to the provider in
- // the destructor chain.
- instance_->StopDataProvider();
- delete instance_;
- instance_ = NULL;
- }
- return true;
- }
-
- // Provides whatever data the provider has, which may be nothing. Return
- // value indicates whether this is all the data the provider could ever
- // obtain.
- bool GetData(DataType* data) {
- return impl_->GetData(data);
- }
-
- private:
- // Private constructor and destructor, callers access singleton through
- // Register and Unregister.
- DeviceDataProvider() {
- DCHECK(factory_function_);
- impl_ = (*factory_function_)();
- DCHECK(impl_.get());
- impl_->SetContainer(this);
- }
- virtual ~DeviceDataProvider() {
- DCHECK(impl_.get());
- impl_->SetContainer(NULL);
- }
-
- void AddListener(ListenerInterface* listener) {
- impl_->AddListener(listener);
- }
-
- bool RemoveListener(ListenerInterface* listener) {
- return impl_->RemoveListener(listener);
- }
-
- bool has_listeners() const {
- return impl_->has_listeners();
- }
-
- void StartDataProvider() {
- impl_->StartDataProvider();
- }
-
- void StopDataProvider() {
- impl_->StopDataProvider();
- }
-
- CONTENT_EXPORT static DeviceDataProviderImplBase<DataType>*
- DefaultFactoryFunction();
-
- // The singleton-like instance of this class. (Not 'true' singleton, as it
- // may go through multiple create/destroy/create cycles per process instance,
- // e.g. when under test).
- CONTENT_EXPORT static DeviceDataProvider* instance_;
-
- // The factory function used to create the singleton instance.
- CONTENT_EXPORT static ImplFactoryFunction factory_function_;
-
- // The internal implementation.
- scoped_refptr<DeviceDataProviderImplBase<DataType> > impl_;
-
- DISALLOW_COPY_AND_ASSIGN(DeviceDataProvider);
-};
-
-typedef DeviceDataProvider<WifiData> WifiDataProvider;
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_GEOLOCATION_DEVICE_DATA_PROVIDER_H_
diff --git a/content/browser/geolocation/device_data_provider_unittest.cc b/content/browser/geolocation/device_data_provider_unittest.cc
deleted file mode 100644
index 42a678c..0000000
--- a/content/browser/geolocation/device_data_provider_unittest.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2012 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 "base/threading/platform_thread.h"
-#include "content/browser/geolocation/device_data_provider.h"
-#include "content/browser/geolocation/wifi_data_provider_common.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-class NullWifiDataListenerInterface
- : public WifiDataProviderCommon::ListenerInterface {
- public:
- // ListenerInterface
- virtual void DeviceDataUpdateAvailable(
- DeviceDataProvider<WifiData>* provider) OVERRIDE {}
-};
-
-TEST(GeolocationDeviceDataProviderWifiData, CreateDestroy) {
- // See http://crbug.com/59913 . The main_message_loop is not required to be
- // run for correct behaviour, but we run it in this test to help smoke out
- // any race conditions between processing in the main loop and the setup /
- // tear down of the DeviceDataProvider thread.
- base::MessageLoopForUI main_message_loop;
- NullWifiDataListenerInterface listener;
- for (int i = 0; i < 10; i++) {
- DeviceDataProvider<WifiData>::Register(&listener);
- for (int j = 0; j < 10; j++) {
- base::PlatformThread::Sleep(base::TimeDelta());
- main_message_loop.RunUntilIdle(); // See comment above
- }
- DeviceDataProvider<WifiData>::Unregister(&listener);
- for (int j = 0; j < 10; j++) {
- base::PlatformThread::Sleep(base::TimeDelta());
- main_message_loop.RunUntilIdle(); // See comment above
- }
- }
-}
-
-} // namespace content
diff --git a/content/browser/geolocation/empty_device_data_provider.cc b/content/browser/geolocation/empty_device_data_provider.cc
deleted file mode 100644
index 57e25b0..0000000
--- a/content/browser/geolocation/empty_device_data_provider.cc
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) 2012 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 "content/browser/geolocation/empty_device_data_provider.h"
-
-namespace content {
-
-// Only define for platforms that lack a real wifi data provider.
-#if !defined(OS_WIN) && !defined(OS_MACOSX) && !defined(OS_LINUX)
-// static
-template<>
-WifiDataProviderImplBase* WifiDataProvider::DefaultFactoryFunction() {
- return new EmptyDeviceDataProvider<WifiData>();
-}
-#endif
-
-} // namespace content
diff --git a/content/browser/geolocation/empty_device_data_provider.h b/content/browser/geolocation/empty_device_data_provider.h
deleted file mode 100644
index eb526d9..0000000
--- a/content/browser/geolocation/empty_device_data_provider.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2012 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.
-
-#ifndef CONTENT_BROWSER_GEOLOCATION_EMPTY_DEVICE_DATA_PROVIDER_H_
-#define CONTENT_BROWSER_GEOLOCATION_EMPTY_DEVICE_DATA_PROVIDER_H_
-
-#include "content/browser/geolocation/device_data_provider.h"
-
-namespace content {
-
-// An implementation of DeviceDataProviderImplBase that does not provide any
-// data. Used on platforms where a given data type is not available.
-
-template<typename DataType>
-class EmptyDeviceDataProvider : public DeviceDataProviderImplBase<DataType> {
- public:
- EmptyDeviceDataProvider() {}
- virtual ~EmptyDeviceDataProvider() {}
-
- // DeviceDataProviderImplBase implementation
- virtual void StartDataProvider() { }
- virtual void StopDataProvider() { }
- virtual bool GetData(DataType *data) {
- DCHECK(data);
- // This is all the data we can get - nothing.
- return true;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(EmptyDeviceDataProvider);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_GEOLOCATION_EMPTY_DEVICE_DATA_PROVIDER_H_
diff --git a/content/browser/geolocation/empty_wifi_data_provider.cc b/content/browser/geolocation/empty_wifi_data_provider.cc
new file mode 100644
index 0000000..7255f46
--- /dev/null
+++ b/content/browser/geolocation/empty_wifi_data_provider.cc
@@ -0,0 +1,29 @@
+// Copyright 2013 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 "content/browser/geolocation/empty_wifi_data_provider.h"
+
+namespace content {
+
+EmptyWifiDataProvider::EmptyWifiDataProvider() {
+}
+
+EmptyWifiDataProvider::~EmptyWifiDataProvider() {
+}
+
+bool EmptyWifiDataProvider::GetData(WifiData* data) {
+ DCHECK(data);
+ // This is all the data we can get - nothing.
+ return true;
+}
+
+// Only define for platforms that lack a real wifi data provider.
+#if !defined(OS_WIN) && !defined(OS_MACOSX) && !defined(OS_LINUX)
+// static
+WifiDataProviderImplBase* WifiDataProvider::DefaultFactoryFunction() {
+ return new EmptyWifiDataProvider();
+}
+#endif
+
+} // namespace content
diff --git a/content/browser/geolocation/empty_wifi_data_provider.h b/content/browser/geolocation/empty_wifi_data_provider.h
new file mode 100644
index 0000000..a02ed2b
--- /dev/null
+++ b/content/browser/geolocation/empty_wifi_data_provider.h
@@ -0,0 +1,31 @@
+// Copyright 2013 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.
+
+#ifndef CONTENT_BROWSER_GEOLOCATION_EMPTY_WIFI_DATA_PROVIDER_H_
+#define CONTENT_BROWSER_GEOLOCATION_EMPTY_WIFI_DATA_PROVIDER_H_
+
+#include "content/browser/geolocation/wifi_data_provider.h"
+
+namespace content {
+
+// An implementation of WifiDataProviderImplBase that does not provide any
+// data. Used on platforms where a real implementation is not available.
+class EmptyWifiDataProvider : public WifiDataProviderImplBase {
+ public:
+ EmptyWifiDataProvider();
+
+ // WifiDataProviderImplBase implementation
+ virtual void StartDataProvider() OVERRIDE { }
+ virtual void StopDataProvider() OVERRIDE { }
+ virtual bool GetData(WifiData* data) OVERRIDE;
+
+ private:
+ virtual ~EmptyWifiDataProvider();
+
+ DISALLOW_COPY_AND_ASSIGN(EmptyWifiDataProvider);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GEOLOCATION_EMPTY_WIFI_DATA_PROVIDER_H_
diff --git a/content/browser/geolocation/network_location_provider.cc b/content/browser/geolocation/network_location_provider.cc
index 0ea890c..678edb2 100644
--- a/content/browser/geolocation/network_location_provider.cc
+++ b/content/browser/geolocation/network_location_provider.cc
@@ -11,7 +11,7 @@
namespace content {
namespace {
-// The maximum period of time we'll wait for a complete set of device data
+// The maximum period of time we'll wait for a complete set of wifi data
// before sending the request.
const int kDataCompleteWaitSeconds = 2;
} // namespace
@@ -26,7 +26,7 @@ NetworkLocationProvider::PositionCache::~PositionCache() {}
bool NetworkLocationProvider::PositionCache::CachePosition(
const WifiData& wifi_data,
const Geoposition& position) {
- // Check that we can generate a valid key for the device data.
+ // Check that we can generate a valid key for the wifi data.
string16 key;
if (!MakeKey(wifi_data, &key)) {
return false;
@@ -53,8 +53,8 @@ bool NetworkLocationProvider::PositionCache::CachePosition(
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.
+// Searches for a cached position response for the current WiFi data. Returns
+// the cached position if available, NULL otherwise.
const Geoposition* NetworkLocationProvider::PositionCache::FindPosition(
const WifiData& wifi_data) {
string16 key;
@@ -65,15 +65,14 @@ const Geoposition* NetworkLocationProvider::PositionCache::FindPosition(
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.
+// Makes the key for the map of cached positions, using the available data.
+// Returns true if a good key was generated, false otherwise.
//
// static
bool NetworkLocationProvider::PositionCache::MakeKey(
const WifiData& wifi_data,
string16* key) {
- // Currently we use only the WiFi data, and base the key only on
- // the MAC addresses.
+ // Currently we use only WiFi data and base the key only on the MAC addresses.
DCHECK(key);
key->clear();
const size_t kCharsPerMacAddress = 6 * 3 + 1; // e.g. "11:22:33:44:55:66|"
@@ -88,7 +87,7 @@ bool NetworkLocationProvider::PositionCache::MakeKey(
*key += separator;
}
// 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.
+ // position for such data.
return !key->empty();
}
@@ -110,6 +109,9 @@ NetworkLocationProvider::NetworkLocationProvider(
const string16& access_token)
: access_token_store_(access_token_store),
wifi_data_provider_(NULL),
+ wifi_data_update_callback_(
+ base::Bind(&NetworkLocationProvider::WifiDataUpdateAvailable,
+ base::Unretained(this))),
is_wifi_data_complete_(false),
access_token_(access_token),
is_permission_granted_(false),
@@ -129,7 +131,7 @@ NetworkLocationProvider::~NetworkLocationProvider() {
}
// LocationProvider implementation
-void NetworkLocationProvider::GetPosition(Geoposition *position) {
+void NetworkLocationProvider::GetPosition(Geoposition* position) {
DCHECK(position);
*position = position_;
}
@@ -151,12 +153,11 @@ void NetworkLocationProvider::OnPermissionGranted() {
}
}
-// DeviceDataProviderInterface::ListenerInterface implementation.
-void NetworkLocationProvider::DeviceDataUpdateAvailable(
+void NetworkLocationProvider::WifiDataUpdateAvailable(
WifiDataProvider* provider) {
DCHECK(provider == wifi_data_provider_);
is_wifi_data_complete_ = wifi_data_provider_->GetData(&wifi_data_);
- OnDeviceDataUpdated();
+ OnWifiDataUpdated();
}
void NetworkLocationProvider::LocationResponseAvailable(
@@ -192,26 +193,35 @@ bool NetworkLocationProvider::StartProvider(bool high_accuracy) {
return false;
}
- // Get the device data providers. The first call to Register will create the
- // provider and it will be deleted by ref counting.
- wifi_data_provider_ = WifiDataProvider::Register(this);
+ // Registers a callback with the data provider. The first call to Register
+ // will create a singleton data provider and it will be deleted when the last
+ // callback is removed with Unregister.
+ wifi_data_provider_ = WifiDataProvider::Register(&wifi_data_update_callback_);
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&NetworkLocationProvider::RequestPosition,
weak_factory_.GetWeakPtr()),
base::TimeDelta::FromSeconds(kDataCompleteWaitSeconds));
- // Get the device data.
+ // Get the wifi data.
is_wifi_data_complete_ = wifi_data_provider_->GetData(&wifi_data_);
if (is_wifi_data_complete_)
- OnDeviceDataUpdated();
+ OnWifiDataUpdated();
return true;
}
+void NetworkLocationProvider::OnWifiDataUpdated() {
+ DCHECK(CalledOnValidThread());
+ wifi_data_updated_timestamp_ = base::Time::Now();
+
+ is_new_data_available_ = is_wifi_data_complete_;
+ RequestRefresh();
+}
+
void NetworkLocationProvider::StopProvider() {
DCHECK(CalledOnValidThread());
if (IsStarted()) {
- wifi_data_provider_->Unregister(this);
+ wifi_data_provider_->Unregister(&wifi_data_update_callback_);
}
wifi_data_provider_ = NULL;
weak_factory_.InvalidateWeakPtrs();
@@ -225,7 +235,7 @@ void NetworkLocationProvider::RequestPosition() {
const Geoposition* cached_position =
position_cache_->FindPosition(wifi_data_);
- DCHECK(!device_data_updated_timestamp_.is_null()) <<
+ DCHECK(!wifi_data_updated_timestamp_.is_null()) <<
"Timestamp must be set before looking up position";
if (cached_position) {
DCHECK(cached_position->Validate());
@@ -234,7 +244,7 @@ void NetworkLocationProvider::RequestPosition() {
// The timestamp of a position fix is determined by the timestamp
// of the source data update. (The value of position_.timestamp from
// the cache could be from weeks ago!)
- position_.timestamp = device_data_updated_timestamp_;
+ position_.timestamp = wifi_data_updated_timestamp_;
is_new_data_available_ = false;
// Let listeners know that we now have a position available.
NotifyCallback(position_);
@@ -255,15 +265,7 @@ void NetworkLocationProvider::RequestPosition() {
<< wifi_data_.access_point_data.size();
}
request_->MakeRequest(access_token_, wifi_data_,
- device_data_updated_timestamp_);
-}
-
-void NetworkLocationProvider::OnDeviceDataUpdated() {
- DCHECK(CalledOnValidThread());
- device_data_updated_timestamp_ = base::Time::Now();
-
- is_new_data_available_ = is_wifi_data_complete_;
- RequestRefresh();
+ wifi_data_updated_timestamp_);
}
bool NetworkLocationProvider::IsStarted() const {
diff --git a/content/browser/geolocation/network_location_provider.h b/content/browser/geolocation/network_location_provider.h
index 84ecfd94..d5f3e99 100644
--- a/content/browser/geolocation/network_location_provider.h
+++ b/content/browser/geolocation/network_location_provider.h
@@ -15,9 +15,9 @@
#include "base/strings/string16.h"
#include "base/threading/non_thread_safe.h"
#include "base/threading/thread.h"
-#include "content/browser/geolocation/device_data_provider.h"
#include "content/browser/geolocation/location_provider_base.h"
#include "content/browser/geolocation/network_location_request.h"
+#include "content/browser/geolocation/wifi_data_provider.h"
#include "content/common/content_export.h"
#include "content/public/common/geoposition.h"
@@ -27,14 +27,12 @@ class AccessTokenStore;
class NetworkLocationProvider
: public base::NonThreadSafe,
- public LocationProviderBase,
- public WifiDataProvider::ListenerInterface {
+ public LocationProviderBase {
public:
// Cache of recently resolved locations. Public for tests.
class CONTENT_EXPORT PositionCache {
public:
- // The maximum size of the cache of positions for previously requested
- // device data.
+ // The maximum size of the cache of positions.
static const size_t kMaximumSize;
PositionCache();
@@ -47,19 +45,19 @@ class NetworkLocationProvider
bool CachePosition(const WifiData& wifi_data,
const Geoposition& position);
- // Searches for a cached position response for the current set of device
- // data. Returns NULL if the position is not in the cache, or the cached
+ // Searches for a cached position response for the current set of data.
+ // Returns NULL if the position is not in the cache, or the cached
// position if available. Ownership remains with the cache.
const Geoposition* FindPosition(const WifiData& wifi_data);
private:
// 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.
+ // data. Returns true if a good key was generated, false otherwise.
static bool MakeKey(const WifiData& wifi_data,
string16* key);
// The cache of positions. This is stored as a map keyed on a string that
- // represents a set of device data, and a list to provide
+ // represents a set of data, and a list to provide
// least-recently-added eviction.
typedef std::map<string16, Geoposition> CacheMap;
CacheMap cache_;
@@ -84,13 +82,13 @@ class NetworkLocationProvider
// Satisfies a position request from cache or network.
void RequestPosition();
- // Internal helper used by DeviceDataUpdateAvailable
- void OnDeviceDataUpdated();
+ // Called from a callback when new wifi data is available.
+ void WifiDataUpdateAvailable(WifiDataProvider* provider);
- bool IsStarted() const;
+ // Internal helper used by WifiDataUpdateAvailable.
+ void OnWifiDataUpdated();
- // DeviceDataProvider::ListenerInterface implementation.
- virtual void DeviceDataUpdateAvailable(WifiDataProvider* provider) OVERRIDE;
+ bool IsStarted() const;
void LocationResponseAvailable(const Geoposition& position,
bool server_error,
@@ -102,12 +100,14 @@ class NetworkLocationProvider
// The wifi data provider, acquired via global factories.
WifiDataProvider* wifi_data_provider_;
- // The wifi data, flags to indicate if the data set is complete.
+ WifiDataProvider::WifiDataUpdateCallback wifi_data_update_callback_;
+
+ // The wifi data and a flag to indicate if the data set is complete.
WifiData wifi_data_;
bool is_wifi_data_complete_;
- // The timestamp for the latest device data update.
- base::Time device_data_updated_timestamp_;
+ // The timestamp for the latest wifi data update.
+ base::Time wifi_data_updated_timestamp_;
// Cached value loaded from the token store or set by a previous server
// response, and sent in each subsequent network request.
@@ -124,10 +124,11 @@ class NetworkLocationProvider
// The network location request object, and the url it uses.
scoped_ptr<NetworkLocationRequest> request_;
- base::WeakPtrFactory<NetworkLocationProvider> weak_factory_;
// The cache of positions.
scoped_ptr<PositionCache> position_cache_;
+ base::WeakPtrFactory<NetworkLocationProvider> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(NetworkLocationProvider);
};
diff --git a/content/browser/geolocation/network_location_provider_unittest.cc b/content/browser/geolocation/network_location_provider_unittest.cc
index b0d9c25..86ebad0 100644
--- a/content/browser/geolocation/network_location_provider_unittest.cc
+++ b/content/browser/geolocation/network_location_provider_unittest.cc
@@ -46,54 +46,49 @@ class MessageLoopQuitListener {
const LocationProvider* updated_provider_;
};
-// A mock implementation of DeviceDataProviderImplBase for testing. Adapted from
+// A mock implementation of WifiDataProviderImplBase for testing. Adapted from
// http://gears.googlecode.com/svn/trunk/gears/geolocation/geolocation_test.cc
-template<typename DataType>
-class MockDeviceDataProviderImpl
- : public DeviceDataProviderImplBase<DataType> {
+class MockWifiDataProviderImpl : public WifiDataProviderImplBase {
public:
- // Factory method for use with DeviceDataProvider::SetFactory.
- static DeviceDataProviderImplBase<DataType>* GetInstance() {
+ // Factory method for use with WifiDataProvider::SetFactory.
+ static WifiDataProviderImplBase* GetInstance() {
CHECK(instance_);
return instance_;
}
- static MockDeviceDataProviderImpl<DataType>* CreateInstance() {
+ static MockWifiDataProviderImpl* CreateInstance() {
CHECK(!instance_);
- instance_ = new MockDeviceDataProviderImpl<DataType>;
+ instance_ = new MockWifiDataProviderImpl;
return instance_;
}
- MockDeviceDataProviderImpl()
+ MockWifiDataProviderImpl()
: start_calls_(0),
stop_calls_(0),
got_data_(true) {
}
- virtual ~MockDeviceDataProviderImpl() {
- CHECK(this == instance_);
- instance_ = NULL;
- }
-
- // DeviceDataProviderImplBase implementation.
- virtual void StartDataProvider() {
+ // WifiDataProviderImplBase implementation.
+ virtual void StartDataProvider() OVERRIDE {
++start_calls_;
}
- virtual void StopDataProvider() {
+
+ virtual void StopDataProvider() OVERRIDE {
++stop_calls_;
}
- virtual bool GetData(DataType* data_out) {
+
+ virtual bool GetData(WifiData* data_out) OVERRIDE {
CHECK(data_out);
*data_out = data_;
return got_data_;
}
- void SetData(const DataType& new_data) {
+ void SetData(const WifiData& new_data) {
got_data_ = true;
const bool differs = data_.DiffersSignificantly(new_data);
data_ = new_data;
if (differs)
- this->NotifyListeners();
+ this->RunCallbacks();
}
void set_got_data(bool got_data) { got_data_ = got_data; }
@@ -101,17 +96,20 @@ class MockDeviceDataProviderImpl
int stop_calls_;
private:
- static MockDeviceDataProviderImpl<DataType>* instance_;
+ virtual ~MockWifiDataProviderImpl() {
+ CHECK(this == instance_);
+ instance_ = NULL;
+ }
+
+ static MockWifiDataProviderImpl* instance_;
- DataType data_;
+ WifiData data_;
bool got_data_;
- DISALLOW_COPY_AND_ASSIGN(MockDeviceDataProviderImpl);
+ DISALLOW_COPY_AND_ASSIGN(MockWifiDataProviderImpl);
};
-template<typename DataType>
-MockDeviceDataProviderImpl<DataType>*
-MockDeviceDataProviderImpl<DataType>::instance_ = NULL;
+MockWifiDataProviderImpl* MockWifiDataProviderImpl::instance_ = NULL;
// Main test fixture
class GeolocationNetworkProviderTest : public testing::Test {
@@ -120,7 +118,7 @@ class GeolocationNetworkProviderTest : public testing::Test {
test_server_url_ = GURL(kTestServerUrl);
access_token_store_ = new FakeAccessTokenStore;
wifi_data_provider_ =
- MockDeviceDataProviderImpl<WifiData>::CreateInstance();
+ MockWifiDataProviderImpl::CreateInstance();
}
virtual void TearDown() {
@@ -142,8 +140,7 @@ class GeolocationNetworkProviderTest : public testing::Test {
GeolocationNetworkProviderTest() {
// TODO(joth): Really these should be in SetUp, not here, but they take no
// effect on Mac OS Release builds if done there. I kid not. Figure out why.
- WifiDataProvider::SetFactory(
- MockDeviceDataProviderImpl<WifiData>::GetInstance);
+ WifiDataProvider::SetFactory(MockWifiDataProviderImpl::GetInstance);
}
// Returns the current url fetcher (if any) and advances the id ready for the
@@ -324,7 +321,7 @@ class GeolocationNetworkProviderTest : public testing::Test {
base::MessageLoop main_message_loop_;
scoped_refptr<FakeAccessTokenStore> access_token_store_;
net::TestURLFetcherFactory url_fetcher_factory_;
- scoped_refptr<MockDeviceDataProviderImpl<WifiData> > wifi_data_provider_;
+ scoped_refptr<MockWifiDataProviderImpl> wifi_data_provider_;
};
TEST_F(GeolocationNetworkProviderTest, CreateDestroy) {
@@ -491,7 +488,7 @@ TEST_F(GeolocationNetworkProviderTest, NoRequestOnStartupUntilWifiData) {
}
TEST_F(GeolocationNetworkProviderTest, NewDataReplacesExistingNetworkRequest) {
- // Send initial request with empty device data
+ // Send initial request with empty data
scoped_ptr<LocationProvider> provider(CreateProvider(true));
EXPECT_TRUE(provider->StartProvider(false));
net::TestURLFetcher* fetcher = get_url_fetcher_and_advance_id();
diff --git a/content/browser/geolocation/network_location_request.cc b/content/browser/geolocation/network_location_request.cc
index d11a474..ccc7526 100644
--- a/content/browser/geolocation/network_location_request.cc
+++ b/content/browser/geolocation/network_location_request.cc
@@ -271,7 +271,7 @@ void GetLocationFromResponse(bool http_post_result,
FormatPositionError(server_url, message, position);
return;
}
- // We use the timestamp from the device data that was used to generate
+ // We use the timestamp from the wifi data that was used to generate
// this position fix.
if (!ParseServerResponse(response_body, timestamp, position, access_token)) {
// We failed to parse the repsonse.
diff --git a/content/browser/geolocation/network_location_request.h b/content/browser/geolocation/network_location_request.h
index 56a6004..38aaf3e 100644
--- a/content/browser/geolocation/network_location_request.h
+++ b/content/browser/geolocation/network_location_request.h
@@ -8,7 +8,7 @@
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
-#include "content/browser/geolocation/device_data_provider.h"
+#include "content/browser/geolocation/wifi_data_provider.h"
#include "content/common/content_export.h"
#include "net/url_request/url_fetcher_delegate.h"
#include "url/gurl.h"
@@ -21,7 +21,7 @@ class URLRequestContextGetter;
namespace content {
struct Geoposition;
-// Takes a set of device data and sends it to a server to get a position fix.
+// Takes wifi 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 : private net::URLFetcherDelegate {
public:
diff --git a/content/browser/geolocation/device_data_provider.cc b/content/browser/geolocation/wifi_data.cc
index 00c585b..f4ea267b 100644
--- a/content/browser/geolocation/device_data_provider.cc
+++ b/content/browser/geolocation/wifi_data.cc
@@ -1,16 +1,12 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 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 "content/browser/geolocation/device_data_provider.h"
+#include "content/browser/geolocation/wifi_data.h"
-namespace content {
+#include "base/logging.h"
-// statics
-template<> DeviceDataProvider<WifiData>*
- DeviceDataProvider<WifiData>::instance_ = NULL;
-template<> DeviceDataProvider<WifiData>::ImplFactoryFunction
- DeviceDataProvider<WifiData>::factory_function_ = DefaultFactoryFunction;
+namespace content {
AccessPointData::AccessPointData()
: radio_signal_strength(kint32min),
@@ -35,7 +31,7 @@ bool WifiData::DiffersSignificantly(const WifiData& other) const {
min_ap_count / 2);
if (max_ap_count > min_ap_count + difference_threadhold)
return true;
- // Compute size of interesction of old and new sets.
+ // Compute size of intersection of old and new sets.
size_t num_common = 0;
for (AccessPointDataSet::const_iterator iter = access_point_data.begin();
iter != access_point_data.end();
diff --git a/content/browser/geolocation/wifi_data.h b/content/browser/geolocation/wifi_data.h
new file mode 100644
index 0000000..a24e42e
--- /dev/null
+++ b/content/browser/geolocation/wifi_data.h
@@ -0,0 +1,54 @@
+// Copyright 2013 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.
+
+#ifndef CONTENT_BROWSER_GEOLOCATION_WIFI_DATA_H_
+#define CONTENT_BROWSER_GEOLOCATION_WIFI_DATA_H_
+
+#include <set>
+
+#include "base/basictypes.h"
+#include "base/strings/string16.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+// Wifi data relating to a single access point.
+struct CONTENT_EXPORT AccessPointData {
+ AccessPointData();
+ ~AccessPointData();
+
+ // MAC address, formatted as per MacAddressAsString16.
+ string16 mac_address;
+ int radio_signal_strength; // Measured in dBm
+ int channel;
+ int signal_to_noise; // Ratio in dB
+ string16 ssid; // Network identifier
+};
+
+// This is to allow AccessPointData to be used in std::set. We order
+// lexicographically by MAC address.
+struct AccessPointDataLess {
+ bool operator()(const AccessPointData& data1,
+ const AccessPointData& data2) const {
+ return data1.mac_address < data2.mac_address;
+ }
+};
+
+// All data for wifi.
+struct CONTENT_EXPORT WifiData {
+ WifiData();
+ ~WifiData();
+
+ // Determines whether a new set of WiFi data differs significantly from this.
+ bool DiffersSignificantly(const WifiData& other) const;
+
+ // Store access points as a set, sorted by MAC address. This allows quick
+ // comparison of sets for detecting changes and for caching.
+ typedef std::set<AccessPointData, AccessPointDataLess> AccessPointDataSet;
+ AccessPointDataSet access_point_data;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GEOLOCATION_WIFI_DATA_H_
diff --git a/content/browser/geolocation/wifi_data_provider.cc b/content/browser/geolocation/wifi_data_provider.cc
new file mode 100644
index 0000000..416ecb8
--- /dev/null
+++ b/content/browser/geolocation/wifi_data_provider.cc
@@ -0,0 +1,95 @@
+// Copyright 2013 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 "content/browser/geolocation/wifi_data_provider.h"
+
+namespace content {
+
+// static
+WifiDataProvider* WifiDataProvider::instance_ = NULL;
+
+// static
+WifiDataProvider::ImplFactoryFunction WifiDataProvider::factory_function_ =
+ DefaultFactoryFunction;
+
+// static
+WifiDataProvider* WifiDataProvider::Register(WifiDataUpdateCallback* callback) {
+ bool need_to_start_data_provider = false;
+ if (!instance_) {
+ instance_ = new WifiDataProvider();
+ need_to_start_data_provider = true;
+ }
+ DCHECK(instance_);
+ instance_->AddCallback(callback);
+ // Start the provider after adding the callback, to avoid any race in
+ // it running early.
+ if (need_to_start_data_provider)
+ instance_->StartDataProvider();
+ return instance_;
+}
+
+WifiDataProviderImplBase::WifiDataProviderImplBase()
+ : container_(NULL),
+ client_loop_(base::MessageLoop::current()) {
+ DCHECK(client_loop_);
+}
+
+WifiDataProviderImplBase::~WifiDataProviderImplBase() {
+}
+
+void WifiDataProviderImplBase::SetContainer(WifiDataProvider* container) {
+ container_ = container;
+}
+
+void WifiDataProviderImplBase::AddCallback(WifiDataUpdateCallback* callback) {
+ callbacks_.insert(callback);
+}
+
+bool WifiDataProviderImplBase::RemoveCallback(
+ WifiDataUpdateCallback* callback) {
+ return callbacks_.erase(callback) == 1;
+}
+
+bool WifiDataProviderImplBase::has_callbacks() const {
+ return !callbacks_.empty();
+}
+
+void WifiDataProviderImplBase::RunCallbacks() {
+ client_loop_->PostTask(FROM_HERE, base::Bind(
+ &WifiDataProviderImplBase::DoRunCallbacks,
+ this));
+}
+
+bool WifiDataProviderImplBase::CalledOnClientThread() const {
+ return base::MessageLoop::current() == this->client_loop_;
+}
+
+base::MessageLoop* WifiDataProviderImplBase::client_loop() const {
+ return client_loop_;
+}
+
+void WifiDataProviderImplBase::DoRunCallbacks() {
+ // It's possible that all the callbacks (and the container) went away
+ // whilst this task was pending. This is fine; the loop will be a no-op.
+ CallbackSet::const_iterator iter = callbacks_.begin();
+ while (iter != callbacks_.end()) {
+ WifiDataUpdateCallback* callback = *iter;
+ ++iter; // Advance iter before running, in case callback unregisters.
+ callback->Run(container_);
+ }
+}
+
+WifiDataProvider::WifiDataProvider() {
+ DCHECK(factory_function_);
+ impl_ = (*factory_function_)();
+ DCHECK(impl_.get());
+ impl_->SetContainer(this);
+}
+
+WifiDataProvider::~WifiDataProvider() {
+ DCHECK(impl_.get());
+ impl_->SetContainer(NULL);
+}
+
+} // namespace content
diff --git a/content/browser/geolocation/wifi_data_provider.h b/content/browser/geolocation/wifi_data_provider.h
new file mode 100644
index 0000000..7937f28
--- /dev/null
+++ b/content/browser/geolocation/wifi_data_provider.h
@@ -0,0 +1,195 @@
+// Copyright 2013 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.
+
+// A wifi data provider provides wifi data from the device that is used by a
+// NetworkLocationProvider to obtain a position fix. We use a singleton
+// instance of the wifi data provider, which is used by multiple
+// NetworkLocationProvider objects.
+//
+// This file provides WifiDataProvider, which provides static methods to
+// access the singleton instance. The singleton instance uses a private
+// implementation to abstract across platforms and also to allow mock providers
+// to be used for testing.
+//
+// This file also provides WifiDataProviderImplBase, a base class which
+// provides common functionality for the private implementations.
+
+#ifndef CONTENT_BROWSER_GEOLOCATION_WIFI_DATA_PROVIDER_H_
+#define CONTENT_BROWSER_GEOLOCATION_WIFI_DATA_PROVIDER_H_
+
+#include <set>
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_util.h"
+#include "content/browser/geolocation/wifi_data.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class WifiDataProvider;
+
+// See class WifiDataProvider for the public client API.
+// WifiDataProvider uses containment to hide platform-specific implementation
+// details from common code. This class provides common functionality for these
+// contained implementation classes. This is a modified pimpl pattern.
+class CONTENT_EXPORT WifiDataProviderImplBase
+ : public base::RefCountedThreadSafe<WifiDataProviderImplBase> {
+ public:
+ WifiDataProviderImplBase();
+
+ // Tells the provider to start looking for data. Callbacks will start
+ // receiving notifications after this call.
+ virtual void StartDataProvider() = 0;
+
+ // Tells the provider to stop looking for data. Callbacks will stop
+ // receiving notifications after this call.
+ virtual void StopDataProvider() = 0;
+
+ // Provides whatever data the provider has, which may be nothing. Return
+ // value indicates whether this is all the data the provider could ever
+ // obtain.
+ virtual bool GetData(WifiData* data) = 0;
+
+ // Sets the container of this class, which is of type WifiDataProvider.
+ // This is required to pass as a parameter when calling a callback.
+ void SetContainer(WifiDataProvider* container);
+
+ typedef base::Callback<void(WifiDataProvider*)> WifiDataUpdateCallback;
+
+ void AddCallback(WifiDataUpdateCallback* callback);
+
+ bool RemoveCallback(WifiDataUpdateCallback* callback);
+
+ bool has_callbacks() const;
+
+ protected:
+ friend class base::RefCountedThreadSafe<WifiDataProviderImplBase>;
+ virtual ~WifiDataProviderImplBase();
+
+ typedef std::set<WifiDataUpdateCallback*> CallbackSet;
+
+ // Runs all callbacks via a posted task, so we can unwind callstack here and
+ // avoid client reentrancy.
+ void RunCallbacks();
+
+ bool CalledOnClientThread() const;
+
+ base::MessageLoop* client_loop() const;
+
+ private:
+ void DoRunCallbacks();
+
+ WifiDataProvider* container_;
+
+ // Reference to the client's message loop. All callbacks should happen in this
+ // context.
+ base::MessageLoop* client_loop_;
+
+ CallbackSet callbacks_;
+
+ DISALLOW_COPY_AND_ASSIGN(WifiDataProviderImplBase);
+};
+
+// A wifi data provider
+//
+// We use a singleton instance of this class which is shared by multiple network
+// location providers. These location providers access the instance through the
+// Register and Unregister methods.
+class CONTENT_EXPORT WifiDataProvider {
+ public:
+ // Sets the factory function which will be used by Register to create the
+ // implementation used by the singleton instance. This factory approach is
+ // used both to abstract accross platform-specific implementations and to
+ // inject mock implementations for testing.
+ typedef WifiDataProviderImplBase* (*ImplFactoryFunction)(void);
+ static void SetFactory(ImplFactoryFunction factory_function_in) {
+ factory_function_ = factory_function_in;
+ }
+
+ static void ResetFactory() {
+ factory_function_ = DefaultFactoryFunction;
+ }
+
+ typedef base::Callback<void(WifiDataProvider*)> WifiDataUpdateCallback;
+
+ // Registers a callback, which will be run whenever new data is available.
+ // Instantiates the singleton if necessary, and always returns it.
+ static WifiDataProvider* Register(WifiDataUpdateCallback* callback);
+
+ // Removes a callback. If this is the last callback, deletes the singleton
+ // instance. Return value indicates success.
+ static bool Unregister(WifiDataUpdateCallback* callback) {
+ DCHECK(instance_);
+ DCHECK(instance_->has_callbacks());
+ if (!instance_->RemoveCallback(callback)) {
+ return false;
+ }
+ if (!instance_->has_callbacks()) {
+ // Must stop the data provider (and any implementation threads) before
+ // destroying to avoid any race conditions in access to the provider in
+ // the destructor chain.
+ instance_->StopDataProvider();
+ delete instance_;
+ instance_ = NULL;
+ }
+ return true;
+ }
+
+ // Provides whatever data the provider has, which may be nothing. Return
+ // value indicates whether this is all the data the provider could ever
+ // obtain.
+ bool GetData(WifiData* data) {
+ return impl_->GetData(data);
+ }
+
+ private:
+ // Private constructor and destructor, callers access singleton through
+ // Register and Unregister.
+ WifiDataProvider();
+ virtual ~WifiDataProvider();
+
+ void AddCallback(WifiDataUpdateCallback* callback) {
+ impl_->AddCallback(callback);
+ }
+
+ bool RemoveCallback(WifiDataUpdateCallback* callback) {
+ return impl_->RemoveCallback(callback);
+ }
+
+ bool has_callbacks() const {
+ return impl_->has_callbacks();
+ }
+
+ void StartDataProvider() {
+ impl_->StartDataProvider();
+ }
+
+ void StopDataProvider() {
+ impl_->StopDataProvider();
+ }
+
+ static WifiDataProviderImplBase* DefaultFactoryFunction();
+
+ // The singleton-like instance of this class. (Not 'true' singleton, as it
+ // may go through multiple create/destroy/create cycles per process instance,
+ // e.g. when under test).
+ static WifiDataProvider* instance_;
+
+ // The factory function used to create the singleton instance.
+ static ImplFactoryFunction factory_function_;
+
+ // The internal implementation.
+ scoped_refptr<WifiDataProviderImplBase> impl_;
+
+ DISALLOW_COPY_AND_ASSIGN(WifiDataProvider);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GEOLOCATION_WIFI_DATA_PROVIDER_H_
diff --git a/content/browser/geolocation/wifi_data_provider_chromeos.cc b/content/browser/geolocation/wifi_data_provider_chromeos.cc
index 951d2d3..7f29276 100644
--- a/content/browser/geolocation/wifi_data_provider_chromeos.cc
+++ b/content/browser/geolocation/wifi_data_provider_chromeos.cc
@@ -87,7 +87,7 @@ void WifiDataProviderChromeOs::DidWifiScanTaskNoResults() {
// in between DoWifiScanTaskOnUIThread and this method).
if (started_)
ScheduleNextScan(polling_policy_->NoWifiInterval());
- MaybeNotifyListeners(false);
+ MaybeRunCallbacks(false);
}
void WifiDataProviderChromeOs::DidWifiScanTask(const WifiData& new_data) {
@@ -100,13 +100,13 @@ void WifiDataProviderChromeOs::DidWifiScanTask(const WifiData& new_data) {
polling_policy_->UpdatePollingInterval(update_available);
ScheduleNextScan(polling_policy_->PollingInterval());
}
- MaybeNotifyListeners(update_available);
+ MaybeRunCallbacks(update_available);
}
-void WifiDataProviderChromeOs::MaybeNotifyListeners(bool update_available) {
+void WifiDataProviderChromeOs::MaybeRunCallbacks(bool update_available) {
if (update_available || !is_first_scan_complete_) {
is_first_scan_complete_ = true;
- NotifyListeners();
+ RunCallbacks();
}
}
@@ -167,7 +167,6 @@ bool WifiDataProviderChromeOs::GetAccessPointData(
}
// static
-template<>
WifiDataProviderImplBase* WifiDataProvider::DefaultFactoryFunction() {
return new WifiDataProviderChromeOs();
}
diff --git a/content/browser/geolocation/wifi_data_provider_chromeos.h b/content/browser/geolocation/wifi_data_provider_chromeos.h
index 4c8a80c..0118298 100644
--- a/content/browser/geolocation/wifi_data_provider_chromeos.h
+++ b/content/browser/geolocation/wifi_data_provider_chromeos.h
@@ -31,7 +31,7 @@ class CONTENT_EXPORT WifiDataProviderChromeOs
// Client thread
void DidWifiScanTaskNoResults();
void DidWifiScanTask(const WifiData& new_data);
- void MaybeNotifyListeners(bool update_available);
+ void MaybeRunCallbacks(bool update_available);
// Will schedule a scan; i.e. enqueue DoWifiScanTask deferred task.
void ScheduleNextScan(int interval);
diff --git a/content/browser/geolocation/wifi_data_provider_common.cc b/content/browser/geolocation/wifi_data_provider_common.cc
index 9132752..31f969c 100644
--- a/content/browser/geolocation/wifi_data_provider_common.cc
+++ b/content/browser/geolocation/wifi_data_provider_common.cc
@@ -75,7 +75,7 @@ void WifiDataProviderCommon::DoWifiScanTask() {
}
if (update_available || !is_first_scan_complete_) {
is_first_scan_complete_ = true;
- NotifyListeners();
+ RunCallbacks();
}
}
diff --git a/content/browser/geolocation/wifi_data_provider_common.h b/content/browser/geolocation/wifi_data_provider_common.h
index 205eae3..5f15e09 100644
--- a/content/browser/geolocation/wifi_data_provider_common.h
+++ b/content/browser/geolocation/wifi_data_provider_common.h
@@ -11,7 +11,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
-#include "content/browser/geolocation/device_data_provider.h"
+#include "content/browser/geolocation/wifi_data_provider.h"
#include "content/common/content_export.h"
namespace content {
@@ -62,7 +62,7 @@ class GenericPollingPolicy : public PollingPolicyInterface {
// providers. It's optional for specific platforms to derive this, but if they
// do polling behavior is taken care of by this base class, and all the platform
// need do is provide the underlying WLAN access API and polling policy.
-// Also designed this way to for ease of testing the cross-platform behavior.
+// Also designed this way for ease of testing the cross-platform behavior.
class CONTENT_EXPORT WifiDataProviderCommon : public WifiDataProviderImplBase {
public:
// Interface to abstract the low level data OS library call, and to allow
@@ -84,14 +84,14 @@ class CONTENT_EXPORT WifiDataProviderCommon : public WifiDataProviderImplBase {
protected:
virtual ~WifiDataProviderCommon();
- // Returns ownership. Will be called from the worker thread.
+ // Returns ownership.
virtual WlanApiInterface* NewWlanApi() = 0;
- // Returns ownership. Will be called from the worker thread.
+ // Returns ownership.
virtual PollingPolicyInterface* NewPollingPolicy() = 0;
private:
- // Runs a scan. Notifies the listeners if new data is found.
+ // Runs a scan. Calls the callbacks if new data is found.
void DoWifiScanTask();
// Will schedule a scan; i.e. enqueue DoWifiScanTask deferred task.
diff --git a/content/browser/geolocation/wifi_data_provider_common_unittest.cc b/content/browser/geolocation/wifi_data_provider_common_unittest.cc
index 2873720..c37200f 100644
--- a/content/browser/geolocation/wifi_data_provider_common_unittest.cc
+++ b/content/browser/geolocation/wifi_data_provider_common_unittest.cc
@@ -42,7 +42,7 @@ class MockWlanApi : public WifiDataProviderCommon::WlanApiInterface {
}
};
-class MockPollingPolicy :public PollingPolicyInterface {
+class MockPollingPolicy : public PollingPolicyInterface {
public:
MockPollingPolicy() {
ON_CALL(*this,PollingInterval())
@@ -57,27 +57,25 @@ class MockPollingPolicy :public PollingPolicyInterface {
virtual void UpdatePollingInterval(bool) {}
};
-// Stops the specified (nested) message loop when the listener is called back.
-class MessageLoopQuitListener
- : public WifiDataProviderCommon::ListenerInterface {
+// Stops the specified (nested) message loop when the callback is called.
+class MessageLoopQuitter {
public:
- explicit MessageLoopQuitListener(base::MessageLoop* message_loop)
- : message_loop_to_quit_(message_loop) {
+ explicit MessageLoopQuitter(base::MessageLoop* message_loop)
+ : message_loop_to_quit_(message_loop),
+ callback_(base::Bind(&MessageLoopQuitter::WifiDataUpdateAvailable,
+ base::Unretained(this))) {
CHECK(message_loop_to_quit_ != NULL);
}
- // ListenerInterface
- virtual void DeviceDataUpdateAvailable(
- DeviceDataProvider<WifiData>* provider) OVERRIDE {
+
+ void WifiDataUpdateAvailable(WifiDataProvider* provider) {
// Provider should call back on client's thread.
EXPECT_EQ(base::MessageLoop::current(), message_loop_to_quit_);
- provider_ = provider;
message_loop_to_quit_->QuitNow();
}
base::MessageLoop* message_loop_to_quit_;
- DeviceDataProvider<WifiData>* provider_;
+ WifiDataProvider::WifiDataUpdateCallback callback_;
};
-
class WifiDataProviderCommonWithMock : public WifiDataProviderCommon {
public:
WifiDataProviderCommonWithMock()
@@ -111,24 +109,24 @@ WifiDataProviderImplBase* CreateWifiDataProviderCommonWithMock() {
class GeolocationWifiDataProviderCommonTest : public testing::Test {
public:
GeolocationWifiDataProviderCommonTest()
- : quit_listener_(&main_message_loop_) {
+ : loop_quitter_(&main_message_loop_) {
}
virtual void SetUp() {
provider_ = new WifiDataProviderCommonWithMock;
wlan_api_ = provider_->new_wlan_api_.get();
polling_policy_ = provider_->new_polling_policy_.get();
- provider_->AddListener(&quit_listener_);
+ provider_->AddCallback(&loop_quitter_.callback_);
}
virtual void TearDown() {
- provider_->RemoveListener(&quit_listener_);
+ provider_->RemoveCallback(&loop_quitter_.callback_);
provider_->StopDataProvider();
provider_ = NULL;
}
protected:
base::MessageLoop main_message_loop_;
- MessageLoopQuitListener quit_listener_;
+ MessageLoopQuitter loop_quitter_;
scoped_refptr<WifiDataProviderCommonWithMock> provider_;
MockWlanApi* wlan_api_;
MockPollingPolicy* polling_policy_;
@@ -141,7 +139,7 @@ TEST_F(GeolocationWifiDataProviderCommonTest, CreateDestroy) {
EXPECT_TRUE(NULL != wlan_api_);
}
-TEST_F(GeolocationWifiDataProviderCommonTest, StartThread) {
+TEST_F(GeolocationWifiDataProviderCommonTest, RunNormal) {
EXPECT_CALL(*wlan_api_, GetAccessPointData(_))
.Times(AtLeast(1));
EXPECT_CALL(*polling_policy_, PollingInterval())
@@ -190,9 +188,7 @@ TEST_F(GeolocationWifiDataProviderCommonTest, DoAnEmptyScan) {
.Times(AtLeast(1));
provider_->StartDataProvider();
main_message_loop_.Run();
- // Check we had at least one call. The worker thread may have raced ahead
- // and made multiple calls.
- EXPECT_GT(wlan_api_->calls_, 0);
+ EXPECT_EQ(wlan_api_->calls_, 1);
WifiData data;
EXPECT_TRUE(provider_->GetData(&data));
EXPECT_EQ(0, static_cast<int>(data.access_point_data.size()));
@@ -213,21 +209,20 @@ TEST_F(GeolocationWifiDataProviderCommonTest, DoScanWithResults) {
provider_->StartDataProvider();
main_message_loop_.Run();
- EXPECT_GT(wlan_api_->calls_, 0);
+ EXPECT_EQ(wlan_api_->calls_, 1);
WifiData data;
EXPECT_TRUE(provider_->GetData(&data));
EXPECT_EQ(1, static_cast<int>(data.access_point_data.size()));
EXPECT_EQ(single_access_point.ssid, data.access_point_data.begin()->ssid);
}
-TEST_F(GeolocationWifiDataProviderCommonTest,
- StartThreadViaDeviceDataProvider) {
- MessageLoopQuitListener quit_listener(&main_message_loop_);
+TEST_F(GeolocationWifiDataProviderCommonTest, RegisterUnregister) {
+ MessageLoopQuitter loop_quitter(&main_message_loop_);
WifiDataProvider::SetFactory(CreateWifiDataProviderCommonWithMock);
- DeviceDataProvider<WifiData>::Register(&quit_listener);
+ WifiDataProvider::Register(&loop_quitter.callback_);
main_message_loop_.Run();
- DeviceDataProvider<WifiData>::Unregister(&quit_listener);
- DeviceDataProvider<WifiData>::ResetFactory();
+ WifiDataProvider::Unregister(&loop_quitter.callback_);
+ WifiDataProvider::ResetFactory();
}
} // namespace content
diff --git a/content/browser/geolocation/wifi_data_provider_common_win.cc b/content/browser/geolocation/wifi_data_provider_common_win.cc
index 9ac7848..a0d334f 100644
--- a/content/browser/geolocation/wifi_data_provider_common_win.cc
+++ b/content/browser/geolocation/wifi_data_provider_common_win.cc
@@ -7,7 +7,6 @@
#include <assert.h>
#include "base/strings/utf_string_conversions.h"
-#include "content/browser/geolocation/device_data_provider.h"
#include "content/browser/geolocation/wifi_data_provider_common.h"
namespace content {
diff --git a/content/browser/geolocation/wifi_data_provider_common_win.h b/content/browser/geolocation/wifi_data_provider_common_win.h
index f58e0c6..24973a5 100644
--- a/content/browser/geolocation/wifi_data_provider_common_win.h
+++ b/content/browser/geolocation/wifi_data_provider_common_win.h
@@ -8,7 +8,7 @@
#include <windows.h>
#include <ntddndis.h>
-#include "content/browser/geolocation/device_data_provider.h"
+#include "content/browser/geolocation/wifi_data_provider.h"
namespace content {
diff --git a/content/browser/geolocation/wifi_data_provider_linux.cc b/content/browser/geolocation/wifi_data_provider_linux.cc
index edece1d..34bc440 100644
--- a/content/browser/geolocation/wifi_data_provider_linux.cc
+++ b/content/browser/geolocation/wifi_data_provider_linux.cc
@@ -344,7 +344,6 @@ scoped_ptr<dbus::Response> NetworkManagerWlanApi::GetAccessPointProperty(
} // namespace
// static
-template<>
WifiDataProviderImplBase* WifiDataProvider::DefaultFactoryFunction() {
return new WifiDataProviderLinux();
}
diff --git a/content/browser/geolocation/wifi_data_provider_mac.cc b/content/browser/geolocation/wifi_data_provider_mac.cc
index 8f81305..f1f3755 100644
--- a/content/browser/geolocation/wifi_data_provider_mac.cc
+++ b/content/browser/geolocation/wifi_data_provider_mac.cc
@@ -158,7 +158,6 @@ bool Apple80211Api::GetAccessPointData(WifiData::AccessPointDataSet* data) {
} // namespace
// static
-template<>
WifiDataProviderImplBase* WifiDataProvider::DefaultFactoryFunction() {
return new MacWifiDataProvider();
}
diff --git a/content/browser/geolocation/wifi_data_provider_win.cc b/content/browser/geolocation/wifi_data_provider_win.cc
index a35e6e9..2cb15dc 100644
--- a/content/browser/geolocation/wifi_data_provider_win.cc
+++ b/content/browser/geolocation/wifi_data_provider_win.cc
@@ -158,7 +158,6 @@ bool ResizeBuffer(int requested_size, scoped_ptr_malloc<BYTE>* buffer);
bool GetSystemDirectory(string16* path);
} // namespace
-template<>
WifiDataProviderImplBase* WifiDataProvider::DefaultFactoryFunction() {
return new Win32WifiDataProvider();
}
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index 49e7987..82deda7 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -530,10 +530,8 @@
'browser/gamepad/gamepad_standard_mappings_win.cc',
'browser/gamepad/xbox_data_fetcher_mac.cc',
'browser/gamepad/xbox_data_fetcher_mac.h',
- 'browser/geolocation/device_data_provider.cc',
- 'browser/geolocation/device_data_provider.h',
- 'browser/geolocation/empty_device_data_provider.cc',
- 'browser/geolocation/empty_device_data_provider.h',
+ 'browser/geolocation/empty_wifi_data_provider.cc',
+ 'browser/geolocation/empty_wifi_data_provider.h',
'browser/geolocation/geolocation_dispatcher_host.cc',
'browser/geolocation/geolocation_dispatcher_host.h',
'browser/geolocation/geolocation_provider_impl.cc',
@@ -554,6 +552,10 @@
'browser/geolocation/network_location_request.cc',
'browser/geolocation/network_location_request.h',
'browser/geolocation/osx_wifi.h',
+ 'browser/geolocation/wifi_data.cc',
+ 'browser/geolocation/wifi_data.h',
+ 'browser/geolocation/wifi_data_provider.cc',
+ 'browser/geolocation/wifi_data_provider.h',
'browser/geolocation/wifi_data_provider_chromeos.cc',
'browser/geolocation/wifi_data_provider_chromeos.h',
'browser/geolocation/wifi_data_provider_common.cc',
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index 783106d..e5ecf10 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -302,7 +302,6 @@
'browser/gamepad/gamepad_provider_unittest.cc',
'browser/gamepad/gamepad_test_helpers.cc',
'browser/gamepad/gamepad_test_helpers.h',
- 'browser/geolocation/device_data_provider_unittest.cc',
'browser/geolocation/geolocation_provider_unittest.cc',
'browser/geolocation/gps_location_provider_unittest_linux.cc',
'browser/geolocation/location_arbitrator_impl_unittest.cc',
@@ -338,7 +337,7 @@
'browser/power_monitor_message_broadcaster_unittest.cc',
'browser/renderer_host/compositing_iosurface_transformer_mac_unittest.cc',
'browser/renderer_host/gtk_key_bindings_handler_unittest.cc',
- 'browser/renderer_host/input/immediate_input_router_unittest.cc',
+ 'browser/renderer_host/input/immediate_input_router_unittest.cc',
'browser/renderer_host/media/audio_input_device_manager_unittest.cc',
'browser/renderer_host/media/audio_mirroring_manager_unittest.cc',
'browser/renderer_host/media/audio_renderer_host_unittest.cc',
@@ -709,7 +708,6 @@
'../ui/ui.gyp:shell_dialogs',
],
'sources!': [
- 'browser/geolocation/device_data_provider_unittest.cc',
'browser/geolocation/gps_location_provider_unittest_linux.cc',
'browser/geolocation/network_location_provider_unittest.cc',
'browser/geolocation/wifi_data_provider_chromeos_unittest.cc',