OLD | NEW |
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 #include "content/browser/device_orientation/provider_impl.h" | 5 #include "content/browser/device_orientation/provider_impl.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
13 #include "base/threading/thread.h" | 13 #include "base/threading/thread.h" |
14 #include "base/threading/worker_pool.h" | 14 #include "base/threading/worker_pool.h" |
15 | 15 |
16 namespace { | 16 namespace { |
17 | 17 |
18 void DeleteThread(base::Thread* thread) { | 18 void DeleteThread(base::Thread* thread) { |
19 delete thread; | 19 delete thread; |
20 } | 20 } |
21 | 21 |
22 } | 22 } |
23 | 23 |
24 namespace content { | 24 namespace content { |
25 | 25 |
26 class ProviderImpl::PollingThread : public base::Thread { | 26 class ProviderImpl::PollingThread : public base::Thread { |
27 public: | 27 public: |
28 PollingThread(const char* name, | 28 PollingThread(const char* name, |
29 base::WeakPtr<ProviderImpl> provider, | 29 base::WeakPtr<ProviderImpl> provider, |
30 MessageLoop* creator_loop); | 30 base::MessageLoop* creator_loop); |
31 virtual ~PollingThread(); | 31 virtual ~PollingThread(); |
32 | 32 |
33 // Method for creating a DataFetcher and starting the polling, if the fetcher | 33 // Method for creating a DataFetcher and starting the polling, if the fetcher |
34 // can provide this type of data. | 34 // can provide this type of data. |
35 void Initialize(DataFetcherFactory factory, DeviceData::Type type); | 35 void Initialize(DataFetcherFactory factory, DeviceData::Type type); |
36 | 36 |
37 // Method for adding a type of data to poll for. | 37 // Method for adding a type of data to poll for. |
38 void DoAddPollingDataType(DeviceData::Type type); | 38 void DoAddPollingDataType(DeviceData::Type type); |
39 | 39 |
40 private: | 40 private: |
41 // Method for polling a DataFetcher. | 41 // Method for polling a DataFetcher. |
42 void DoPoll(); | 42 void DoPoll(); |
43 void ScheduleDoPoll(); | 43 void ScheduleDoPoll(); |
44 | 44 |
45 // Schedule a notification to the |provider_| which lives on a different | 45 // Schedule a notification to the |provider_| which lives on a different |
46 // thread (|creator_loop_| is its message loop). | 46 // thread (|creator_loop_| is its message loop). |
47 void ScheduleDoNotify(const scoped_refptr<const DeviceData>& device_data, | 47 void ScheduleDoNotify(const scoped_refptr<const DeviceData>& device_data, |
48 DeviceData::Type device_data_type); | 48 DeviceData::Type device_data_type); |
49 | 49 |
50 enum { kDesiredSamplingIntervalMs = 100 }; | 50 enum { kDesiredSamplingIntervalMs = 100 }; |
51 base::TimeDelta SamplingInterval() const; | 51 base::TimeDelta SamplingInterval() const; |
52 | 52 |
53 // The Message Loop on which this object was created. | 53 // The Message Loop on which this object was created. |
54 // Typically the I/O loop, but may be something else during testing. | 54 // Typically the I/O loop, but may be something else during testing. |
55 MessageLoop* creator_loop_; | 55 base::MessageLoop* creator_loop_; |
56 | 56 |
57 scoped_ptr<DataFetcher> data_fetcher_; | 57 scoped_ptr<DataFetcher> data_fetcher_; |
58 std::map<DeviceData::Type, scoped_refptr<const DeviceData> > | 58 std::map<DeviceData::Type, scoped_refptr<const DeviceData> > |
59 last_device_data_map_; | 59 last_device_data_map_; |
60 std::set<DeviceData::Type> polling_data_types_; | 60 std::set<DeviceData::Type> polling_data_types_; |
61 | 61 |
62 base::WeakPtr<ProviderImpl> provider_; | 62 base::WeakPtr<ProviderImpl> provider_; |
63 }; | 63 }; |
64 | 64 |
65 ProviderImpl::PollingThread::PollingThread( | 65 ProviderImpl::PollingThread::PollingThread(const char* name, |
66 const char* name, | 66 base::WeakPtr<ProviderImpl> provider, |
67 base::WeakPtr<ProviderImpl> provider, | 67 base::MessageLoop* creator_loop) |
68 MessageLoop* creator_loop) | 68 : base::Thread(name), creator_loop_(creator_loop), provider_(provider) {} |
69 : base::Thread(name), | |
70 creator_loop_(creator_loop), | |
71 provider_(provider) { | |
72 } | |
73 | 69 |
74 ProviderImpl::PollingThread::~PollingThread() { | 70 ProviderImpl::PollingThread::~PollingThread() { |
75 Stop(); | 71 Stop(); |
76 } | 72 } |
77 | 73 |
78 void ProviderImpl::PollingThread::DoAddPollingDataType(DeviceData::Type type) { | 74 void ProviderImpl::PollingThread::DoAddPollingDataType(DeviceData::Type type) { |
79 DCHECK(MessageLoop::current() == message_loop()); | 75 DCHECK(base::MessageLoop::current() == message_loop()); |
80 | 76 |
81 polling_data_types_.insert(type); | 77 polling_data_types_.insert(type); |
82 } | 78 } |
83 | 79 |
84 void ProviderImpl::PollingThread::Initialize(DataFetcherFactory factory, | 80 void ProviderImpl::PollingThread::Initialize(DataFetcherFactory factory, |
85 DeviceData::Type type) { | 81 DeviceData::Type type) { |
86 DCHECK(MessageLoop::current() == message_loop()); | 82 DCHECK(base::MessageLoop::current() == message_loop()); |
87 | 83 |
88 if (factory != NULL) { | 84 if (factory != NULL) { |
89 // Try to use factory to create a fetcher that can provide this type of | 85 // Try to use factory to create a fetcher that can provide this type of |
90 // data. If factory creates a fetcher that provides this type of data, | 86 // data. If factory creates a fetcher that provides this type of data, |
91 // start polling. | 87 // start polling. |
92 scoped_ptr<DataFetcher> fetcher(factory()); | 88 scoped_ptr<DataFetcher> fetcher(factory()); |
93 | 89 |
94 if (fetcher) { | 90 if (fetcher) { |
95 scoped_refptr<const DeviceData> device_data(fetcher->GetDeviceData(type)); | 91 scoped_refptr<const DeviceData> device_data(fetcher->GetDeviceData(type)); |
96 if (device_data != NULL) { | 92 if (device_data != NULL) { |
(...skipping 11 matching lines...) Expand all Loading... |
108 } | 104 } |
109 } | 105 } |
110 | 106 |
111 // When no device data can be provided. | 107 // When no device data can be provided. |
112 ScheduleDoNotify(NULL, type); | 108 ScheduleDoNotify(NULL, type); |
113 } | 109 } |
114 | 110 |
115 void ProviderImpl::PollingThread::ScheduleDoNotify( | 111 void ProviderImpl::PollingThread::ScheduleDoNotify( |
116 const scoped_refptr<const DeviceData>& device_data, | 112 const scoped_refptr<const DeviceData>& device_data, |
117 DeviceData::Type device_data_type) { | 113 DeviceData::Type device_data_type) { |
118 DCHECK(MessageLoop::current() == message_loop()); | 114 DCHECK(base::MessageLoop::current() == message_loop()); |
119 | 115 |
120 creator_loop_->PostTask(FROM_HERE, | 116 creator_loop_->PostTask(FROM_HERE, |
121 base::Bind(&ProviderImpl::DoNotify, provider_, | 117 base::Bind(&ProviderImpl::DoNotify, provider_, |
122 device_data, device_data_type)); | 118 device_data, device_data_type)); |
123 } | 119 } |
124 | 120 |
125 void ProviderImpl::PollingThread::DoPoll() { | 121 void ProviderImpl::PollingThread::DoPoll() { |
126 DCHECK(MessageLoop::current() == message_loop()); | 122 DCHECK(base::MessageLoop::current() == message_loop()); |
127 | 123 |
128 // Poll the fetcher for each type of data. | 124 // Poll the fetcher for each type of data. |
129 typedef std::set<DeviceData::Type>::const_iterator SetIterator; | 125 typedef std::set<DeviceData::Type>::const_iterator SetIterator; |
130 for (SetIterator i = polling_data_types_.begin(); | 126 for (SetIterator i = polling_data_types_.begin(); |
131 i != polling_data_types_.end(); ++i) { | 127 i != polling_data_types_.end(); ++i) { |
132 DeviceData::Type device_data_type = *i; | 128 DeviceData::Type device_data_type = *i; |
133 scoped_refptr<const DeviceData> device_data(data_fetcher_->GetDeviceData( | 129 scoped_refptr<const DeviceData> device_data(data_fetcher_->GetDeviceData( |
134 device_data_type)); | 130 device_data_type)); |
135 | 131 |
136 if (device_data == NULL) { | 132 if (device_data == NULL) { |
137 LOG(ERROR) << "Failed to poll device data fetcher."; | 133 LOG(ERROR) << "Failed to poll device data fetcher."; |
138 ScheduleDoNotify(NULL, device_data_type); | 134 ScheduleDoNotify(NULL, device_data_type); |
139 continue; | 135 continue; |
140 } | 136 } |
141 | 137 |
142 const DeviceData* old_data = last_device_data_map_[device_data_type]; | 138 const DeviceData* old_data = last_device_data_map_[device_data_type]; |
143 if (old_data != NULL && !device_data->ShouldFireEvent(old_data)) | 139 if (old_data != NULL && !device_data->ShouldFireEvent(old_data)) |
144 continue; | 140 continue; |
145 | 141 |
146 // Update the last device data of this type and notify observers. | 142 // Update the last device data of this type and notify observers. |
147 last_device_data_map_[device_data_type] = device_data; | 143 last_device_data_map_[device_data_type] = device_data; |
148 ScheduleDoNotify(device_data, device_data_type); | 144 ScheduleDoNotify(device_data, device_data_type); |
149 } | 145 } |
150 | 146 |
151 ScheduleDoPoll(); | 147 ScheduleDoPoll(); |
152 } | 148 } |
153 | 149 |
154 void ProviderImpl::PollingThread::ScheduleDoPoll() { | 150 void ProviderImpl::PollingThread::ScheduleDoPoll() { |
155 DCHECK(MessageLoop::current() == message_loop()); | 151 DCHECK(base::MessageLoop::current() == message_loop()); |
156 | 152 |
157 message_loop()->PostDelayedTask( | 153 message_loop()->PostDelayedTask( |
158 FROM_HERE, | 154 FROM_HERE, |
159 base::Bind(&PollingThread::DoPoll, base::Unretained(this)), | 155 base::Bind(&PollingThread::DoPoll, base::Unretained(this)), |
160 SamplingInterval()); | 156 SamplingInterval()); |
161 } | 157 } |
162 | 158 |
163 base::TimeDelta ProviderImpl::PollingThread::SamplingInterval() const { | 159 base::TimeDelta ProviderImpl::PollingThread::SamplingInterval() const { |
164 DCHECK(MessageLoop::current() == message_loop()); | 160 DCHECK(base::MessageLoop::current() == message_loop()); |
165 DCHECK(data_fetcher_.get()); | 161 DCHECK(data_fetcher_.get()); |
166 | 162 |
167 // TODO(erg): There used to be unused code here, that called a default | 163 // TODO(erg): There used to be unused code here, that called a default |
168 // implementation on the DataFetcherInterface that was never defined. I'm | 164 // implementation on the DataFetcherInterface that was never defined. I'm |
169 // removing unused methods from headers. | 165 // removing unused methods from headers. |
170 return base::TimeDelta::FromMilliseconds(kDesiredSamplingIntervalMs); | 166 return base::TimeDelta::FromMilliseconds(kDesiredSamplingIntervalMs); |
171 } | 167 } |
172 | 168 |
173 ProviderImpl::ProviderImpl(DataFetcherFactory factory) | 169 ProviderImpl::ProviderImpl(DataFetcherFactory factory) |
174 : creator_loop_(MessageLoop::current()), | 170 : creator_loop_(base::MessageLoop::current()), |
175 factory_(factory), | 171 factory_(factory), |
176 weak_factory_(this), | 172 weak_factory_(this), |
177 polling_thread_(NULL) { | 173 polling_thread_(NULL) { |
178 } | 174 } |
179 | 175 |
180 ProviderImpl::~ProviderImpl() { | 176 ProviderImpl::~ProviderImpl() { |
181 Stop(); | 177 Stop(); |
182 } | 178 } |
183 | 179 |
184 void ProviderImpl::ScheduleDoAddPollingDataType(DeviceData::Type type) { | 180 void ProviderImpl::ScheduleDoAddPollingDataType(DeviceData::Type type) { |
185 DCHECK(MessageLoop::current() == creator_loop_); | 181 DCHECK(base::MessageLoop::current() == creator_loop_); |
186 | 182 |
187 MessageLoop* polling_loop = polling_thread_->message_loop(); | 183 base::MessageLoop* polling_loop = polling_thread_->message_loop(); |
188 polling_loop->PostTask(FROM_HERE, | 184 polling_loop->PostTask(FROM_HERE, |
189 base::Bind(&PollingThread::DoAddPollingDataType, | 185 base::Bind(&PollingThread::DoAddPollingDataType, |
190 base::Unretained(polling_thread_), | 186 base::Unretained(polling_thread_), |
191 type)); | 187 type)); |
192 } | 188 } |
193 | 189 |
194 void ProviderImpl::AddObserver(Observer* observer) { | 190 void ProviderImpl::AddObserver(Observer* observer) { |
195 DCHECK(MessageLoop::current() == creator_loop_); | 191 DCHECK(base::MessageLoop::current() == creator_loop_); |
196 | 192 |
197 DeviceData::Type type = observer->device_data_type(); | 193 DeviceData::Type type = observer->device_data_type(); |
198 | 194 |
199 observers_.insert(observer); | 195 observers_.insert(observer); |
200 if (observers_.size() == 1) | 196 if (observers_.size() == 1) |
201 Start(type); | 197 Start(type); |
202 else { | 198 else { |
203 // Notify observer of most recent notification if one exists. | 199 // Notify observer of most recent notification if one exists. |
204 const DeviceData *last_notification = last_notifications_map_[type]; | 200 const DeviceData *last_notification = last_notifications_map_[type]; |
205 if (last_notification != NULL) | 201 if (last_notification != NULL) |
206 observer->OnDeviceDataUpdate(last_notification, type); | 202 observer->OnDeviceDataUpdate(last_notification, type); |
207 } | 203 } |
208 | 204 |
209 ScheduleDoAddPollingDataType(type); | 205 ScheduleDoAddPollingDataType(type); |
210 } | 206 } |
211 | 207 |
212 void ProviderImpl::RemoveObserver(Observer* observer) { | 208 void ProviderImpl::RemoveObserver(Observer* observer) { |
213 DCHECK(MessageLoop::current() == creator_loop_); | 209 DCHECK(base::MessageLoop::current() == creator_loop_); |
214 | 210 |
215 observers_.erase(observer); | 211 observers_.erase(observer); |
216 if (observers_.empty()) | 212 if (observers_.empty()) |
217 Stop(); | 213 Stop(); |
218 } | 214 } |
219 | 215 |
220 void ProviderImpl::Start(DeviceData::Type type) { | 216 void ProviderImpl::Start(DeviceData::Type type) { |
221 DCHECK(MessageLoop::current() == creator_loop_); | 217 DCHECK(base::MessageLoop::current() == creator_loop_); |
222 DCHECK(!polling_thread_); | 218 DCHECK(!polling_thread_); |
223 | 219 |
224 polling_thread_ = new PollingThread("Device data polling thread", | 220 polling_thread_ = new PollingThread("Device data polling thread", |
225 weak_factory_.GetWeakPtr(), | 221 weak_factory_.GetWeakPtr(), |
226 creator_loop_); | 222 creator_loop_); |
227 #if defined(OS_WIN) | 223 #if defined(OS_WIN) |
228 polling_thread_->init_com_with_mta(true); | 224 polling_thread_->init_com_with_mta(true); |
229 #endif | 225 #endif |
230 if (!polling_thread_->Start()) { | 226 if (!polling_thread_->Start()) { |
231 LOG(ERROR) << "Failed to start device data polling thread"; | 227 LOG(ERROR) << "Failed to start device data polling thread"; |
232 delete polling_thread_; | 228 delete polling_thread_; |
233 polling_thread_ = NULL; | 229 polling_thread_ = NULL; |
234 return; | 230 return; |
235 } | 231 } |
236 ScheduleInitializePollingThread(type); | 232 ScheduleInitializePollingThread(type); |
237 } | 233 } |
238 | 234 |
239 void ProviderImpl::Stop() { | 235 void ProviderImpl::Stop() { |
240 DCHECK(MessageLoop::current() == creator_loop_); | 236 DCHECK(base::MessageLoop::current() == creator_loop_); |
241 | 237 |
242 weak_factory_.InvalidateWeakPtrs(); | 238 weak_factory_.InvalidateWeakPtrs(); |
243 if (polling_thread_) { | 239 if (polling_thread_) { |
244 polling_thread_->StopSoon(); | 240 polling_thread_->StopSoon(); |
245 bool posted = base::WorkerPool::PostTask( | 241 bool posted = base::WorkerPool::PostTask( |
246 FROM_HERE, | 242 FROM_HERE, |
247 base::Bind(&DeleteThread, base::Unretained(polling_thread_)), | 243 base::Bind(&DeleteThread, base::Unretained(polling_thread_)), |
248 true /* task is slow */); | 244 true /* task is slow */); |
249 DCHECK(posted); | 245 DCHECK(posted); |
250 polling_thread_ = NULL; | 246 polling_thread_ = NULL; |
251 } | 247 } |
252 } | 248 } |
253 | 249 |
254 void ProviderImpl::ScheduleInitializePollingThread( | 250 void ProviderImpl::ScheduleInitializePollingThread( |
255 DeviceData::Type device_data_type) { | 251 DeviceData::Type device_data_type) { |
256 DCHECK(MessageLoop::current() == creator_loop_); | 252 DCHECK(base::MessageLoop::current() == creator_loop_); |
257 | 253 |
258 MessageLoop* polling_loop = polling_thread_->message_loop(); | 254 base::MessageLoop* polling_loop = polling_thread_->message_loop(); |
259 polling_loop->PostTask(FROM_HERE, | 255 polling_loop->PostTask(FROM_HERE, |
260 base::Bind(&PollingThread::Initialize, | 256 base::Bind(&PollingThread::Initialize, |
261 base::Unretained(polling_thread_), | 257 base::Unretained(polling_thread_), |
262 factory_, | 258 factory_, |
263 device_data_type)); | 259 device_data_type)); |
264 } | 260 } |
265 | 261 |
266 void ProviderImpl::DoNotify(const scoped_refptr<const DeviceData>& data, | 262 void ProviderImpl::DoNotify(const scoped_refptr<const DeviceData>& data, |
267 DeviceData::Type device_data_type) { | 263 DeviceData::Type device_data_type) { |
268 DCHECK(MessageLoop::current() == creator_loop_); | 264 DCHECK(base::MessageLoop::current() == creator_loop_); |
269 | 265 |
270 // Update last notification of this type. | 266 // Update last notification of this type. |
271 last_notifications_map_[device_data_type] = data; | 267 last_notifications_map_[device_data_type] = data; |
272 | 268 |
273 // Notify observers of this type of the new data. | 269 // Notify observers of this type of the new data. |
274 typedef std::set<Observer*>::const_iterator ConstIterator; | 270 typedef std::set<Observer*>::const_iterator ConstIterator; |
275 for (ConstIterator i = observers_.begin(); i != observers_.end(); ++i) { | 271 for (ConstIterator i = observers_.begin(); i != observers_.end(); ++i) { |
276 if ((*i)->device_data_type() == device_data_type) | 272 if ((*i)->device_data_type() == device_data_type) |
277 (*i)->OnDeviceDataUpdate(data.get(), device_data_type); | 273 (*i)->OnDeviceDataUpdate(data.get(), device_data_type); |
278 } | 274 } |
279 | 275 |
280 if (data == NULL) { | 276 if (data == NULL) { |
281 // Notify observers exactly once about failure to provide data. | 277 // Notify observers exactly once about failure to provide data. |
282 typedef std::set<Observer*>::iterator Iterator; | 278 typedef std::set<Observer*>::iterator Iterator; |
283 Iterator i = observers_.begin(); | 279 Iterator i = observers_.begin(); |
284 while (i != observers_.end()) { | 280 while (i != observers_.end()) { |
285 Iterator current = i++; | 281 Iterator current = i++; |
286 if ((*current)->device_data_type() == device_data_type) | 282 if ((*current)->device_data_type() == device_data_type) |
287 observers_.erase(current); | 283 observers_.erase(current); |
288 } | 284 } |
289 | 285 |
290 if (observers_.empty()) | 286 if (observers_.empty()) |
291 Stop(); | 287 Stop(); |
292 } | 288 } |
293 } | 289 } |
294 | 290 |
295 | 291 |
296 } // namespace content | 292 } // namespace content |
OLD | NEW |