diff options
Diffstat (limited to 'chromium/content/browser/device_orientation/device_motion_provider.cc')
-rw-r--r-- | chromium/content/browser/device_orientation/device_motion_provider.cc | 172 |
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 |