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