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

Unified Diff: content/browser/device_orientation/provider_impl.cc

Issue 10755002: Refactors DeviceOrientation to make it more extensible (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Moves construction of DeviceData objects out of ProviderImpl Created 8 years, 5 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 side-by-side diff with in-line comments
Download patch
Index: content/browser/device_orientation/provider_impl.cc
diff --git a/content/browser/device_orientation/provider_impl.cc b/content/browser/device_orientation/provider_impl.cc
index fab78a11a42733926495eaa1902bc52d879a21bb..9f12832ea980be2fa33ad0ac98e014fd71b1d185 100644
--- a/content/browser/device_orientation/provider_impl.cc
+++ b/content/browser/device_orientation/provider_impl.cc
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <cmath>
#include <set>
#include <vector>
@@ -29,11 +28,24 @@ ProviderImpl::~ProviderImpl() {
void ProviderImpl::AddObserver(Observer* observer) {
DCHECK(MessageLoop::current() == creator_loop_);
+ DeviceData::DeviceDataType device_data_type = observer->device_data_type();
+
observers_.insert(observer);
if (observers_.size() == 1)
Start();
- else
- observer->OnOrientationUpdate(last_notification_);
+
+ ScheduleDoAddObserverType(device_data_type);
+
+ if (!data_fetcher_.get()) {
+ ScheduleInitializePollingThread(device_data_type);
+ return;
+ }
+
+ // Notify observer of most recent notification if one exists.
+ DeviceData* last_notification = last_notifications_map_.Lookup(
+ device_data_type);
+ if (last_notification)
+ observer->OnDeviceDataUpdate(last_notification);
}
void ProviderImpl::RemoveObserver(Observer* observer) {
@@ -48,13 +60,16 @@ void ProviderImpl::Start() {
DCHECK(MessageLoop::current() == creator_loop_);
DCHECK(!polling_thread_.get());
- polling_thread_.reset(new base::Thread("Device orientation polling thread"));
+ // Reset members used on polling thread.
+ last_device_data_map_.reset(new IDMap<DeviceData, IDMapOwnPointer>);
+ observer_types_.clear();
+
+ polling_thread_.reset(new base::Thread("Device data polling thread"));
if (!polling_thread_->Start()) {
- LOG(ERROR) << "Failed to start device orientation polling thread";
+ LOG(ERROR) << "Failed to start device data polling thread";
polling_thread_.reset();
return;
}
- ScheduleInitializePollingThread();
}
void ProviderImpl::Stop() {
@@ -67,24 +82,46 @@ void ProviderImpl::Stop() {
data_fetcher_.reset();
}
+void ProviderImpl::DoAddObserverType(
+ DeviceData::DeviceDataType device_data_type) {
+ DCHECK(MessageLoop::current() == polling_thread_->message_loop());
+
+ observer_types_.insert(device_data_type);
+}
+
+void ProviderImpl::ScheduleDoAddObserverType(
+ DeviceData::DeviceDataType device_data_type) {
+ DCHECK(MessageLoop::current() == creator_loop_);
+
+ MessageLoop* polling_loop = polling_thread_->message_loop();
+ polling_loop->PostTask(FROM_HERE,
+ base::Bind(&ProviderImpl::DoAddObserverType,
+ this,
+ device_data_type));
+}
+
void ProviderImpl::DoInitializePollingThread(
- const std::vector<DataFetcherFactory>& factories) {
+ const std::vector<DataFetcherFactory>& factories,
+ DeviceData::DeviceDataType device_data_type) {
DCHECK(MessageLoop::current() == polling_thread_->message_loop());
typedef std::vector<DataFetcherFactory>::const_iterator Iterator;
for (Iterator i = factories_.begin(), e = factories_.end(); i != e; ++i) {
DataFetcherFactory factory = *i;
scoped_ptr<DataFetcher> fetcher(factory());
- Orientation orientation;
- if (fetcher.get() && fetcher->GetOrientation(&orientation)) {
+ if (!fetcher.get())
+ continue;
+
+ scoped_ptr<DeviceData> device_data(fetcher->GetDeviceData(
+ device_data_type));
+ if (device_data != NULL) {
// Pass ownership of fetcher to provider_.
data_fetcher_.swap(fetcher);
- last_orientation_ = orientation;
+ last_device_data_map_->AddWithID(device_data->Clone(), device_data_type);
// Notify observers.
- if (!orientation.is_empty())
- ScheduleDoNotify(orientation);
+ ScheduleDoNotify(device_data.release(), device_data_type);
// Start polling.
ScheduleDoPoll();
@@ -92,58 +129,97 @@ void ProviderImpl::DoInitializePollingThread(
}
}
- // When no orientation data can be provided.
- ScheduleDoNotify(Orientation::Empty());
+ // When no device data can be provided.
+ ScheduleDoNotify(NULL, device_data_type);
}
-void ProviderImpl::ScheduleInitializePollingThread() {
+void ProviderImpl::ScheduleInitializePollingThread(
+ DeviceData::DeviceDataType device_data_type) {
DCHECK(MessageLoop::current() == creator_loop_);
MessageLoop* polling_loop = polling_thread_->message_loop();
polling_loop->PostTask(FROM_HERE,
base::Bind(&ProviderImpl::DoInitializePollingThread,
this,
- factories_));
+ factories_,
+ device_data_type));
}
-void ProviderImpl::DoNotify(const Orientation& orientation) {
+void ProviderImpl::DoNotify(const DeviceData* device_data,
+ DeviceData::DeviceDataType device_data_type) {
DCHECK(MessageLoop::current() == creator_loop_);
- last_notification_ = orientation;
+ scoped_ptr<const DeviceData> data(device_data);
+
+ // Update last notification of this type.
+ DeviceData* last_notification = last_notifications_map_.Lookup(
+ device_data_type);
+ if (last_notification)
+ last_notifications_map_.Remove(device_data_type);
+ if (data != NULL)
+ last_notifications_map_.AddWithID(data->Clone(), device_data_type);
+
+ // Notify observers of this type of the new data.
+ typedef std::set<Observer*>::const_iterator ConstIterator;
+ for (ConstIterator i = observers_.begin(), e = observers_.end();
+ i != e; ++i) {
+ if ((*i)->device_data_type() == device_data_type)
+ (*i)->OnDeviceDataUpdate(data.get());
+ }
- typedef std::set<Observer*>::const_iterator Iterator;
- for (Iterator i = observers_.begin(), e = observers_.end(); i != e; ++i)
- (*i)->OnOrientationUpdate(orientation);
+ if (data == NULL) {
+ // Notify observers exactly once about failure to provide data.
+ typedef std::set<Observer*>::iterator Iterator;
+ Iterator i = observers_.begin();
+ while (i != observers_.end()) {
+ Iterator current = i++;
+ if ((*current)->device_data_type() == device_data_type)
+ observers_.erase(current);
+ }
- if (orientation.is_empty()) {
- // Notify observers about failure to provide data exactly once.
- observers_.clear();
- Stop();
+ if (observers_.empty())
+ Stop();
}
}
-void ProviderImpl::ScheduleDoNotify(const Orientation& orientation) {
+void ProviderImpl::ScheduleDoNotify(const DeviceData* device_data,
+ DeviceData::DeviceDataType device_data_type) {
DCHECK(MessageLoop::current() == polling_thread_->message_loop());
- creator_loop_->PostTask(
- FROM_HERE, base::Bind(&ProviderImpl::DoNotify, this, orientation));
+ creator_loop_->PostTask(FROM_HERE,
+ base::Bind(&ProviderImpl::DoNotify, this,
+ device_data, device_data_type));
}
void ProviderImpl::DoPoll() {
DCHECK(MessageLoop::current() == polling_thread_->message_loop());
- Orientation orientation;
- if (!data_fetcher_->GetOrientation(&orientation)) {
- LOG(ERROR) << "Failed to poll device orientation data fetcher.";
-
- ScheduleDoNotify(Orientation::Empty());
- return;
- }
+ // Poll the fetcher for each type of data
+ typedef std::set<DeviceData::DeviceDataType>::const_iterator SetIterator;
+ for (SetIterator i = observer_types_.begin(), e = observer_types_.end();
+ i != e; ++i) {
+ DeviceData::DeviceDataType device_data_type = *i;
+ scoped_ptr<DeviceData> device_data(data_fetcher_->GetDeviceData(
+ device_data_type));
+
+ if (device_data == NULL) {
+ LOG(ERROR) << "Failed to poll device data fetcher.";
+ ScheduleDoNotify(NULL, device_data_type);
+ return;
bulach 2012/07/12 10:43:27 hmm, I think now that we're traversing all the dif
aousterh 2012/07/12 17:13:57 Good point. Done.
+ }
- if (!orientation.is_empty() &&
- SignificantlyDifferent(orientation, last_orientation_)) {
- last_orientation_ = orientation;
- ScheduleDoNotify(orientation);
+ // Update the last device data of this type and notify observers
+ DeviceData* last_device_data = last_device_data_map_->Lookup(
+ device_data_type);
+ if (!last_device_data) {
+ last_device_data_map_->AddWithID(device_data->Clone(), device_data_type);
+ ScheduleDoNotify(device_data.release(), device_data_type);
+ }
+ else if (device_data->SignificantlyDifferentFrom(*last_device_data)) {
bulach 2012/07/12 10:43:27 nit: else on the line above with }
aousterh 2012/07/12 17:13:57 Done.
+ last_device_data_map_->Remove(device_data_type);
+ last_device_data_map_->AddWithID(device_data->Clone(), device_data_type);
+ ScheduleDoNotify(device_data.release(), device_data_type);
+ }
}
ScheduleDoPoll();
@@ -159,43 +235,6 @@ void ProviderImpl::ScheduleDoPoll() {
SamplingInterval());
}
-namespace {
-
-bool IsElementSignificantlyDifferent(bool can_provide_element1,
- bool can_provide_element2,
- double element1,
- double element2) {
- const double kThreshold = 0.1;
-
- if (can_provide_element1 != can_provide_element2)
- return true;
- if (can_provide_element1 &&
- std::fabs(element1 - element2) >= kThreshold)
- return true;
- return false;
-}
-} // namespace
-
-// Returns true if two orientations are considered different enough that
-// observers should be notified of the new orientation.
-bool ProviderImpl::SignificantlyDifferent(const Orientation& o1,
- const Orientation& o2) {
- return IsElementSignificantlyDifferent(o1.can_provide_alpha(),
- o2.can_provide_alpha(),
- o1.alpha(),
- o2.alpha()) ||
- IsElementSignificantlyDifferent(o1.can_provide_beta(),
- o2.can_provide_beta(),
- o1.beta(),
- o2.beta()) ||
- IsElementSignificantlyDifferent(o1.can_provide_gamma(),
- o2.can_provide_gamma(),
- o1.gamma(),
- o2.gamma()) ||
- (o1.can_provide_absolute() != o2.can_provide_absolute() ||
- o1.absolute() != o2.absolute());
-}
-
base::TimeDelta ProviderImpl::SamplingInterval() const {
DCHECK(MessageLoop::current() == polling_thread_->message_loop());
DCHECK(data_fetcher_.get());

Powered by Google App Engine
This is Rietveld 408576698