Index: content/browser/gamepad/gamepad_provider.cc |
diff --git a/content/browser/gamepad/gamepad_provider.cc b/content/browser/gamepad/gamepad_provider.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..642e2445a7bbe8fa0d0fc8fa7fd1fcbe2827c101 |
--- /dev/null |
+++ b/content/browser/gamepad/gamepad_provider.cc |
@@ -0,0 +1,145 @@ |
+// Copyright (c) 2011 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 <cmath> |
+#include <set> |
+#include <vector> |
+ |
+#include "base/bind.h" |
+#include "base/logging.h" |
+#include "base/message_loop.h" |
+#include "base/task.h" |
+#include "base/threading/thread.h" |
+#include "base/threading/thread_restrictions.h" |
+#include "content/public/browser/browser_thread.h" |
+#include "content/browser/gamepad/gamepad_provider.h" |
+#include "content/browser/gamepad/data_fetcher.h" |
+#include "content/common/gamepad_messages.h" |
+ |
+#if defined(OS_WIN) |
+#include "content/browser/gamepad/data_fetcher_win.h" |
+#endif |
+ |
+namespace gamepad { |
+ |
+Provider* Provider::instance_ = NULL; |
+ |
+using namespace content; |
+ |
+// Define the default data fetcher that Provider will use if none is supplied. |
+// (PlatformDataFetcher). |
+#if defined(OS_WIN) |
+ |
+typedef DataFetcherWindows PlatformDataFetcher; |
+ |
+#else |
+ |
+class EmptyDataFetcher : public DataFetcher { |
+ public: |
+ void GetGamepadData(WebKit::WebGamepads* pads, bool) { |
+ pads->length = 0; |
+ } |
+}; |
+typedef EmptyDataFetcher PlatformDataFetcher; |
+ |
+#endif |
+ |
+Provider::Provider(DataFetcher* fetcher) |
+ : creator_loop_(MessageLoop::current()->message_loop_proxy()), |
+ provided_fetcher_(fetcher), |
+ devices_changed_(true), |
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { |
+ size_t data_size = sizeof(GamepadHardwareBuffer); |
+ base::SystemMonitor* monitor = base::SystemMonitor::Get(); |
+ if (monitor) |
+ monitor->AddDevicesChangedObserver(this); |
+ gamepad_shared_memory_.CreateAndMapAnonymous(data_size); |
+ GamepadHardwareBuffer* hwbuf = SharedMemoryAsHardwareBuffer(); |
+ memset(hwbuf, 0, sizeof(GamepadHardwareBuffer)); |
+} |
+ |
+Provider::~Provider() { |
+ base::SystemMonitor* monitor = base::SystemMonitor::Get(); |
+ if (monitor) |
+ monitor->RemoveDevicesChangedObserver(this); |
+ Stop(); |
+} |
+ |
+base::SharedMemoryHandle Provider::GetRendererSharedMemoryHandle( |
+ base::ProcessHandle process) { |
+ base::SharedMemoryHandle renderer_handle; |
+ gamepad_shared_memory_.ShareToProcess(process, &renderer_handle); |
+ return renderer_handle; |
+} |
+ |
+void Provider::OnDevicesChanged() { |
+ devices_changed_ = true; |
+} |
+ |
+void Provider::Start() { |
+ DCHECK(MessageLoop::current()->message_loop_proxy() == creator_loop_); |
+ |
+ if (polling_thread_.get()) |
+ return; |
+ |
+ polling_thread_.reset(new base::Thread("Gamepad polling thread")); |
+ if (!polling_thread_->Start()) { |
+ LOG(ERROR) << "Failed to start gamepad polling thread"; |
+ polling_thread_.reset(); |
+ return; |
+ } |
+ |
+ MessageLoop* polling_loop = polling_thread_->message_loop(); |
+ polling_loop->PostTask( |
+ FROM_HERE, |
+ base::Bind(&Provider::DoInitializePollingThread, this)); |
+} |
+ |
+void Provider::Stop() { |
+ DCHECK(MessageLoop::current()->message_loop_proxy() == creator_loop_); |
+ |
+ polling_thread_.reset(); |
+ data_fetcher_.reset(); |
+} |
+ |
+void Provider::DoInitializePollingThread() { |
+ DCHECK(MessageLoop::current() == polling_thread_->message_loop()); |
+ |
+ if (!provided_fetcher_.get()) |
+ provided_fetcher_.reset(new PlatformDataFetcher); |
+ |
+ // Pass ownership of fetcher to provider_. |
+ data_fetcher_.swap(provided_fetcher_); |
+ |
+ // Start polling. |
+ ScheduleDoPoll(); |
+} |
+ |
+void Provider::DoPoll() { |
+ DCHECK(MessageLoop::current() == polling_thread_->message_loop()); |
+ GamepadHardwareBuffer* hwbuf = SharedMemoryAsHardwareBuffer(); |
+ base::subtle::Barrier_AtomicIncrement(&hwbuf->start_marker, 1); |
+ data_fetcher_->GetGamepadData(&hwbuf->buffer, devices_changed_); |
+ base::subtle::Barrier_AtomicIncrement(&hwbuf->end_marker, 1); |
+ devices_changed_ = false; |
+ // Schedule our next interval of polling. |
+ ScheduleDoPoll(); |
+} |
+ |
+void Provider::ScheduleDoPoll() { |
+ DCHECK(MessageLoop::current() == polling_thread_->message_loop()); |
+ |
+ MessageLoop::current()->PostDelayedTask( |
+ FROM_HERE, |
+ base::Bind(&Provider::DoPoll, weak_factory_.GetWeakPtr()), |
+ kDesiredSamplingIntervalMs); |
+} |
+ |
+GamepadHardwareBuffer* Provider::SharedMemoryAsHardwareBuffer() { |
+ void* mem = gamepad_shared_memory_.memory(); |
+ DCHECK(mem); |
+ return static_cast<GamepadHardwareBuffer*>(mem); |
+} |
+ |
+} // namespace gamepad |