| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 // Copyright (c) 2010 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 #pragma once |  | 
| 25 |  | 
| 26 #include <algorithm> |  | 
| 27 #include <set> |  | 
| 28 #include <vector> |  | 
| 29 |  | 
| 30 #include "base/basictypes.h" |  | 
| 31 #include "base/message_loop.h" |  | 
| 32 #include "base/ref_counted.h" |  | 
| 33 #include "base/string16.h" |  | 
| 34 #include "base/string_util.h" |  | 
| 35 #include "base/task.h" |  | 
| 36 #include "base/threading/non_thread_safe.h" |  | 
| 37 |  | 
| 38 // The following data structures are used to store cell radio data and wifi |  | 
| 39 // data. See the Geolocation API design document at |  | 
| 40 // http://code.google.com/p/google-gears/wiki/LocationAPI for a more complete |  | 
| 41 // description. |  | 
| 42 // |  | 
| 43 // For all integer fields, we use kint32min to represent unknown values. |  | 
| 44 |  | 
| 45 // Cell radio data relating to a single cell tower. |  | 
| 46 struct CellData { |  | 
| 47   CellData(); |  | 
| 48   bool Matches(const CellData &other) const { |  | 
| 49     // Ignore radio_signal_strength when matching. |  | 
| 50     return cell_id == other.cell_id && |  | 
| 51            location_area_code == other.location_area_code && |  | 
| 52            mobile_network_code == other.mobile_network_code && |  | 
| 53            mobile_country_code == other.mobile_country_code && |  | 
| 54            timing_advance == other.timing_advance; |  | 
| 55   } |  | 
| 56 |  | 
| 57   int cell_id;                // Unique identifier of the cell |  | 
| 58   int location_area_code;     // For current location area |  | 
| 59   int mobile_network_code;    // For current cell |  | 
| 60   int mobile_country_code;    // For current cell |  | 
| 61   int radio_signal_strength;  // Measured in dBm. |  | 
| 62   int timing_advance;         // Timing advance representing the distance from |  | 
| 63                               // the cell tower. Each unit is roughly 550 |  | 
| 64                               // meters. |  | 
| 65 }; |  | 
| 66 |  | 
| 67 enum RadioType { |  | 
| 68   RADIO_TYPE_UNKNOWN, |  | 
| 69   RADIO_TYPE_GSM, |  | 
| 70   RADIO_TYPE_CDMA, |  | 
| 71   RADIO_TYPE_WCDMA, |  | 
| 72 }; |  | 
| 73 |  | 
| 74 // All data for the cell radio. |  | 
| 75 struct RadioData { |  | 
| 76   RadioData(); |  | 
| 77   ~RadioData(); |  | 
| 78 |  | 
| 79   bool Matches(const RadioData &other) const; |  | 
| 80 |  | 
| 81   // Determines whether a new set of radio data differs significantly from this. |  | 
| 82   bool DiffersSignificantly(const RadioData &other) const { |  | 
| 83     // This is required by MockDeviceDataProviderImpl. |  | 
| 84     // TODO(steveblock): Implement properly. |  | 
| 85     return !Matches(other); |  | 
| 86   } |  | 
| 87 |  | 
| 88   string16 device_id; |  | 
| 89   std::vector<CellData> cell_data; |  | 
| 90   int home_mobile_network_code;  // For the device's home network. |  | 
| 91   int home_mobile_country_code;  // For the device's home network. |  | 
| 92   RadioType radio_type;          // Mobile radio type. |  | 
| 93   string16 carrier;              // Carrier name. |  | 
| 94 }; |  | 
| 95 |  | 
| 96 // Wifi data relating to a single access point. |  | 
| 97 struct AccessPointData { |  | 
| 98   AccessPointData(); |  | 
| 99   ~AccessPointData(); |  | 
| 100 |  | 
| 101   // MAC address, formatted as per MacAddressAsString16. |  | 
| 102   string16 mac_address; |  | 
| 103   int radio_signal_strength;  // Measured in dBm |  | 
| 104   int channel; |  | 
| 105   int signal_to_noise;  // Ratio in dB |  | 
| 106   string16 ssid;   // Network identifier |  | 
| 107 }; |  | 
| 108 |  | 
| 109 // This is to allow AccessPointData to be used in std::set. We order |  | 
| 110 // lexicographically by MAC address. |  | 
| 111 struct AccessPointDataLess { |  | 
| 112   bool operator()(const AccessPointData& data1, |  | 
| 113                   const AccessPointData& data2) const { |  | 
| 114     return data1.mac_address < data2.mac_address; |  | 
| 115   } |  | 
| 116 }; |  | 
| 117 |  | 
| 118 // All data for wifi. |  | 
| 119 struct WifiData { |  | 
| 120   WifiData(); |  | 
| 121   ~WifiData(); |  | 
| 122 |  | 
| 123   // Determines whether a new set of WiFi data differs significantly from this. |  | 
| 124   bool DiffersSignificantly(const WifiData& other) const; |  | 
| 125 |  | 
| 126   // Store access points as a set, sorted by MAC address. This allows quick |  | 
| 127   // comparison of sets for detecting changes and for caching. |  | 
| 128   typedef std::set<AccessPointData, AccessPointDataLess> AccessPointDataSet; |  | 
| 129   AccessPointDataSet access_point_data; |  | 
| 130 }; |  | 
| 131 |  | 
| 132 // Gateway data relating to a single router. |  | 
| 133 struct RouterData { |  | 
| 134   // MAC address, formatted as per MacAddressAsString16. |  | 
| 135   string16 mac_address; |  | 
| 136 }; |  | 
| 137 |  | 
| 138 // This is to allow RouterData to be used in std::set. We order |  | 
| 139 // lexicographically by MAC address. |  | 
| 140 struct RouterDataLess { |  | 
| 141   bool operator()(const RouterData& data1, |  | 
| 142                   const RouterData& data2) const { |  | 
| 143     return data1.mac_address < data2.mac_address; |  | 
| 144   } |  | 
| 145 }; |  | 
| 146 |  | 
| 147 // All gateway data for routers. |  | 
| 148 struct GatewayData { |  | 
| 149   GatewayData(); |  | 
| 150   ~GatewayData(); |  | 
| 151 |  | 
| 152   // Determines whether a new set of gateway data differs significantly |  | 
| 153   // from this. |  | 
| 154   bool DiffersSignificantly(const GatewayData& other) const; |  | 
| 155 |  | 
| 156   // Store routers as a set, sorted by MAC address. This allows quick |  | 
| 157   // comparison of sets for detecting changes and for caching. |  | 
| 158   typedef std::set<RouterData, RouterDataLess> RouterDataSet; |  | 
| 159   RouterDataSet router_data; |  | 
| 160 }; |  | 
| 161 |  | 
| 162 template<typename DataType> |  | 
| 163 class DeviceDataProvider; |  | 
| 164 |  | 
| 165 // This class just exists to work-around MSVC2005 not being able to have a |  | 
| 166 // template class implement RefCountedThreadSafe |  | 
| 167 class DeviceDataProviderImplBaseHack |  | 
| 168     : public base::RefCountedThreadSafe<DeviceDataProviderImplBaseHack> { |  | 
| 169  protected: |  | 
| 170   friend class base::RefCountedThreadSafe<DeviceDataProviderImplBaseHack>; |  | 
| 171   virtual ~DeviceDataProviderImplBaseHack() {} |  | 
| 172 }; |  | 
| 173 |  | 
| 174 // See class DeviceDataProvider for the public client API. |  | 
| 175 // DeviceDataProvider uses containment to hide platform-specific implementation |  | 
| 176 // details from common code. This class provides common functionality for these |  | 
| 177 // contained implementation classes. This is a modified pimpl pattern: this |  | 
| 178 // class needs to be in the public header due to use of templating. |  | 
| 179 template<typename DataType> |  | 
| 180 class DeviceDataProviderImplBase : public DeviceDataProviderImplBaseHack { |  | 
| 181  public: |  | 
| 182   DeviceDataProviderImplBase() |  | 
| 183       : container_(NULL), client_loop_(MessageLoop::current()) { |  | 
| 184     DCHECK(client_loop_); |  | 
| 185   } |  | 
| 186 |  | 
| 187   virtual bool StartDataProvider() = 0; |  | 
| 188   virtual void StopDataProvider() = 0; |  | 
| 189   virtual bool GetData(DataType* data) = 0; |  | 
| 190 |  | 
| 191   // Sets the container of this class, which is of type DeviceDataProvider. |  | 
| 192   // This is required to pass as a parameter when making the callback to |  | 
| 193   // listeners. |  | 
| 194   void SetContainer(DeviceDataProvider<DataType>* container) { |  | 
| 195     DCHECK(CalledOnClientThread()); |  | 
| 196     container_ = container; |  | 
| 197   } |  | 
| 198 |  | 
| 199   typedef typename DeviceDataProvider<DataType>::ListenerInterface |  | 
| 200           ListenerInterface; |  | 
| 201   void AddListener(ListenerInterface* listener) { |  | 
| 202     DCHECK(CalledOnClientThread()); |  | 
| 203     listeners_.insert(listener); |  | 
| 204   } |  | 
| 205   bool RemoveListener(ListenerInterface* listener) { |  | 
| 206     DCHECK(CalledOnClientThread()); |  | 
| 207     return listeners_.erase(listener) == 1; |  | 
| 208   } |  | 
| 209 |  | 
| 210   bool has_listeners() const { |  | 
| 211     DCHECK(CalledOnClientThread()); |  | 
| 212     return !listeners_.empty(); |  | 
| 213   } |  | 
| 214 |  | 
| 215  protected: |  | 
| 216   virtual ~DeviceDataProviderImplBase() { |  | 
| 217     DCHECK(CalledOnClientThread()); |  | 
| 218   } |  | 
| 219 |  | 
| 220   // Calls DeviceDataUpdateAvailable() on all registered listeners. |  | 
| 221   typedef std::set<ListenerInterface*> ListenersSet; |  | 
| 222   void NotifyListeners() { |  | 
| 223     // Always make the nitofy callback via a posted task, se we can unwind |  | 
| 224     // callstack here and make callback without causing client re-entrancy. |  | 
| 225     client_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, |  | 
| 226         &DeviceDataProviderImplBase<DataType>::NotifyListenersInClientLoop)); |  | 
| 227   } |  | 
| 228 |  | 
| 229   bool CalledOnClientThread() const { |  | 
| 230     return MessageLoop::current() == this->client_loop_; |  | 
| 231   } |  | 
| 232 |  | 
| 233  private: |  | 
| 234   void NotifyListenersInClientLoop() { |  | 
| 235     DCHECK(CalledOnClientThread()); |  | 
| 236     // It's possible that all the listeners (and the container) went away |  | 
| 237     // whilst this task was pending. This is fine; the loop will be a no-op. |  | 
| 238     typename ListenersSet::const_iterator iter = listeners_.begin(); |  | 
| 239     while (iter != listeners_.end()) { |  | 
| 240       ListenerInterface* listener = *iter; |  | 
| 241       ++iter;  // Advance iter before callback, in case listener unregisters. |  | 
| 242       listener->DeviceDataUpdateAvailable(container_); |  | 
| 243     } |  | 
| 244   } |  | 
| 245 |  | 
| 246   DeviceDataProvider<DataType>* container_; |  | 
| 247 |  | 
| 248   // Reference to the client's message loop, all callbacks and access to |  | 
| 249   // the listeners_ member should happen in this context. |  | 
| 250   MessageLoop* client_loop_; |  | 
| 251 |  | 
| 252   ListenersSet listeners_; |  | 
| 253 |  | 
| 254   DISALLOW_COPY_AND_ASSIGN(DeviceDataProviderImplBase); |  | 
| 255 }; |  | 
| 256 |  | 
| 257 typedef DeviceDataProviderImplBase<GatewayData> GatewayDataProviderImplBase; |  | 
| 258 typedef DeviceDataProviderImplBase<RadioData> RadioDataProviderImplBase; |  | 
| 259 typedef DeviceDataProviderImplBase<WifiData> WifiDataProviderImplBase; |  | 
| 260 |  | 
| 261 // A device data provider |  | 
| 262 // |  | 
| 263 // We use a singleton instance of this class which is shared by multiple network |  | 
| 264 // location providers. These location providers access the instance through the |  | 
| 265 // Register and Unregister methods. |  | 
| 266 template<typename DataType> |  | 
| 267 class DeviceDataProvider : public base::NonThreadSafe { |  | 
| 268  public: |  | 
| 269   // Interface to be implemented by listeners to a device data provider. |  | 
| 270   class ListenerInterface { |  | 
| 271    public: |  | 
| 272     // Will be called in the context of the thread that called Register(). |  | 
| 273     virtual void DeviceDataUpdateAvailable( |  | 
| 274         DeviceDataProvider<DataType>* provider) = 0; |  | 
| 275     virtual ~ListenerInterface() {} |  | 
| 276   }; |  | 
| 277 |  | 
| 278   // Sets the factory function which will be used by Register to create the |  | 
| 279   // implementation used by the singleton instance. This factory approach is |  | 
| 280   // used to abastract accross both platform-specific implementation and to |  | 
| 281   // inject mock implementations for testing. |  | 
| 282   typedef DeviceDataProviderImplBase<DataType>* (*ImplFactoryFunction)(void); |  | 
| 283   static void SetFactory(ImplFactoryFunction factory_function_in) { |  | 
| 284     factory_function_ = factory_function_in; |  | 
| 285   } |  | 
| 286 |  | 
| 287   static void ResetFactory() { |  | 
| 288     factory_function_ = DefaultFactoryFunction; |  | 
| 289   } |  | 
| 290 |  | 
| 291   // Adds a listener, which will be called back with DeviceDataUpdateAvailable |  | 
| 292   // whenever new data is available. Returns the singleton instance. |  | 
| 293   static DeviceDataProvider* Register(ListenerInterface* listener) { |  | 
| 294     bool need_to_start_thread = false; |  | 
| 295     if (!instance_) { |  | 
| 296       instance_ = new DeviceDataProvider(); |  | 
| 297       need_to_start_thread = true; |  | 
| 298     } |  | 
| 299     DCHECK(instance_); |  | 
| 300     DCHECK(instance_->CalledOnValidThread()); |  | 
| 301     instance_->AddListener(listener); |  | 
| 302     // Start the provider after adding the listener, to avoid any race in |  | 
| 303     // it receiving an early callback. |  | 
| 304     if (need_to_start_thread) { |  | 
| 305       bool started = instance_->StartDataProvider(); |  | 
| 306       DCHECK(started); |  | 
| 307     } |  | 
| 308     return instance_; |  | 
| 309   } |  | 
| 310 |  | 
| 311   // Removes a listener. If this is the last listener, deletes the singleton |  | 
| 312   // instance. Return value indicates success. |  | 
| 313   static bool Unregister(ListenerInterface* listener) { |  | 
| 314     DCHECK(instance_); |  | 
| 315     DCHECK(instance_->CalledOnValidThread()); |  | 
| 316     DCHECK(instance_->has_listeners()); |  | 
| 317     if (!instance_->RemoveListener(listener)) { |  | 
| 318       return false; |  | 
| 319     } |  | 
| 320     if (!instance_->has_listeners()) { |  | 
| 321       // Must stop the provider (and any implementation threads) before |  | 
| 322       // destroying to avoid any race conditions in access to the provider in |  | 
| 323       // the destructor chain. |  | 
| 324       instance_->StopDataProvider(); |  | 
| 325       delete instance_; |  | 
| 326       instance_ = NULL; |  | 
| 327     } |  | 
| 328     return true; |  | 
| 329   } |  | 
| 330 |  | 
| 331   // Provides whatever data the provider has, which may be nothing. Return |  | 
| 332   // value indicates whether this is all the data the provider could ever |  | 
| 333   // obtain. |  | 
| 334   bool GetData(DataType* data) { |  | 
| 335     DCHECK(this->CalledOnValidThread()); |  | 
| 336     return impl_->GetData(data); |  | 
| 337   } |  | 
| 338 |  | 
| 339  private: |  | 
| 340   // Private constructor and destructor, callers access singleton through |  | 
| 341   // Register and Unregister. |  | 
| 342   DeviceDataProvider() { |  | 
| 343     DCHECK(factory_function_); |  | 
| 344     impl_ = (*factory_function_)(); |  | 
| 345     DCHECK(impl_); |  | 
| 346     impl_->SetContainer(this); |  | 
| 347   } |  | 
| 348   virtual ~DeviceDataProvider() { |  | 
| 349     DCHECK(impl_); |  | 
| 350     impl_->SetContainer(NULL); |  | 
| 351   } |  | 
| 352 |  | 
| 353   void AddListener(ListenerInterface* listener) { |  | 
| 354     impl_->AddListener(listener); |  | 
| 355   } |  | 
| 356 |  | 
| 357   bool RemoveListener(ListenerInterface* listener) { |  | 
| 358     return impl_->RemoveListener(listener); |  | 
| 359   } |  | 
| 360 |  | 
| 361   bool has_listeners() const { |  | 
| 362     return impl_->has_listeners(); |  | 
| 363   } |  | 
| 364 |  | 
| 365   bool StartDataProvider() { |  | 
| 366     return impl_->StartDataProvider(); |  | 
| 367   } |  | 
| 368 |  | 
| 369   void StopDataProvider() { |  | 
| 370     impl_->StopDataProvider(); |  | 
| 371   } |  | 
| 372 |  | 
| 373   static DeviceDataProviderImplBase<DataType>* DefaultFactoryFunction(); |  | 
| 374 |  | 
| 375   // The singleton-like instance of this class. (Not 'true' singleton, as it |  | 
| 376   // may go through multiple create/destroy/create cycles per process instance, |  | 
| 377   // e.g. when under test). |  | 
| 378   static DeviceDataProvider* instance_; |  | 
| 379 |  | 
| 380   // The factory function used to create the singleton instance. |  | 
| 381   static ImplFactoryFunction factory_function_; |  | 
| 382 |  | 
| 383   // The internal implementation. |  | 
| 384   scoped_refptr<DeviceDataProviderImplBase<DataType> > impl_; |  | 
| 385 |  | 
| 386   DISALLOW_COPY_AND_ASSIGN(DeviceDataProvider); |  | 
| 387 }; |  | 
| 388 |  | 
| 389 // static |  | 
| 390 template<typename DataType> |  | 
| 391 DeviceDataProvider<DataType>* DeviceDataProvider<DataType>::instance_ = NULL; |  | 
| 392 |  | 
| 393 // static |  | 
| 394 template<typename DataType> |  | 
| 395 typename DeviceDataProvider<DataType>::ImplFactoryFunction |  | 
| 396     DeviceDataProvider<DataType>::factory_function_ = DefaultFactoryFunction; |  | 
| 397 |  | 
| 398 typedef DeviceDataProvider<GatewayData> GatewayDataProvider; |  | 
| 399 typedef DeviceDataProvider<RadioData> RadioDataProvider; |  | 
| 400 typedef DeviceDataProvider<WifiData> WifiDataProvider; |  | 
| 401 |  | 
| 402 #endif  // CONTENT_BROWSER_GEOLOCATION_DEVICE_DATA_PROVIDER_H_ |  | 
| OLD | NEW | 
|---|