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