By moving the call to Load() up in SearchProvider::Start(), we are giving a chance...
[chromium-blink-merge.git] / content / browser / geolocation / device_data_provider.h
blob4918e303d4c6ec5703e2890e66b58b51b60c8f01
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
20 // and wifi data.
22 #ifndef CONTENT_BROWSER_GEOLOCATION_DEVICE_DATA_PROVIDER_H_
23 #define CONTENT_BROWSER_GEOLOCATION_DEVICE_DATA_PROVIDER_H_
25 #include <set>
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"
36 namespace content {
38 // Wifi data relating to a single access point.
39 struct CONTENT_EXPORT AccessPointData {
40 AccessPointData();
41 ~AccessPointData();
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
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;
60 // All data for wifi.
61 struct CONTENT_EXPORT WifiData {
62 WifiData();
63 ~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> {
81 protected:
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 {
93 public:
94 DeviceDataProviderImplBase()
95 : container_(NULL), client_loop_(MessageLoop::current()) {
96 DCHECK(client_loop_);
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
105 // listeners.
106 void SetContainer(DeviceDataProvider<DataType>* container) {
107 DCHECK(CalledOnClientThread());
108 container_ = container;
111 typedef typename DeviceDataProvider<DataType>::ListenerInterface
112 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();
127 protected:
128 virtual ~DeviceDataProviderImplBase() {}
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));
140 bool CalledOnClientThread() const {
141 return MessageLoop::current() == this->client_loop_;
144 MessageLoop* client_loop() const {
145 return client_loop_;
148 private:
149 void NotifyListenersInClientLoop() {
150 DCHECK(CalledOnClientThread());
151 // It's possible that all the listeners (and the container) went away
152 // whilst this task was pending. This is fine; the loop will be a no-op.
153 typename ListenersSet::const_iterator iter = listeners_.begin();
154 while (iter != listeners_.end()) {
155 ListenerInterface* listener = *iter;
156 ++iter; // Advance iter before callback, in case listener unregisters.
157 listener->DeviceDataUpdateAvailable(container_);
161 DeviceDataProvider<DataType>* container_;
163 // Reference to the client's message loop, all callbacks and access to
164 // the listeners_ member should happen in this context.
165 MessageLoop* client_loop_;
167 ListenersSet listeners_;
169 DISALLOW_COPY_AND_ASSIGN(DeviceDataProviderImplBase);
172 typedef DeviceDataProviderImplBase<WifiData> WifiDataProviderImplBase;
174 // A device data provider
176 // We use a singleton instance of this class which is shared by multiple network
177 // location providers. These location providers access the instance through the
178 // Register and Unregister methods.
179 template<typename DataType>
180 class DeviceDataProvider : public base::NonThreadSafe {
181 public:
182 // Interface to be implemented by listeners to a device data provider.
183 class ListenerInterface {
184 public:
185 // Will be called in the context of the thread that called Register().
186 virtual void DeviceDataUpdateAvailable(
187 DeviceDataProvider<DataType>* provider) = 0;
188 virtual ~ListenerInterface() {}
191 // Sets the factory function which will be used by Register to create the
192 // implementation used by the singleton instance. This factory approach is
193 // used to abastract accross both platform-specific implementation and to
194 // inject mock implementations for testing.
195 typedef DeviceDataProviderImplBase<DataType>* (*ImplFactoryFunction)(void);
196 static void SetFactory(ImplFactoryFunction factory_function_in) {
197 factory_function_ = factory_function_in;
200 static void ResetFactory() {
201 factory_function_ = DefaultFactoryFunction;
204 // Adds a listener, which will be called back with DeviceDataUpdateAvailable
205 // whenever new data is available. Returns the singleton instance.
206 static DeviceDataProvider* Register(ListenerInterface* listener) {
207 bool need_to_start_thread = false;
208 if (!instance_) {
209 instance_ = new DeviceDataProvider();
210 need_to_start_thread = true;
212 DCHECK(instance_);
213 DCHECK(instance_->CalledOnValidThread());
214 instance_->AddListener(listener);
215 // Start the provider after adding the listener, to avoid any race in
216 // it receiving an early callback.
217 if (need_to_start_thread) {
218 bool started = instance_->StartDataProvider();
219 DCHECK(started);
221 return instance_;
224 // Removes a listener. If this is the last listener, deletes the singleton
225 // instance. Return value indicates success.
226 static bool Unregister(ListenerInterface* listener) {
227 DCHECK(instance_);
228 DCHECK(instance_->CalledOnValidThread());
229 DCHECK(instance_->has_listeners());
230 if (!instance_->RemoveListener(listener)) {
231 return false;
233 if (!instance_->has_listeners()) {
234 // Must stop the provider (and any implementation threads) before
235 // destroying to avoid any race conditions in access to the provider in
236 // the destructor chain.
237 instance_->StopDataProvider();
238 delete instance_;
239 instance_ = NULL;
241 return true;
244 // Provides whatever data the provider has, which may be nothing. Return
245 // value indicates whether this is all the data the provider could ever
246 // obtain.
247 bool GetData(DataType* data) {
248 DCHECK(this->CalledOnValidThread());
249 return impl_->GetData(data);
252 private:
253 // Private constructor and destructor, callers access singleton through
254 // Register and Unregister.
255 DeviceDataProvider() {
256 DCHECK(factory_function_);
257 impl_ = (*factory_function_)();
258 DCHECK(impl_);
259 impl_->SetContainer(this);
261 virtual ~DeviceDataProvider() {
262 DCHECK(impl_);
263 impl_->SetContainer(NULL);
266 void AddListener(ListenerInterface* listener) {
267 impl_->AddListener(listener);
270 bool RemoveListener(ListenerInterface* listener) {
271 return impl_->RemoveListener(listener);
274 bool has_listeners() const {
275 return impl_->has_listeners();
278 bool StartDataProvider() {
279 return impl_->StartDataProvider();
282 void StopDataProvider() {
283 impl_->StopDataProvider();
286 CONTENT_EXPORT static DeviceDataProviderImplBase<DataType>*
287 DefaultFactoryFunction();
289 // The singleton-like instance of this class. (Not 'true' singleton, as it
290 // may go through multiple create/destroy/create cycles per process instance,
291 // e.g. when under test).
292 CONTENT_EXPORT static DeviceDataProvider* instance_;
294 // The factory function used to create the singleton instance.
295 CONTENT_EXPORT static ImplFactoryFunction factory_function_;
297 // The internal implementation.
298 scoped_refptr<DeviceDataProviderImplBase<DataType> > impl_;
300 DISALLOW_COPY_AND_ASSIGN(DeviceDataProvider);
303 typedef DeviceDataProvider<WifiData> WifiDataProvider;
305 } // namespace content
307 #endif // CONTENT_BROWSER_GEOLOCATION_DEVICE_DATA_PROVIDER_H_