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

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

Issue 546116: Adding geolocation data provider infrastructure to Chrome.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 11 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
« no previous file with comments | « no previous file | chrome/browser/geolocation/empty_device_data_provider.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2008, Google Inc.
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are met:
5 //
6 // 1. Redistributions of source code must retain the above copyright notice,
7 // this list of conditions and the following disclaimer.
8 // 2. Redistributions in binary form must reproduce the above copyright notice,
9 // this list of conditions and the following disclaimer in the documentation
10 // and/or other materials provided with the distribution.
11 // 3. Neither the name of Google Inc. nor the names of its contributors may be
12 // used to endorse or promote products derived from this software without
13 // specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
18 // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 //
26 // A device data provider provides data from the device that is used by a
27 // NetworkLocationProvider to obtain a position fix. This data may be either
28 // cell radio data or wifi data. For a given type of data, we use a singleton
29 // instance of the device data provider, which is used by multiple
30 // NetworkLocationProvider objects.
31 //
32 // This file providers DeviceDataProvider, which provides static methods to
33 // access the singleton instance. The singleton instance uses a private
34 // implementation to abstract across platforms and also to allow mock providers
35 // to be used for testing.
36 //
37 // This file also provides DeviceDataProviderImplBase, a base class which
38 // provides commom functionality for the private implementations.
39 //
40 // This file also declares the data structures used to represent cell radio data
41 // and wifi data.
42
43 #ifndef GEARS_GEOLOCATION_DEVICE_DATA_PROVIDER_H__
44 #define GEARS_GEOLOCATION_DEVICE_DATA_PROVIDER_H__
45
46 #include <algorithm>
47 #include <set>
48 #include <vector>
49 #include "gears/base/common/basictypes.h" // For int64
50 #include "gears/base/common/common.h"
51 #include "gears/base/common/mutex.h"
52 #include "gears/base/common/scoped_refptr.h" // For RefCount
53 #include "gears/base/common/string16.h"
54 #include "third_party/scoped_ptr/scoped_ptr.h"
55
56 // The following data structures are used to store cell radio data and wifi
57 // data. See the Geolocation API design document at
58 // http://code.google.com/p/google-gears/wiki/LocationAPI for a more complete
59 // description.
60 //
61 // For all integer fields, we use kint32min to represent unknown values.
62
63 // Cell radio data relating to a single cell tower.
64 struct CellData {
65 CellData()
66 : cell_id(kint32min),
67 location_area_code(kint32min),
68 mobile_network_code(kint32min),
69 mobile_country_code(kint32min),
70 age(kint32min),
71 radio_signal_strength(kint32min),
72 timing_advance(kint32min) {}
73 bool Matches(const CellData &other) const {
74 // Ignore age and radio_signal_strength when matching.
75 return cell_id == other.cell_id &&
76 location_area_code == other.location_area_code &&
77 mobile_network_code == other.mobile_network_code &&
78 mobile_country_code == other.mobile_country_code &&
79 timing_advance == other.timing_advance;
80 }
81
82 int cell_id; // Unique identifier of the cell
83 int location_area_code; // For current location area
84 int mobile_network_code; // For current cell
85 int mobile_country_code; // For current cell
86 int age; // Milliseconds since this cell was primary
87 int radio_signal_strength; // Measured in dBm.
88 int timing_advance; // Timing advance representing the distance from
89 // the cell tower. Each unit is roughly 550
90 // meters.
91 };
92
93 static bool CellDataMatches(const CellData &data1, const CellData &data2) {
94 return data1.Matches(data2);
95 }
96
97 enum RadioType {
98 RADIO_TYPE_UNKNOWN,
99 RADIO_TYPE_GSM,
100 RADIO_TYPE_CDMA,
101 RADIO_TYPE_WCDMA,
102 };
103
104 // All data for the cell radio.
105 struct RadioData {
106 RadioData()
107 : home_mobile_network_code(kint32min),
108 home_mobile_country_code(kint32min),
109 radio_type(RADIO_TYPE_UNKNOWN) {}
110 bool Matches(const RadioData &other) const {
111 if (cell_data.size() != other.cell_data.size()) {
112 return false;
113 }
114 if (!std::equal(cell_data.begin(), cell_data.end(), other.cell_data.begin(),
115 CellDataMatches)) {
116 return false;
117 }
118 return device_id == other.device_id &&
119 home_mobile_network_code == other.home_mobile_network_code &&
120 home_mobile_country_code == other.home_mobile_country_code &&
121 radio_type == other.radio_type &&
122 carrier == other.carrier;
123 }
124 // Determines whether a new set of radio data differs significantly from this.
125 bool DiffersSignificantly(const RadioData &other) const {
126 // This is required by MockDeviceDataProviderImpl.
127 // TODO(steveblock): Implement properly.
128 return !Matches(other);
129 }
130
131 std::string16 device_id;
132 std::vector<CellData> cell_data;
133 int home_mobile_network_code; // For the device's home network.
134 int home_mobile_country_code; // For the device's home network.
135 RadioType radio_type; // Mobile radio type.
136 std::string16 carrier; // Carrier name.
137 };
138
139 // Wifi data relating to a single access point.
140 struct AccessPointData {
141 AccessPointData()
142 : radio_signal_strength(kint32min),
143 age(kint32min),
144 channel(kint32min),
145 signal_to_noise(kint32min) {}
146
147 std::string16 mac_address;
148 int radio_signal_strength; // Measured in dBm
149 int age; // Milliseconds since this access point was detected
150 int channel;
151 int signal_to_noise; // Ratio in dB
152 std::string16 ssid; // Network identifier
153 };
154
155 // This is to allow AccessPointData to be used in std::set. We order
156 // lexicographically by MAC address.
157 struct AccessPointDataLess : public std::less<AccessPointData> {
158 bool operator()(const AccessPointData &data1,
159 const AccessPointData &data2) const {
160 return data1.mac_address < data2.mac_address;
161 }
162 };
163
164 // All data for wifi.
165 struct WifiData {
166 // Determines whether a new set of WiFi data differs significantly from this.
167 bool DiffersSignificantly(const WifiData &other) const {
168 // At least 5 or 50% of access points added or removed is significant.
169 static const size_t kMinChangedAccessPoints = 5;
170
171 // Compute size of interesction of old and new sets.
172 size_t num_common = 0;
173 for (AccessPointDataSet::const_iterator iter = access_point_data.begin();
174 iter != access_point_data.end();
175 iter++) {
176 if (other.access_point_data.find(*iter) !=
177 other.access_point_data.end()) {
178 ++num_common;
179 }
180 }
181 assert(num_common <= access_point_data.size());
182 assert(num_common <= other.access_point_data.size());
183
184 // Test how many have changed.
185 size_t added_or_removed = std::max(
186 other.access_point_data.size() - num_common,
187 access_point_data.size() - num_common);
188 return added_or_removed >=
189 std::min(kMinChangedAccessPoints, access_point_data.size() / 2);
190 }
191
192 // Store access points as a set, sorted by MAC address. This allows quick
193 // comparison of sets for detecting changes and for caching.
194 typedef std::set<AccessPointData, AccessPointDataLess> AccessPointDataSet;
195 AccessPointDataSet access_point_data;
196 };
197
198 template<typename DataType>
199 class DeviceDataProvider;
200
201 // DeviceDataProvider uses containment to hide platform-specific implementation
202 // details from common code. This class provides common functionality for these
203 // contained implementation classes.
204 template<typename DataType>
205 class DeviceDataProviderImplBase {
206 public:
207 DeviceDataProviderImplBase() : container_(NULL) {}
208 virtual ~DeviceDataProviderImplBase() {}
209
210 virtual bool GetData(DataType *data) = 0;
211
212 // Sets the container of this class, which is of type DeviceDataProvider.
213 // This is required to pass as a parameter when making the callback to
214 // listeners.
215 void SetContainer(DeviceDataProvider<DataType> *container) {
216 container_ = container;
217 }
218
219 typedef typename DeviceDataProvider<DataType>::ListenerInterface
220 ListenerInterface;
221 void AddListener(ListenerInterface *listener) {
222 MutexLock mutex(&listeners_mutex_);
223 listeners_.insert(listener);
224 }
225 bool RemoveListener(ListenerInterface *listener) {
226 MutexLock mutex(&listeners_mutex_);
227 typename ListenersSet::iterator iter = find(listeners_.begin(),
228 listeners_.end(),
229 listener);
230 if (iter == listeners_.end()) {
231 return false;
232 }
233 listeners_.erase(iter);
234 return true;
235 }
236
237 protected:
238 // Calls DeviceDataUpdateAvailable() on all registered listeners.
239 typedef std::set<ListenerInterface*> ListenersSet;
240 void NotifyListeners() {
241 MutexLock lock(&listeners_mutex_);
242 for (typename ListenersSet::const_iterator iter = listeners_.begin();
243 iter != listeners_.end();
244 ++iter) {
245 (*iter)->DeviceDataUpdateAvailable(container_);
246 }
247 }
248
249 private:
250 DeviceDataProvider<DataType> *container_;
251
252 // The listeners to this class and their mutex.
253 ListenersSet listeners_;
254 Mutex listeners_mutex_;
255
256 DISALLOW_EVIL_CONSTRUCTORS(DeviceDataProviderImplBase);
257 };
258
259 typedef DeviceDataProviderImplBase<RadioData> RadioDataProviderImplBase;
260 typedef DeviceDataProviderImplBase<WifiData> WifiDataProviderImplBase;
261
262 // A device data provider
263 //
264 // We use a singleton instance of this class which is shared by multiple network
265 // location providers. These location providers access the instance through the
266 // Register and Unregister methods.
267 template<typename DataType>
268 class DeviceDataProvider {
269 public:
270 // Interface to be implemented by listeners to a device data provider.
271 class ListenerInterface {
272 public:
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 // We protect against Register and Unregister being called asynchronously
295 // from different threads. This is the case when a device data provider is
296 // used by a NetworkLocationProvider object. Register is always called from
297 // the JavaScript thread. Unregister is called when NetworkLocationProvider
298 // objects are destructed, which happens asynchronously once the
299 // NetworkLocationProvider HTTP request has completed.
300 MutexLock mutex(&instance_mutex_);
301 if (!instance_) {
302 instance_ = new DeviceDataProvider();
303 }
304 assert(instance_);
305 instance_->Ref();
306 instance_->AddListener(listener);
307 return instance_;
308 }
309
310 // Removes a listener. If this is the last listener, deletes the singleton
311 // instance. Return value indicates success.
312 static bool Unregister(ListenerInterface *listener) {
313 MutexLock mutex(&instance_mutex_);
314 if (!instance_->RemoveListener(listener)) {
315 return false;
316 }
317 if (instance_->Unref()) {
318 delete instance_;
319 instance_ = NULL;
320 }
321 return true;
322 }
323
324 // Provides whatever data the provider has, which may be nothing. Return
325 // value indicates whether this is all the data the provider could ever
326 // obtain.
327 bool GetData(DataType *data) {
328 return impl_->GetData(data);
329 }
330
331 private:
332 // Private constructor and destructor, callers access singleton through
333 // Register and Unregister.
334 DeviceDataProvider() {
335 assert(factory_function_);
336 impl_.reset((*factory_function_)());
337 impl_->SetContainer(this);
338 }
339 virtual ~DeviceDataProvider() {}
340
341 void Ref() {
342 count_.Ref();
343 }
344 // Returns true when the ref count transitions from 1 to 0.
345 bool Unref() {
346 return count_.Unref();
347 }
348
349 void AddListener(ListenerInterface *listener) {
350 impl_->AddListener(listener);
351 }
352
353 bool RemoveListener(ListenerInterface *listener) {
354 return impl_->RemoveListener(listener);
355 }
356
357 static DeviceDataProviderImplBase<DataType> *DefaultFactoryFunction();
358
359 // The singleton instance of this class and its mutex.
360 static DeviceDataProvider *instance_;
361 static Mutex instance_mutex_;
362
363 // The factory function used to create the singleton instance.
364 static ImplFactoryFunction factory_function_;
365
366 // The internal implementation.
367 scoped_ptr<DeviceDataProviderImplBase<DataType> > impl_;
368
369 RefCount count_;
370
371 DISALLOW_EVIL_CONSTRUCTORS(DeviceDataProvider);
372 };
373
374 // static
375 template<typename DataType>
376 Mutex DeviceDataProvider<DataType>::instance_mutex_;
377
378 // static
379 template<typename DataType>
380 DeviceDataProvider<DataType> *DeviceDataProvider<DataType>::instance_ =
381 NULL;
382
383 // static
384 template<typename DataType>
385 typename DeviceDataProvider<DataType>::ImplFactoryFunction
386 DeviceDataProvider<DataType>::factory_function_ = DefaultFactoryFunction;
387
388 typedef DeviceDataProvider<RadioData> RadioDataProvider;
389 typedef DeviceDataProvider<WifiData> WifiDataProvider;
390
391 #endif // GEARS_GEOLOCATION_DEVICE_DATA_PROVIDER_H__
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/geolocation/empty_device_data_provider.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698