diff options
author | mvanouwerkerk@chromium.org <mvanouwerkerk@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-23 15:01:17 +0000 |
---|---|---|
committer | mvanouwerkerk@chromium.org <mvanouwerkerk@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-23 15:01:17 +0000 |
commit | 296a9999fb46f314cfcc5492265273d99e6ced5c (patch) | |
tree | fd6b1d2e11937ef1b0988ee23f994c54b48cbd4e /content | |
parent | dda540b9975640716d72b9b954750541a826f2c2 (diff) | |
download | chromium_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')
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', |