summaryrefslogtreecommitdiff
path: root/chromium/content/browser/device_orientation/device_motion_provider.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/content/browser/device_orientation/device_motion_provider.cc')
-rw-r--r--chromium/content/browser/device_orientation/device_motion_provider.cc172
1 files changed, 172 insertions, 0 deletions
diff --git a/chromium/content/browser/device_orientation/device_motion_provider.cc b/chromium/content/browser/device_orientation/device_motion_provider.cc
new file mode 100644
index 00000000000..e88d5af83f4
--- /dev/null
+++ b/chromium/content/browser/device_orientation/device_motion_provider.cc
@@ -0,0 +1,172 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/device_orientation/device_motion_provider.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/threading/thread.h"
+#include "base/timer/timer.h"
+#include "content/browser/device_orientation/data_fetcher_shared_memory.h"
+#include "content/common/device_motion_hardware_buffer.h"
+
+namespace content {
+
+namespace {
+const int kPeriodInMilliseconds = 100;
+}
+
+class DeviceMotionProvider::PollingThread : public base::Thread {
+ public:
+ explicit PollingThread(const char* name);
+ virtual ~PollingThread();
+
+ void StartPolling(DataFetcherSharedMemory* fetcher,
+ DeviceMotionHardwareBuffer* buffer);
+ void StopPolling();
+
+ private:
+ void DoPoll();
+
+ scoped_ptr<base::RepeatingTimer<PollingThread> > timer_;
+ DataFetcherSharedMemory* fetcher_;
+
+ DISALLOW_COPY_AND_ASSIGN(PollingThread);
+};
+
+// ---- PollingThread methods
+
+DeviceMotionProvider::PollingThread::PollingThread(const char* name)
+ : base::Thread(name) {
+}
+
+DeviceMotionProvider::PollingThread::~PollingThread() {
+}
+
+void DeviceMotionProvider::PollingThread::StartPolling(
+ DataFetcherSharedMemory* fetcher, DeviceMotionHardwareBuffer* buffer) {
+ DCHECK(base::MessageLoop::current() == message_loop());
+ DCHECK(!timer_);
+
+ fetcher_ = fetcher;
+ fetcher_->StartFetchingDeviceMotionData(buffer);
+ timer_.reset(new base::RepeatingTimer<PollingThread>());
+ timer_->Start(FROM_HERE,
+ base::TimeDelta::FromMilliseconds(kPeriodInMilliseconds),
+ this, &PollingThread::DoPoll);
+}
+
+void DeviceMotionProvider::PollingThread::StopPolling() {
+ DCHECK(base::MessageLoop::current() == message_loop());
+ DCHECK(fetcher_);
+ // this will also stop the timer before killing it.
+ timer_.reset();
+ fetcher_->StopFetchingDeviceMotionData();
+}
+
+void DeviceMotionProvider::PollingThread::DoPoll() {
+ DCHECK(base::MessageLoop::current() == message_loop());
+ fetcher_->FetchDeviceMotionDataIntoBuffer();
+}
+
+// ---- end PollingThread methods
+
+DeviceMotionProvider::DeviceMotionProvider()
+ : is_started_(false) {
+ Initialize();
+}
+
+DeviceMotionProvider::DeviceMotionProvider(
+ scoped_ptr<DataFetcherSharedMemory> fetcher)
+ : is_started_(false) {
+ data_fetcher_ = fetcher.Pass();
+ Initialize();
+}
+
+DeviceMotionProvider::~DeviceMotionProvider() {
+ StopFetchingDeviceMotionData();
+ // make sure polling thread stops before data_fetcher_ gets deleted.
+ if (polling_thread_)
+ polling_thread_->Stop();
+ data_fetcher_.reset();
+}
+
+void DeviceMotionProvider::Initialize() {
+ size_t data_size = sizeof(DeviceMotionHardwareBuffer);
+ bool res = device_motion_shared_memory_.CreateAndMapAnonymous(data_size);
+ // TODO(timvolodine): consider not crashing the browser if the check fails.
+ CHECK(res);
+ DeviceMotionHardwareBuffer* hwbuf = SharedMemoryAsHardwareBuffer();
+ memset(hwbuf, 0, sizeof(DeviceMotionHardwareBuffer));
+}
+
+base::SharedMemoryHandle DeviceMotionProvider::GetSharedMemoryHandleForProcess(
+ base::ProcessHandle process) {
+ base::SharedMemoryHandle renderer_handle;
+ device_motion_shared_memory_.ShareToProcess(process, &renderer_handle);
+ return renderer_handle;
+}
+
+void DeviceMotionProvider::StartFetchingDeviceMotionData() {
+ if (is_started_)
+ return;
+
+ if (!data_fetcher_)
+ data_fetcher_.reset(new DataFetcherSharedMemory);
+
+ if (data_fetcher_->NeedsPolling()) {
+ if (!polling_thread_)
+ CreateAndStartPollingThread();
+
+ polling_thread_->message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&PollingThread::StartPolling,
+ base::Unretained(polling_thread_.get()),
+ data_fetcher_.get(),
+ SharedMemoryAsHardwareBuffer()));
+ } else {
+ data_fetcher_->StartFetchingDeviceMotionData(
+ SharedMemoryAsHardwareBuffer());
+ }
+
+ is_started_ = true;
+}
+
+void DeviceMotionProvider::CreateAndStartPollingThread() {
+ polling_thread_.reset(
+ new PollingThread("Device Motion poller"));
+
+ if (!polling_thread_->Start()) {
+ LOG(ERROR) << "Failed to start Device Motion data polling thread";
+ return;
+ }
+}
+
+void DeviceMotionProvider::StopFetchingDeviceMotionData() {
+ if (!is_started_)
+ return;
+
+ DCHECK(data_fetcher_);
+
+ if (data_fetcher_->NeedsPolling()) {
+ DCHECK(polling_thread_);
+ polling_thread_->message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&PollingThread::StopPolling,
+ base::Unretained(polling_thread_.get())));
+ } else {
+ data_fetcher_->StopFetchingDeviceMotionData();
+ }
+
+ is_started_ = false;
+}
+
+DeviceMotionHardwareBuffer*
+DeviceMotionProvider::SharedMemoryAsHardwareBuffer() {
+ void* mem = device_motion_shared_memory_.memory();
+ CHECK(mem);
+ return static_cast<DeviceMotionHardwareBuffer*>(mem);
+}
+
+} // namespace content