Home | History | Annotate | Download | only in geolocation
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // A device data provider provides data from the device that is used by a
      6 // NetworkLocationProvider to obtain a position fix. This data may be either
      7 // cell radio data or wifi data. For a given type of data, we use a singleton
      8 // instance of the device data provider, which is used by multiple
      9 // NetworkLocationProvider objects.
     10 //
     11 // This file providers DeviceDataProvider, which provides static methods to
     12 // access the singleton instance. The singleton instance uses a private
     13 // implementation to abstract across platforms and also to allow mock providers
     14 // to be used for testing.
     15 //
     16 // This file also provides DeviceDataProviderImplBase, a base class which
     17 // provides commom functionality for the private implementations.
     18 //
     19 // This file also declares the data structures used to represent cell radio data
     20 // and wifi data.
     21 
     22 #ifndef CONTENT_BROWSER_GEOLOCATION_DEVICE_DATA_PROVIDER_H_
     23 #define CONTENT_BROWSER_GEOLOCATION_DEVICE_DATA_PROVIDER_H_
     24 
     25 #include <set>
     26 
     27 #include "base/basictypes.h"
     28 #include "base/bind.h"
     29 #include "base/memory/ref_counted.h"
     30 #include "base/message_loop/message_loop.h"
     31 #include "base/strings/string16.h"
     32 #include "base/strings/string_util.h"
     33 #include "base/threading/non_thread_safe.h"
     34 #include "content/common/content_export.h"
     35 
     36 namespace content {
     37 
     38 // Wifi data relating to a single access point.
     39 struct CONTENT_EXPORT AccessPointData {
     40   AccessPointData();
     41   ~AccessPointData();
     42 
     43   // MAC address, formatted as per MacAddressAsString16.
     44   string16 mac_address;
     45   int radio_signal_strength;  // Measured in dBm
     46   int channel;
     47   int signal_to_noise;  // Ratio in dB
     48   string16 ssid;   // Network identifier
     49 };
     50 
     51 // This is to allow AccessPointData to be used in std::set. We order
     52 // lexicographically by MAC address.
     53 struct AccessPointDataLess {
     54   bool operator()(const AccessPointData& data1,
     55                   const AccessPointData& data2) const {
     56     return data1.mac_address < data2.mac_address;
     57   }
     58 };
     59 
     60 // All data for wifi.
     61 struct CONTENT_EXPORT WifiData {
     62   WifiData();
     63   ~WifiData();
     64 
     65   // Determines whether a new set of WiFi data differs significantly from this.
     66   bool DiffersSignificantly(const WifiData& other) const;
     67 
     68   // Store access points as a set, sorted by MAC address. This allows quick
     69   // comparison of sets for detecting changes and for caching.
     70   typedef std::set<AccessPointData, AccessPointDataLess> AccessPointDataSet;
     71   AccessPointDataSet access_point_data;
     72 };
     73 
     74 template<typename DataType>
     75 class DeviceDataProvider;
     76 
     77 // This class just exists to work-around MSVC2005 not being able to have a
     78 // template class implement RefCountedThreadSafe
     79 class CONTENT_EXPORT DeviceDataProviderImplBaseHack
     80     : public base::RefCountedThreadSafe<DeviceDataProviderImplBaseHack> {
     81  protected:
     82   friend class base::RefCountedThreadSafe<DeviceDataProviderImplBaseHack>;
     83   virtual ~DeviceDataProviderImplBaseHack() {}
     84 };
     85 
     86 // See class DeviceDataProvider for the public client API.
     87 // DeviceDataProvider uses containment to hide platform-specific implementation
     88 // details from common code. This class provides common functionality for these
     89 // contained implementation classes. This is a modified pimpl pattern: this
     90 // class needs to be in the public header due to use of templating.
     91 template<typename DataType>
     92 class DeviceDataProviderImplBase : public DeviceDataProviderImplBaseHack {
     93  public:
     94   DeviceDataProviderImplBase()
     95       : container_(NULL), client_loop_(base::MessageLoop::current()) {
     96     DCHECK(client_loop_);
     97   }
     98 
     99   virtual bool StartDataProvider() = 0;
    100   virtual void StopDataProvider() = 0;
    101   virtual bool GetData(DataType* data) = 0;
    102 
    103   // Sets the container of this class, which is of type DeviceDataProvider.
    104   // This is required to pass as a parameter when making the callback to
    105   // listeners.
    106   void SetContainer(DeviceDataProvider<DataType>* container) {
    107     DCHECK(CalledOnClientThread());
    108     container_ = container;
    109   }
    110 
    111   typedef typename DeviceDataProvider<DataType>::ListenerInterface
    112           ListenerInterface;
    113   void AddListener(ListenerInterface* listener) {
    114     DCHECK(CalledOnClientThread());
    115     listeners_.insert(listener);
    116   }
    117   bool RemoveListener(ListenerInterface* listener) {
    118     DCHECK(CalledOnClientThread());
    119     return listeners_.erase(listener) == 1;
    120   }
    121 
    122   bool has_listeners() const {
    123     DCHECK(CalledOnClientThread());
    124     return !listeners_.empty();
    125   }
    126 
    127  protected:
    128   virtual ~DeviceDataProviderImplBase() {}
    129 
    130   // Calls DeviceDataUpdateAvailable() on all registered listeners.
    131   typedef std::set<ListenerInterface*> ListenersSet;
    132   void NotifyListeners() {
    133     // Always make the notify callback via a posted task, so we can unwind
    134     // callstack here and make callback without causing client re-entrancy.
    135     client_loop_->PostTask(FROM_HERE, base::Bind(
    136         &DeviceDataProviderImplBase<DataType>::NotifyListenersInClientLoop,
    137         this));
    138   }
    139 
    140   bool CalledOnClientThread() const {
    141     return base::MessageLoop::current() == this->client_loop_;
    142   }
    143 
    144   base::MessageLoop* client_loop() const { return client_loop_; }
    145 
    146  private:
    147   void NotifyListenersInClientLoop() {
    148     DCHECK(CalledOnClientThread());
    149     // It's possible that all the listeners (and the container) went away
    150     // whilst this task was pending. This is fine; the loop will be a no-op.
    151     typename ListenersSet::const_iterator iter = listeners_.begin();
    152     while (iter != listeners_.end()) {
    153       ListenerInterface* listener = *iter;
    154       ++iter;  // Advance iter before callback, in case listener unregisters.
    155       listener->DeviceDataUpdateAvailable(container_);
    156     }
    157   }
    158 
    159   DeviceDataProvider<DataType>* container_;
    160 
    161   // Reference to the client's message loop, all callbacks and access to
    162   // the listeners_ member should happen in this context.
    163   base::MessageLoop* client_loop_;
    164 
    165   ListenersSet listeners_;
    166 
    167   DISALLOW_COPY_AND_ASSIGN(DeviceDataProviderImplBase);
    168 };
    169 
    170 typedef DeviceDataProviderImplBase<WifiData> WifiDataProviderImplBase;
    171 
    172 // A device data provider
    173 //
    174 // We use a singleton instance of this class which is shared by multiple network
    175 // location providers. These location providers access the instance through the
    176 // Register and Unregister methods.
    177 template<typename DataType>
    178 class DeviceDataProvider : public base::NonThreadSafe {
    179  public:
    180   // Interface to be implemented by listeners to a device data provider.
    181   class ListenerInterface {
    182    public:
    183     // Will be called in the context of the thread that called Register().
    184     virtual void DeviceDataUpdateAvailable(
    185         DeviceDataProvider<DataType>* provider) = 0;
    186     virtual ~ListenerInterface() {}
    187   };
    188 
    189   // Sets the factory function which will be used by Register to create the
    190   // implementation used by the singleton instance. This factory approach is
    191   // used to abastract accross both platform-specific implementation and to
    192   // inject mock implementations for testing.
    193   typedef DeviceDataProviderImplBase<DataType>* (*ImplFactoryFunction)(void);
    194   static void SetFactory(ImplFactoryFunction factory_function_in) {
    195     factory_function_ = factory_function_in;
    196   }
    197 
    198   static void ResetFactory() {
    199     factory_function_ = DefaultFactoryFunction;
    200   }
    201 
    202   // Adds a listener, which will be called back with DeviceDataUpdateAvailable
    203   // whenever new data is available. Returns the singleton instance.
    204   static DeviceDataProvider* Register(ListenerInterface* listener) {
    205     bool need_to_start_thread = false;
    206     if (!instance_) {
    207       instance_ = new DeviceDataProvider();
    208       need_to_start_thread = true;
    209     }
    210     DCHECK(instance_);
    211     DCHECK(instance_->CalledOnValidThread());
    212     instance_->AddListener(listener);
    213     // Start the provider after adding the listener, to avoid any race in
    214     // it receiving an early callback.
    215     if (need_to_start_thread) {
    216       bool started = instance_->StartDataProvider();
    217       DCHECK(started);
    218     }
    219     return instance_;
    220   }
    221 
    222   // Removes a listener. If this is the last listener, deletes the singleton
    223   // instance. Return value indicates success.
    224   static bool Unregister(ListenerInterface* listener) {
    225     DCHECK(instance_);
    226     DCHECK(instance_->CalledOnValidThread());
    227     DCHECK(instance_->has_listeners());
    228     if (!instance_->RemoveListener(listener)) {
    229       return false;
    230     }
    231     if (!instance_->has_listeners()) {
    232       // Must stop the provider (and any implementation threads) before
    233       // destroying to avoid any race conditions in access to the provider in
    234       // the destructor chain.
    235       instance_->StopDataProvider();
    236       delete instance_;
    237       instance_ = NULL;
    238     }
    239     return true;
    240   }
    241 
    242   // Provides whatever data the provider has, which may be nothing. Return
    243   // value indicates whether this is all the data the provider could ever
    244   // obtain.
    245   bool GetData(DataType* data) {
    246     DCHECK(this->CalledOnValidThread());
    247     return impl_->GetData(data);
    248   }
    249 
    250  private:
    251   // Private constructor and destructor, callers access singleton through
    252   // Register and Unregister.
    253   DeviceDataProvider() {
    254     DCHECK(factory_function_);
    255     impl_ = (*factory_function_)();
    256     DCHECK(impl_.get());
    257     impl_->SetContainer(this);
    258   }
    259   virtual ~DeviceDataProvider() {
    260     DCHECK(impl_.get());
    261     impl_->SetContainer(NULL);
    262   }
    263 
    264   void AddListener(ListenerInterface* listener) {
    265     impl_->AddListener(listener);
    266   }
    267 
    268   bool RemoveListener(ListenerInterface* listener) {
    269     return impl_->RemoveListener(listener);
    270   }
    271 
    272   bool has_listeners() const {
    273     return impl_->has_listeners();
    274   }
    275 
    276   bool StartDataProvider() {
    277     return impl_->StartDataProvider();
    278   }
    279 
    280   void StopDataProvider() {
    281     impl_->StopDataProvider();
    282   }
    283 
    284   CONTENT_EXPORT static DeviceDataProviderImplBase<DataType>*
    285       DefaultFactoryFunction();
    286 
    287   // The singleton-like instance of this class. (Not 'true' singleton, as it
    288   // may go through multiple create/destroy/create cycles per process instance,
    289   // e.g. when under test).
    290   CONTENT_EXPORT static DeviceDataProvider* instance_;
    291 
    292   // The factory function used to create the singleton instance.
    293   CONTENT_EXPORT static ImplFactoryFunction factory_function_;
    294 
    295   // The internal implementation.
    296   scoped_refptr<DeviceDataProviderImplBase<DataType> > impl_;
    297 
    298   DISALLOW_COPY_AND_ASSIGN(DeviceDataProvider);
    299 };
    300 
    301 typedef DeviceDataProvider<WifiData> WifiDataProvider;
    302 
    303 }  // namespace content
    304 
    305 #endif  // CONTENT_BROWSER_GEOLOCATION_DEVICE_DATA_PROVIDER_H_
    306