Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(501)

Side by Side Diff: content/browser/geolocation/device_data_provider.h

Issue 6597044: Revert 76228 - Move core pieces of geolocation from chrome to content.This is... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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_
OLDNEW
« no previous file with comments | « content/browser/geolocation/core_location_provider_mac.mm ('k') | content/browser/geolocation/device_data_provider.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698