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

Side by Side Diff: chrome/browser/device_orientation/provider_impl.cc

Issue 6586001: Move appcache/file_sytem/device_orientation subdirectories of chrome\browser ... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: sync Created 9 years, 10 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2010 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.
4
5 #include <cmath>
6 #include <set>
7 #include <vector>
8
9 #include "base/logging.h"
10 #include "base/message_loop.h"
11 #include "base/task.h"
12 #include "base/threading/thread.h"
13 #include "base/threading/thread_restrictions.h"
14 #include "chrome/browser/device_orientation/orientation.h"
15 #include "chrome/browser/device_orientation/provider_impl.h"
16
17 namespace device_orientation {
18
19 ProviderImpl::ProviderImpl(const DataFetcherFactory factories[])
20 : creator_loop_(MessageLoop::current()),
21 ALLOW_THIS_IN_INITIALIZER_LIST(do_poll_method_factory_(this)) {
22 for (const DataFetcherFactory* fp = factories; *fp; ++fp)
23 factories_.push_back(*fp);
24 }
25
26 ProviderImpl::~ProviderImpl() {
27 }
28
29 void ProviderImpl::AddObserver(Observer* observer) {
30 DCHECK(MessageLoop::current() == creator_loop_);
31
32 observers_.insert(observer);
33 if (observers_.size() == 1)
34 Start();
35 else
36 observer->OnOrientationUpdate(last_notification_);
37 }
38
39 void ProviderImpl::RemoveObserver(Observer* observer) {
40 DCHECK(MessageLoop::current() == creator_loop_);
41
42 observers_.erase(observer);
43 if (observers_.empty())
44 Stop();
45 }
46
47 void ProviderImpl::Start() {
48 DCHECK(MessageLoop::current() == creator_loop_);
49 DCHECK(!polling_thread_.get());
50
51 polling_thread_.reset(new base::Thread("Device orientation polling thread"));
52 if (!polling_thread_->Start()) {
53 LOG(ERROR) << "Failed to start device orientation polling thread";
54 polling_thread_.reset();
55 return;
56 }
57 ScheduleInitializePollingThread();
58 }
59
60 void ProviderImpl::Stop() {
61 DCHECK(MessageLoop::current() == creator_loop_);
62
63 // TODO(hans): Don't join the thread. See crbug.com/72286.
64 base::ThreadRestrictions::ScopedAllowIO allow_io;
65
66 polling_thread_.reset();
67 data_fetcher_.reset();
68 }
69
70 void ProviderImpl::DoInitializePollingThread(
71 std::vector<DataFetcherFactory> factories) {
72 DCHECK(MessageLoop::current() == polling_thread_->message_loop());
73
74 typedef std::vector<DataFetcherFactory>::const_iterator Iterator;
75 for (Iterator i = factories_.begin(), e = factories_.end(); i != e; ++i) {
76 DataFetcherFactory factory = *i;
77 scoped_ptr<DataFetcher> fetcher(factory());
78 Orientation orientation;
79
80 if (fetcher.get() && fetcher->GetOrientation(&orientation)) {
81 // Pass ownership of fetcher to provider_.
82 data_fetcher_.swap(fetcher);
83 last_orientation_ = orientation;
84
85 // Notify observers.
86 ScheduleDoNotify(orientation);
87
88 // Start polling.
89 ScheduleDoPoll();
90 return;
91 }
92 }
93
94 // When no orientation data can be provided.
95 ScheduleDoNotify(Orientation::Empty());
96 }
97
98 void ProviderImpl::ScheduleInitializePollingThread() {
99 DCHECK(MessageLoop::current() == creator_loop_);
100
101 Task* task = NewRunnableMethod(this,
102 &ProviderImpl::DoInitializePollingThread,
103 factories_);
104 MessageLoop* polling_loop = polling_thread_->message_loop();
105 polling_loop->PostTask(FROM_HERE, task);
106 }
107
108 void ProviderImpl::DoNotify(const Orientation& orientation) {
109 DCHECK(MessageLoop::current() == creator_loop_);
110
111 last_notification_ = orientation;
112
113 typedef std::set<Observer*>::const_iterator Iterator;
114 for (Iterator i = observers_.begin(), e = observers_.end(); i != e; ++i)
115 (*i)->OnOrientationUpdate(orientation);
116
117 if (orientation.IsEmpty()) {
118 // Notify observers about failure to provide data exactly once.
119 observers_.clear();
120 Stop();
121 }
122 }
123
124 void ProviderImpl::ScheduleDoNotify(const Orientation& orientation) {
125 DCHECK(MessageLoop::current() == polling_thread_->message_loop());
126
127 Task* task = NewRunnableMethod(this, &ProviderImpl::DoNotify, orientation);
128 creator_loop_->PostTask(FROM_HERE, task);
129 }
130
131 void ProviderImpl::DoPoll() {
132 DCHECK(MessageLoop::current() == polling_thread_->message_loop());
133
134 Orientation orientation;
135 if (!data_fetcher_->GetOrientation(&orientation)) {
136 LOG(ERROR) << "Failed to poll device orientation data fetcher.";
137
138 ScheduleDoNotify(Orientation::Empty());
139 return;
140 }
141
142 if (SignificantlyDifferent(orientation, last_orientation_)) {
143 last_orientation_ = orientation;
144 ScheduleDoNotify(orientation);
145 }
146
147 ScheduleDoPoll();
148 }
149
150 void ProviderImpl::ScheduleDoPoll() {
151 DCHECK(MessageLoop::current() == polling_thread_->message_loop());
152
153 Task* task = do_poll_method_factory_.NewRunnableMethod(&ProviderImpl::DoPoll);
154 MessageLoop* polling_loop = polling_thread_->message_loop();
155 polling_loop->PostDelayedTask(FROM_HERE, task, SamplingIntervalMs());
156 }
157
158 namespace {
159
160 bool IsElementSignificantlyDifferent(bool can_provide_element1,
161 bool can_provide_element2,
162 double element1,
163 double element2) {
164 const double kThreshold = 0.1;
165
166 if (can_provide_element1 != can_provide_element2)
167 return true;
168 if (can_provide_element1 &&
169 std::fabs(element1 - element2) >= kThreshold)
170 return true;
171 return false;
172 }
173 } // namespace
174
175 // Returns true if two orientations are considered different enough that
176 // observers should be notified of the new orientation.
177 bool ProviderImpl::SignificantlyDifferent(const Orientation& o1,
178 const Orientation& o2) {
179 return IsElementSignificantlyDifferent(o1.can_provide_alpha_,
180 o2.can_provide_alpha_,
181 o1.alpha_,
182 o2.alpha_) ||
183 IsElementSignificantlyDifferent(o1.can_provide_beta_,
184 o2.can_provide_beta_,
185 o1.beta_,
186 o2.beta_) ||
187 IsElementSignificantlyDifferent(o1.can_provide_gamma_,
188 o2.can_provide_gamma_,
189 o1.gamma_,
190 o2.gamma_);
191 }
192
193 int ProviderImpl::SamplingIntervalMs() const {
194 DCHECK(MessageLoop::current() == polling_thread_->message_loop());
195 DCHECK(data_fetcher_.get());
196
197 // TODO(erg): There used to be unused code here, that called a default
198 // implementation on the DataFetcherInterface that was never defined. I'm
199 // removing unused methods from headers.
200 return kDesiredSamplingIntervalMs;
201 }
202
203 } // namespace device_orientation
OLDNEW
« no previous file with comments | « chrome/browser/device_orientation/provider_impl.h ('k') | chrome/browser/device_orientation/provider_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698