[content shell] implement testRunner.overridePreference
[chromium-blink-merge.git] / content / browser / geolocation / device_data_provider.h
blobb1014ade13fab2bf713a0e1d9a3c9ecd8800fb78
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() {
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,
139 this));
142 bool CalledOnClientThread() const {
143 return MessageLoop::current() == this->client_loop_;
146 MessageLoop* client_loop() const {
147 return client_loop_;
150 private:
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 {
183 public:
184 // Interface to be implemented by listeners to a device data provider.
185 class ListenerInterface {
186 public:
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;
210 if (!instance_) {
211 instance_ = new DeviceDataProvider();
212 need_to_start_thread = true;
214 DCHECK(instance_);
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();
221 DCHECK(started);
223 return instance_;
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) {
229 DCHECK(instance_);
230 DCHECK(instance_->CalledOnValidThread());
231 DCHECK(instance_->has_listeners());
232 if (!instance_->RemoveListener(listener)) {
233 return false;
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();
240 delete instance_;
241 instance_ = NULL;
243 return true;
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
248 // obtain.
249 bool GetData(DataType* data) {
250 DCHECK(this->CalledOnValidThread());
251 return impl_->GetData(data);
254 private:
255 // Private constructor and destructor, callers access singleton through
256 // Register and Unregister.
257 DeviceDataProvider() {
258 DCHECK(factory_function_);
259 impl_ = (*factory_function_)();
260 DCHECK(impl_);
261 impl_->SetContainer(this);
263 virtual ~DeviceDataProvider() {
264 DCHECK(impl_);
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_