| 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 CHROME_BROWSER_GEOLOCATION_DEVICE_DATA_PROVIDER_H_ | |
| 23 #define CHROME_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 // CHROME_BROWSER_GEOLOCATION_DEVICE_DATA_PROVIDER_H_ | |
| OLD | NEW |