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

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

Issue 22866005: Remove threading from WifiDataProviderCommon. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Use client_loop instead of message_loop. Created 7 years, 4 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // A device data provider provides data from the device that is used by a 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 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 7 // wifi data or (currently not used) cell radio data. For a given type of data,
8 // instance of the device data provider, which is used by multiple 8 // we use a singleton instance of the device data provider, which is used by
9 // NetworkLocationProvider objects. 9 // multiple NetworkLocationProvider objects.
10 // 10 //
11 // This file providers DeviceDataProvider, which provides static methods to 11 // This file provides DeviceDataProvider, which provides static methods to
12 // access the singleton instance. The singleton instance uses a private 12 // access the singleton instance. The singleton instance uses a private
13 // implementation to abstract across platforms and also to allow mock providers 13 // implementation to abstract across platforms and also to allow mock providers
14 // to be used for testing. 14 // to be used for testing.
15 // 15 //
16 // This file also provides DeviceDataProviderImplBase, a base class which 16 // This file also provides DeviceDataProviderImplBase, a base class which
17 // provides commom functionality for the private implementations. 17 // provides common functionality for the private implementations.
18 // 18 //
19 // This file also declares the data structures used to represent cell radio data 19 // This file also declares the data structure used to represent wifi data.
20 // and wifi data.
21 20
22 #ifndef CONTENT_BROWSER_GEOLOCATION_DEVICE_DATA_PROVIDER_H_ 21 #ifndef CONTENT_BROWSER_GEOLOCATION_DEVICE_DATA_PROVIDER_H_
23 #define CONTENT_BROWSER_GEOLOCATION_DEVICE_DATA_PROVIDER_H_ 22 #define CONTENT_BROWSER_GEOLOCATION_DEVICE_DATA_PROVIDER_H_
24 23
25 #include <set> 24 #include <set>
26 25
27 #include "base/basictypes.h" 26 #include "base/basictypes.h"
28 #include "base/bind.h" 27 #include "base/bind.h"
29 #include "base/memory/ref_counted.h" 28 #include "base/memory/ref_counted.h"
30 #include "base/message_loop/message_loop.h" 29 #include "base/message_loop/message_loop.h"
31 #include "base/strings/string16.h" 30 #include "base/strings/string16.h"
32 #include "base/strings/string_util.h" 31 #include "base/strings/string_util.h"
33 #include "base/threading/non_thread_safe.h"
34 #include "content/common/content_export.h" 32 #include "content/common/content_export.h"
35 33
36 namespace content { 34 namespace content {
37 35
38 // Wifi data relating to a single access point. 36 // Wifi data relating to a single access point.
39 struct CONTENT_EXPORT AccessPointData { 37 struct CONTENT_EXPORT AccessPointData {
40 AccessPointData(); 38 AccessPointData();
41 ~AccessPointData(); 39 ~AccessPointData();
42 40
43 // MAC address, formatted as per MacAddressAsString16. 41 // MAC address, formatted as per MacAddressAsString16.
(...skipping 26 matching lines...) Expand all
70 typedef std::set<AccessPointData, AccessPointDataLess> AccessPointDataSet; 68 typedef std::set<AccessPointData, AccessPointDataLess> AccessPointDataSet;
71 AccessPointDataSet access_point_data; 69 AccessPointDataSet access_point_data;
72 }; 70 };
73 71
74 template<typename DataType> 72 template<typename DataType>
75 class DeviceDataProvider; 73 class DeviceDataProvider;
76 74
77 // This class just exists to work-around MSVC2005 not being able to have a 75 // This class just exists to work-around MSVC2005 not being able to have a
78 // template class implement RefCountedThreadSafe 76 // template class implement RefCountedThreadSafe
79 class CONTENT_EXPORT DeviceDataProviderImplBaseHack 77 class CONTENT_EXPORT DeviceDataProviderImplBaseHack
80 : public base::RefCountedThreadSafe<DeviceDataProviderImplBaseHack> { 78 : public base::RefCountedThreadSafe<DeviceDataProviderImplBaseHack> {
bulach 2013/08/13 16:59:46 I suppose this no longer needs to be ThreadSafe, i
bulach 2013/08/13 17:23:32 just to capture our chat: CrOS still needs to be R
81 protected: 79 protected:
82 friend class base::RefCountedThreadSafe<DeviceDataProviderImplBaseHack>; 80 friend class base::RefCountedThreadSafe<DeviceDataProviderImplBaseHack>;
83 virtual ~DeviceDataProviderImplBaseHack() {} 81 virtual ~DeviceDataProviderImplBaseHack() {}
84 }; 82 };
85 83
86 // See class DeviceDataProvider for the public client API. 84 // See class DeviceDataProvider for the public client API.
87 // DeviceDataProvider uses containment to hide platform-specific implementation 85 // DeviceDataProvider uses containment to hide platform-specific implementation
88 // details from common code. This class provides common functionality for these 86 // details from common code. This class provides common functionality for these
89 // contained implementation classes. This is a modified pimpl pattern: this 87 // contained implementation classes. This is a modified pimpl pattern: this
90 // class needs to be in the public header due to use of templating. 88 // class needs to be in the public header due to use of templating.
91 template<typename DataType> 89 template<typename DataType>
92 class DeviceDataProviderImplBase : public DeviceDataProviderImplBaseHack { 90 class DeviceDataProviderImplBase : public DeviceDataProviderImplBaseHack {
93 public: 91 public:
94 DeviceDataProviderImplBase() 92 DeviceDataProviderImplBase()
95 : container_(NULL), client_loop_(base::MessageLoop::current()) { 93 : container_(NULL), client_loop_(base::MessageLoop::current()) {
96 DCHECK(client_loop_); 94 DCHECK(client_loop_);
97 } 95 }
98 96
99 virtual bool StartDataProvider() = 0; 97 // Tells the provider to start looking for data. Listeners will start
98 // receiving notifications.
bulach 2013/08/13 16:59:46 nit: to be extra safe, add "after this call". sinc
Michael van Ouwerkerk 2013/08/13 17:44:30 Done.
99 virtual void StartDataProvider() = 0;
100 // Tells the provider to stop looking for data. Listeners will stop
101 // receiving notifications.
100 virtual void StopDataProvider() = 0; 102 virtual void StopDataProvider() = 0;
101 virtual bool GetData(DataType* data) = 0; 103 virtual bool GetData(DataType* data) = 0;
102 104
103 // Sets the container of this class, which is of type DeviceDataProvider. 105 // 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 // This is required to pass as a parameter when making the callback to
105 // listeners. 107 // listeners.
106 void SetContainer(DeviceDataProvider<DataType>* container) { 108 void SetContainer(DeviceDataProvider<DataType>* container) {
107 DCHECK(CalledOnClientThread());
108 container_ = container; 109 container_ = container;
109 } 110 }
110 111
111 typedef typename DeviceDataProvider<DataType>::ListenerInterface 112 typedef typename DeviceDataProvider<DataType>::ListenerInterface
112 ListenerInterface; 113 ListenerInterface;
113 void AddListener(ListenerInterface* listener) { 114 void AddListener(ListenerInterface* listener) {
114 DCHECK(CalledOnClientThread());
115 listeners_.insert(listener); 115 listeners_.insert(listener);
116 } 116 }
117 bool RemoveListener(ListenerInterface* listener) { 117 bool RemoveListener(ListenerInterface* listener) {
118 DCHECK(CalledOnClientThread());
119 return listeners_.erase(listener) == 1; 118 return listeners_.erase(listener) == 1;
120 } 119 }
121 120
122 bool has_listeners() const { 121 bool has_listeners() const {
123 DCHECK(CalledOnClientThread());
124 return !listeners_.empty(); 122 return !listeners_.empty();
125 } 123 }
126 124
127 protected: 125 protected:
128 virtual ~DeviceDataProviderImplBase() {} 126 virtual ~DeviceDataProviderImplBase() {}
129 127
130 // Calls DeviceDataUpdateAvailable() on all registered listeners. 128 // Calls DeviceDataUpdateAvailable() on all registered listeners.
131 typedef std::set<ListenerInterface*> ListenersSet; 129 typedef std::set<ListenerInterface*> ListenersSet;
132 void NotifyListeners() { 130 void NotifyListeners() {
133 // Always make the notify callback via a posted task, so we can unwind 131 // Always make the notify callback via a posted task, so we can unwind
134 // callstack here and make callback without causing client re-entrancy. 132 // callstack here and make callback without causing client re-entrancy.
135 client_loop_->PostTask(FROM_HERE, base::Bind( 133 client_loop_->PostTask(FROM_HERE, base::Bind(
136 &DeviceDataProviderImplBase<DataType>::NotifyListenersInClientLoop, 134 &DeviceDataProviderImplBase<DataType>::DoNotifyListeners,
137 this)); 135 this));
138 } 136 }
139 137
140 bool CalledOnClientThread() const { 138 bool CalledOnClientThread() const {
141 return base::MessageLoop::current() == this->client_loop_; 139 return base::MessageLoop::current() == this->client_loop_;
142 } 140 }
143 141
144 base::MessageLoop* client_loop() const { return client_loop_; } 142 base::MessageLoop* client_loop() const { return client_loop_; }
145 143
146 private: 144 private:
147 void NotifyListenersInClientLoop() { 145 void DoNotifyListeners() {
148 DCHECK(CalledOnClientThread());
149 // It's possible that all the listeners (and the container) went away 146 // It's possible that all the listeners (and the container) went away
150 // whilst this task was pending. This is fine; the loop will be a no-op. 147 // whilst this task was pending. This is fine; the loop will be a no-op.
151 typename ListenersSet::const_iterator iter = listeners_.begin(); 148 typename ListenersSet::const_iterator iter = listeners_.begin();
152 while (iter != listeners_.end()) { 149 while (iter != listeners_.end()) {
153 ListenerInterface* listener = *iter; 150 ListenerInterface* listener = *iter;
154 ++iter; // Advance iter before callback, in case listener unregisters. 151 ++iter; // Advance iter before callback, in case listener unregisters.
155 listener->DeviceDataUpdateAvailable(container_); 152 listener->DeviceDataUpdateAvailable(container_);
156 } 153 }
157 } 154 }
158 155
159 DeviceDataProvider<DataType>* container_; 156 DeviceDataProvider<DataType>* container_;
160 157
161 // Reference to the client's message loop, all callbacks and access to 158 // Reference to the client's message loop, all callbacks and access to
162 // the listeners_ member should happen in this context. 159 // the listeners_ member should happen in this context.
163 base::MessageLoop* client_loop_; 160 base::MessageLoop* client_loop_;
164 161
165 ListenersSet listeners_; 162 ListenersSet listeners_;
166 163
167 DISALLOW_COPY_AND_ASSIGN(DeviceDataProviderImplBase); 164 DISALLOW_COPY_AND_ASSIGN(DeviceDataProviderImplBase);
168 }; 165 };
169 166
170 typedef DeviceDataProviderImplBase<WifiData> WifiDataProviderImplBase; 167 typedef DeviceDataProviderImplBase<WifiData> WifiDataProviderImplBase;
171 168
172 // A device data provider 169 // A device data provider
173 // 170 //
174 // We use a singleton instance of this class which is shared by multiple network 171 // We use a singleton instance of this class which is shared by multiple network
175 // location providers. These location providers access the instance through the 172 // location providers. These location providers access the instance through the
176 // Register and Unregister methods. 173 // Register and Unregister methods.
177 template<typename DataType> 174 template<typename DataType>
178 class DeviceDataProvider : public base::NonThreadSafe { 175 class DeviceDataProvider {
179 public: 176 public:
180 // Interface to be implemented by listeners to a device data provider. 177 // Interface to be implemented by listeners to a device data provider.
181 class ListenerInterface { 178 class ListenerInterface {
182 public: 179 public:
183 // Will be called in the context of the thread that called Register(). 180 // Will be called in the context of the thread that called Register().
184 virtual void DeviceDataUpdateAvailable( 181 virtual void DeviceDataUpdateAvailable(
185 DeviceDataProvider<DataType>* provider) = 0; 182 DeviceDataProvider<DataType>* provider) = 0;
186 virtual ~ListenerInterface() {} 183 virtual ~ListenerInterface() {}
187 }; 184 };
188 185
189 // Sets the factory function which will be used by Register to create the 186 // Sets the factory function which will be used by Register to create the
190 // implementation used by the singleton instance. This factory approach is 187 // implementation used by the singleton instance. This factory approach is
191 // used to abastract accross both platform-specific implementation and to 188 // used both to abstract accross platform-specific implementations and to
192 // inject mock implementations for testing. 189 // inject mock implementations for testing.
193 typedef DeviceDataProviderImplBase<DataType>* (*ImplFactoryFunction)(void); 190 typedef DeviceDataProviderImplBase<DataType>* (*ImplFactoryFunction)(void);
194 static void SetFactory(ImplFactoryFunction factory_function_in) { 191 static void SetFactory(ImplFactoryFunction factory_function_in) {
195 factory_function_ = factory_function_in; 192 factory_function_ = factory_function_in;
196 } 193 }
197 194
198 static void ResetFactory() { 195 static void ResetFactory() {
199 factory_function_ = DefaultFactoryFunction; 196 factory_function_ = DefaultFactoryFunction;
200 } 197 }
201 198
202 // Adds a listener, which will be called back with DeviceDataUpdateAvailable 199 // Adds a listener, which will be called back with DeviceDataUpdateAvailable
203 // whenever new data is available. Returns the singleton instance. 200 // whenever new data is available. Returns the singleton instance.
204 static DeviceDataProvider* Register(ListenerInterface* listener) { 201 static DeviceDataProvider* Register(ListenerInterface* listener) {
205 bool need_to_start_thread = false; 202 bool need_to_start_provider = false;
206 if (!instance_) { 203 if (!instance_) {
207 instance_ = new DeviceDataProvider(); 204 instance_ = new DeviceDataProvider();
208 need_to_start_thread = true; 205 need_to_start_provider = true;
209 } 206 }
210 DCHECK(instance_); 207 DCHECK(instance_);
211 DCHECK(instance_->CalledOnValidThread());
212 instance_->AddListener(listener); 208 instance_->AddListener(listener);
213 // Start the provider after adding the listener, to avoid any race in 209 // Start the provider after adding the listener, to avoid any race in
214 // it receiving an early callback. 210 // it receiving an early callback.
215 if (need_to_start_thread) { 211 if (need_to_start_provider)
216 bool started = instance_->StartDataProvider(); 212 instance_->StartDataProvider();
217 DCHECK(started);
218 }
219 return instance_; 213 return instance_;
220 } 214 }
221 215
222 // Removes a listener. If this is the last listener, deletes the singleton 216 // Removes a listener. If this is the last listener, deletes the singleton
223 // instance. Return value indicates success. 217 // instance. Return value indicates success.
224 static bool Unregister(ListenerInterface* listener) { 218 static bool Unregister(ListenerInterface* listener) {
225 DCHECK(instance_); 219 DCHECK(instance_);
226 DCHECK(instance_->CalledOnValidThread());
227 DCHECK(instance_->has_listeners()); 220 DCHECK(instance_->has_listeners());
228 if (!instance_->RemoveListener(listener)) { 221 if (!instance_->RemoveListener(listener)) {
229 return false; 222 return false;
230 } 223 }
231 if (!instance_->has_listeners()) { 224 if (!instance_->has_listeners()) {
232 // Must stop the provider (and any implementation threads) before 225 // Must stop the provider (and any implementation threads) before
233 // destroying to avoid any race conditions in access to the provider in 226 // destroying to avoid any race conditions in access to the provider in
234 // the destructor chain. 227 // the destructor chain.
235 instance_->StopDataProvider(); 228 instance_->StopDataProvider();
236 delete instance_; 229 delete instance_;
237 instance_ = NULL; 230 instance_ = NULL;
238 } 231 }
239 return true; 232 return true;
240 } 233 }
241 234
242 // Provides whatever data the provider has, which may be nothing. Return 235 // Provides whatever data the provider has, which may be nothing. Return
243 // value indicates whether this is all the data the provider could ever 236 // value indicates whether this is all the data the provider could ever
244 // obtain. 237 // obtain.
245 bool GetData(DataType* data) { 238 bool GetData(DataType* data) {
246 DCHECK(this->CalledOnValidThread());
247 return impl_->GetData(data); 239 return impl_->GetData(data);
248 } 240 }
249 241
250 private: 242 private:
251 // Private constructor and destructor, callers access singleton through 243 // Private constructor and destructor, callers access singleton through
252 // Register and Unregister. 244 // Register and Unregister.
253 DeviceDataProvider() { 245 DeviceDataProvider() {
254 DCHECK(factory_function_); 246 DCHECK(factory_function_);
255 impl_ = (*factory_function_)(); 247 impl_ = (*factory_function_)();
256 DCHECK(impl_.get()); 248 DCHECK(impl_.get());
257 impl_->SetContainer(this); 249 impl_->SetContainer(this);
258 } 250 }
259 virtual ~DeviceDataProvider() { 251 virtual ~DeviceDataProvider() {
260 DCHECK(impl_.get()); 252 DCHECK(impl_.get());
261 impl_->SetContainer(NULL); 253 impl_->SetContainer(NULL);
262 } 254 }
263 255
264 void AddListener(ListenerInterface* listener) { 256 void AddListener(ListenerInterface* listener) {
265 impl_->AddListener(listener); 257 impl_->AddListener(listener);
266 } 258 }
267 259
268 bool RemoveListener(ListenerInterface* listener) { 260 bool RemoveListener(ListenerInterface* listener) {
269 return impl_->RemoveListener(listener); 261 return impl_->RemoveListener(listener);
270 } 262 }
271 263
272 bool has_listeners() const { 264 bool has_listeners() const {
273 return impl_->has_listeners(); 265 return impl_->has_listeners();
274 } 266 }
275 267
276 bool StartDataProvider() { 268 void StartDataProvider() {
277 return impl_->StartDataProvider(); 269 impl_->StartDataProvider();
278 } 270 }
279 271
280 void StopDataProvider() { 272 void StopDataProvider() {
281 impl_->StopDataProvider(); 273 impl_->StopDataProvider();
282 } 274 }
283 275
284 CONTENT_EXPORT static DeviceDataProviderImplBase<DataType>* 276 CONTENT_EXPORT static DeviceDataProviderImplBase<DataType>*
285 DefaultFactoryFunction(); 277 DefaultFactoryFunction();
286 278
287 // The singleton-like instance of this class. (Not 'true' singleton, as it 279 // The singleton-like instance of this class. (Not 'true' singleton, as it
288 // may go through multiple create/destroy/create cycles per process instance, 280 // may go through multiple create/destroy/create cycles per process instance,
289 // e.g. when under test). 281 // e.g. when under test).
290 CONTENT_EXPORT static DeviceDataProvider* instance_; 282 CONTENT_EXPORT static DeviceDataProvider* instance_;
291 283
292 // The factory function used to create the singleton instance. 284 // The factory function used to create the singleton instance.
293 CONTENT_EXPORT static ImplFactoryFunction factory_function_; 285 CONTENT_EXPORT static ImplFactoryFunction factory_function_;
294 286
295 // The internal implementation. 287 // The internal implementation.
296 scoped_refptr<DeviceDataProviderImplBase<DataType> > impl_; 288 scoped_refptr<DeviceDataProviderImplBase<DataType> > impl_;
297 289
298 DISALLOW_COPY_AND_ASSIGN(DeviceDataProvider); 290 DISALLOW_COPY_AND_ASSIGN(DeviceDataProvider);
299 }; 291 };
300 292
301 typedef DeviceDataProvider<WifiData> WifiDataProvider; 293 typedef DeviceDataProvider<WifiData> WifiDataProvider;
302 294
303 } // namespace content 295 } // namespace content
304 296
305 #endif // CONTENT_BROWSER_GEOLOCATION_DEVICE_DATA_PROVIDER_H_ 297 #endif // CONTENT_BROWSER_GEOLOCATION_DEVICE_DATA_PROVIDER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698