15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef CONTENT_BROWSER_GAMEPAD_GAMEPAD_PROVIDER_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CONTENT_BROWSER_GAMEPAD_GAMEPAD_PROVIDER_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback_forward.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/memory/shared_memory.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h" 16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/system_monitor/system_monitor.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/content_export.h" 20010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "third_party/WebKit/public/platform/WebGamepads.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MessageLoopProxy; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Thread; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GamepadDataFetcher; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct GamepadHardwareBuffer; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CONTENT_EXPORT GamepadProvider : 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public base::SystemMonitor::DevicesChangedObserver { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GamepadProvider(); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Manually specifies the data fetcher. Used for testing. 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit GamepadProvider(scoped_ptr<GamepadDataFetcher> fetcher); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~GamepadProvider(); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the shared memory handle of the gamepad data duplicated into the 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // given process. 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SharedMemoryHandle GetSharedMemoryHandleForProcess( 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ProcessHandle renderer_process); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 47010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) void GetCurrentGamepadData(blink::WebGamepads* data); 48010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Pause and resume the background polling thread. Can be called from any 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thread. 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Pause(); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Resume(); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Registers the given closure for calling when the user has interacted with 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the device. This callback will only be issued once. 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RegisterForUserGesture(const base::Closure& closure); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // base::SystemMonitor::DevicesChangedObserver implementation. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnDevicesChanged(base::SystemMonitor::DeviceType type) OVERRIDE; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Initialize(scoped_ptr<GamepadDataFetcher> fetcher); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Method for setting up the platform-specific data fetcher. Takes ownership 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of |fetcher|. 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DoInitializePollingThread(scoped_ptr<GamepadDataFetcher> fetcher); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Method for sending pause hints to the low-level data fetcher. Runs on 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // polling_thread_. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SendPauseHint(bool paused); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Method for polling a GamepadDataFetcher. Runs on the polling_thread_. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DoPoll(); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ScheduleDoPoll(); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 76010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) void OnGamepadConnectionChange(bool connected, 77010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) int index, 78010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const blink::WebGamepad& pad); 79010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) void DispatchGamepadConnectionChange(bool connected, 80010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) int index, 81010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const blink::WebGamepad& pad); 82010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GamepadHardwareBuffer* SharedMemoryAsHardwareBuffer(); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Checks the gamepad state to see if the user has interacted with it. 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void CheckForUserGesture(); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum { kDesiredSamplingIntervalMs = 16 }; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Keeps track of when the background thread is paused. Access to is_paused_ 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // must be guarded by is_paused_lock_. 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Lock is_paused_lock_; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_paused_; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Keep track of when a polling task is schedlued, so as to prevent us from 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // accidentally scheduling more than one at any time, when rapidly toggling 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |is_paused_|. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool have_scheduled_do_poll_; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Lists all observers registered for user gestures, and the thread which 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to issue the callbacks on. Since we always issue the callback on the 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thread which the registration happened, and this class lives on the I/O 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thread, the message loop proxies will normally just be the I/O thread. 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // However, this will be the main thread for unit testing. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Lock user_gesture_lock_; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct ClosureAndThread { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClosureAndThread(const base::Closure& c, 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const scoped_refptr<base::MessageLoopProxy>& m); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~ClosureAndThread(); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Closure closure; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::MessageLoopProxy> message_loop; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::vector<ClosureAndThread> UserGestureObserverVector; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UserGestureObserverVector user_gesture_observers_; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Updated based on notification from SystemMonitor when the system devices 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // have been updated, and this notification is passed on to the data fetcher 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to enable it to avoid redundant (and possibly expensive) is-connected 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tests. Access to devices_changed_ must be guarded by 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // devices_changed_lock_. 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Lock devices_changed_lock_; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool devices_changed_; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) bool ever_had_user_gesture_; 126010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 127010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) class PadState { 128010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) public: 129010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) PadState() { 130010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) SetDisconnected(); 131010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 132010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 133010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) bool Match(const blink::WebGamepad& pad) const; 134010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) void SetPad(const blink::WebGamepad& pad); 135010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) void SetDisconnected(); 136010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) void AsWebGamepad(blink::WebGamepad* pad); 137010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 138010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) bool connected() const { return connected_; } 139010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 140010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) private: 141010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) bool connected_; 142010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) unsigned axes_length_; 143010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) unsigned buttons_length_; 144010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) blink::WebUChar id_[blink::WebGamepad::idLengthCap]; 145010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) blink::WebUChar mapping_[blink::WebGamepad::mappingLengthCap]; 146010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) }; 147010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 148010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Used to detect connections and disconnections. 149010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) scoped_ptr<PadState[]> pad_states_; 150010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 151010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Only used on the polling thread. 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<GamepadDataFetcher> data_fetcher_; 153010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 154010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::Lock shared_memory_lock_; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SharedMemory gamepad_shared_memory_; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Polling is done on this background thread. 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::Thread> polling_thread_; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static GamepadProvider* instance_; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(GamepadProvider); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // CONTENT_BROWSER_GAMEPAD_GAMEPAD_PROVIDER_H_ 168