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.
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.
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.
16 // This file also provides DeviceDataProviderImplBase, a base class which
17 // provides commom functionality for the private implementations.
19 // This file also declares the data structures used to represent cell radio data
22 #ifndef CONTENT_BROWSER_GEOLOCATION_DEVICE_DATA_PROVIDER_H_
23 #define CONTENT_BROWSER_GEOLOCATION_DEVICE_DATA_PROVIDER_H_
27 #include "base/basictypes.h"
28 #include "base/bind.h"
29 #include "base/memory/ref_counted.h"
30 #include "base/message_loop.h"
31 #include "base/string16.h"
32 #include "base/string_util.h"
33 #include "base/threading/non_thread_safe.h"
34 #include "content/common/content_export.h"
38 // Wifi data relating to a single access point.
39 struct CONTENT_EXPORT AccessPointData
{
43 // MAC address, formatted as per MacAddressAsString16.
45 int radio_signal_strength
; // Measured in dBm
47 int signal_to_noise
; // Ratio in dB
48 string16 ssid
; // Network identifier
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
;
61 struct CONTENT_EXPORT WifiData
{
65 // Determines whether a new set of WiFi data differs significantly from this.
66 bool DiffersSignificantly(const WifiData
& other
) const;
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
;
74 template<typename DataType
>
75 class DeviceDataProvider
;
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
> {
82 friend class base::RefCountedThreadSafe
<DeviceDataProviderImplBaseHack
>;
83 virtual ~DeviceDataProviderImplBaseHack() {}
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
{
94 DeviceDataProviderImplBase()
95 : container_(NULL
), client_loop_(MessageLoop::current()) {
99 virtual bool StartDataProvider() = 0;
100 virtual void StopDataProvider() = 0;
101 virtual bool GetData(DataType
* data
) = 0;
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
106 void SetContainer(DeviceDataProvider
<DataType
>* container
) {
107 DCHECK(CalledOnClientThread());
108 container_
= container
;
111 typedef typename DeviceDataProvider
<DataType
>::ListenerInterface
113 void AddListener(ListenerInterface
* listener
) {
114 DCHECK(CalledOnClientThread());
115 listeners_
.insert(listener
);
117 bool RemoveListener(ListenerInterface
* listener
) {
118 DCHECK(CalledOnClientThread());
119 return listeners_
.erase(listener
) == 1;
122 bool has_listeners() const {
123 DCHECK(CalledOnClientThread());
124 return !listeners_
.empty();
128 virtual ~DeviceDataProviderImplBase() {
129 DCHECK(CalledOnClientThread());
132 // Calls DeviceDataUpdateAvailable() on all registered listeners.
133 typedef std::set
<ListenerInterface
*> ListenersSet
;
134 void NotifyListeners() {
135 // Always make the notify callback via a posted task, so we can unwind
136 // callstack here and make callback without causing client re-entrancy.
137 client_loop_
->PostTask(FROM_HERE
, base::Bind(
138 &DeviceDataProviderImplBase
<DataType
>::NotifyListenersInClientLoop
,
142 bool CalledOnClientThread() const {
143 return MessageLoop::current() == this->client_loop_
;
146 MessageLoop
* client_loop() const {
151 void NotifyListenersInClientLoop() {
152 DCHECK(CalledOnClientThread());
153 // It's possible that all the listeners (and the container) went away
154 // whilst this task was pending. This is fine; the loop will be a no-op.
155 typename
ListenersSet::const_iterator iter
= listeners_
.begin();
156 while (iter
!= listeners_
.end()) {
157 ListenerInterface
* listener
= *iter
;
158 ++iter
; // Advance iter before callback, in case listener unregisters.
159 listener
->DeviceDataUpdateAvailable(container_
);
163 DeviceDataProvider
<DataType
>* container_
;
165 // Reference to the client's message loop, all callbacks and access to
166 // the listeners_ member should happen in this context.
167 MessageLoop
* client_loop_
;
169 ListenersSet listeners_
;
171 DISALLOW_COPY_AND_ASSIGN(DeviceDataProviderImplBase
);
174 typedef DeviceDataProviderImplBase
<WifiData
> WifiDataProviderImplBase
;
176 // A device data provider
178 // We use a singleton instance of this class which is shared by multiple network
179 // location providers. These location providers access the instance through the
180 // Register and Unregister methods.
181 template<typename DataType
>
182 class DeviceDataProvider
: public base::NonThreadSafe
{
184 // Interface to be implemented by listeners to a device data provider.
185 class ListenerInterface
{
187 // Will be called in the context of the thread that called Register().
188 virtual void DeviceDataUpdateAvailable(
189 DeviceDataProvider
<DataType
>* provider
) = 0;
190 virtual ~ListenerInterface() {}
193 // Sets the factory function which will be used by Register to create the
194 // implementation used by the singleton instance. This factory approach is
195 // used to abastract accross both platform-specific implementation and to
196 // inject mock implementations for testing.
197 typedef DeviceDataProviderImplBase
<DataType
>* (*ImplFactoryFunction
)(void);
198 static void SetFactory(ImplFactoryFunction factory_function_in
) {
199 factory_function_
= factory_function_in
;
202 static void ResetFactory() {
203 factory_function_
= DefaultFactoryFunction
;
206 // Adds a listener, which will be called back with DeviceDataUpdateAvailable
207 // whenever new data is available. Returns the singleton instance.
208 static DeviceDataProvider
* Register(ListenerInterface
* listener
) {
209 bool need_to_start_thread
= false;
211 instance_
= new DeviceDataProvider();
212 need_to_start_thread
= true;
215 DCHECK(instance_
->CalledOnValidThread());
216 instance_
->AddListener(listener
);
217 // Start the provider after adding the listener, to avoid any race in
218 // it receiving an early callback.
219 if (need_to_start_thread
) {
220 bool started
= instance_
->StartDataProvider();
226 // Removes a listener. If this is the last listener, deletes the singleton
227 // instance. Return value indicates success.
228 static bool Unregister(ListenerInterface
* listener
) {
230 DCHECK(instance_
->CalledOnValidThread());
231 DCHECK(instance_
->has_listeners());
232 if (!instance_
->RemoveListener(listener
)) {
235 if (!instance_
->has_listeners()) {
236 // Must stop the provider (and any implementation threads) before
237 // destroying to avoid any race conditions in access to the provider in
238 // the destructor chain.
239 instance_
->StopDataProvider();
246 // Provides whatever data the provider has, which may be nothing. Return
247 // value indicates whether this is all the data the provider could ever
249 bool GetData(DataType
* data
) {
250 DCHECK(this->CalledOnValidThread());
251 return impl_
->GetData(data
);
255 // Private constructor and destructor, callers access singleton through
256 // Register and Unregister.
257 DeviceDataProvider() {
258 DCHECK(factory_function_
);
259 impl_
= (*factory_function_
)();
261 impl_
->SetContainer(this);
263 virtual ~DeviceDataProvider() {
265 impl_
->SetContainer(NULL
);
268 void AddListener(ListenerInterface
* listener
) {
269 impl_
->AddListener(listener
);
272 bool RemoveListener(ListenerInterface
* listener
) {
273 return impl_
->RemoveListener(listener
);
276 bool has_listeners() const {
277 return impl_
->has_listeners();
280 bool StartDataProvider() {
281 return impl_
->StartDataProvider();
284 void StopDataProvider() {
285 impl_
->StopDataProvider();
288 CONTENT_EXPORT
static DeviceDataProviderImplBase
<DataType
>*
289 DefaultFactoryFunction();
291 // The singleton-like instance of this class. (Not 'true' singleton, as it
292 // may go through multiple create/destroy/create cycles per process instance,
293 // e.g. when under test).
294 CONTENT_EXPORT
static DeviceDataProvider
* instance_
;
296 // The factory function used to create the singleton instance.
297 CONTENT_EXPORT
static ImplFactoryFunction factory_function_
;
299 // The internal implementation.
300 scoped_refptr
<DeviceDataProviderImplBase
<DataType
> > impl_
;
302 DISALLOW_COPY_AND_ASSIGN(DeviceDataProvider
);
305 typedef DeviceDataProvider
<WifiData
> WifiDataProvider
;
307 } // namespace content
309 #endif // CONTENT_BROWSER_GEOLOCATION_DEVICE_DATA_PROVIDER_H_